prople_crypto/ecdh/
keypair.rs

1//! `keypair` module used to generate primary [`KeyPair`] data format
2use core::fmt;
3
4use rst_common::with_cryptography::hex;
5use rst_common::with_cryptography::rand::{rngs::adapter::ReseedingRng, SeedableRng};
6use rst_common::with_cryptography::rand_chacha::{rand_core::OsRng, ChaCha20Core};
7use rst_common::with_cryptography::x25519_dalek::{PublicKey as ECDHPublicKey, StaticSecret};
8
9use crate::errors::CommonError;
10use crate::types::{ByteHex, BytesValue, Hexer, Value};
11
12use crate::keysecure::builder::Builder;
13use crate::keysecure::types::errors::KeySecureError;
14use crate::keysecure::types::ToKeySecure;
15use crate::keysecure::types::{ContextOptions, Password};
16use crate::keysecure::KeySecure;
17
18use crate::ecdh::pubkey::PublicKey;
19use crate::ecdh::secret::Secret;
20use crate::ecdh::types::errors::*;
21use crate::ecdh::types::PrivateKeyBytes;
22
23/// `KeyPair` used to store [`StaticSecret`] and implement [`fmt::Debug`] and [`std::clone::Clone`]
24///
25/// This object provides methods to generate [`PublicKey`], [`Secret`], and [`ECDHPrivateKeyBytes`].
26/// Besides of it, this object also implement [`ToKeySecure`]
27#[derive(Clone)]
28pub struct KeyPair {
29    secret: StaticSecret,
30}
31
32impl fmt::Debug for KeyPair {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("KeyPairs")
35            .field("secret_in_hex", &self.to_hex().hex())
36            .finish()
37    }
38}
39
40impl KeyPair {
41    pub fn generate() -> Self {
42        let prng = ChaCha20Core::from_entropy();
43        let mut reseeding_rng = ReseedingRng::new(prng, 0, OsRng);
44        let secret = StaticSecret::random_from_rng(&mut reseeding_rng);
45        Self { secret }
46    }
47
48    pub fn pub_key(&self) -> PublicKey {
49        PublicKey::new(ECDHPublicKey::from(&self.secret))
50    }
51
52    pub fn secret(self, peer_hex: ByteHex) -> Secret {
53        Secret::new(self.secret, peer_hex)
54    }
55
56    pub fn to_hex(&self) -> ByteHex {
57        ByteHex::from(hex::encode(self.to_bytes().bytes()))
58    }
59
60    pub fn from_hex(val: String) -> Result<Self, EcdhError> {
61        let decoded = hex::decode(val)
62            .map_err(|err| EcdhError::Common(CommonError::ParseHexError(err.to_string())))?;
63
64        let valid_bytes: Result<[u8; 32], _> = decoded.try_into();
65        valid_bytes
66            .map(|val| Self {
67                secret: StaticSecret::from(val),
68            })
69            .map_err(|_| EcdhError::ParseBytesError("unable to parse decode bytes".to_string()))
70    }
71
72    pub fn to_bytes(&self) -> PrivateKeyBytes {
73        PrivateKeyBytes::from(self.secret.to_bytes())
74    }
75
76    pub fn from_bytes(val: PrivateKeyBytes) -> Result<Self, CommonError> {
77        let private_key_bytes = val.get()?;
78        Ok(Self {
79            secret: StaticSecret::from(private_key_bytes),
80        })
81    }
82}
83
84impl ToKeySecure for KeyPair {
85    fn to_keysecure(&self, password: Password) -> Result<KeySecure, KeySecureError> {
86        let priv_key_hex = self.to_hex();
87
88        let keysecure_builder = Builder::new(ContextOptions::X25519, password);
89        let keysecure = keysecure_builder.secure(priv_key_hex.hex())?;
90
91        Ok(keysecure)
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn test_gen_pub_key_from_hex() {
101        let keypair = KeyPair::generate();
102        let pubkey = keypair.pub_key();
103
104        let pubkeyhex = pubkey.to_hex();
105        let pubkey_decode = PublicKey::from_hex(pubkeyhex);
106        assert!(!pubkey_decode.is_err());
107        assert_eq!(pubkey_decode.unwrap(), pubkey)
108    }
109
110    #[test]
111    fn test_gen_pub_key_from_hex_error() {
112        let given = b"test";
113        let given_hex = hex::encode(given);
114
115        let pubkey_decode = PublicKey::from_hex(ByteHex::from(given_hex));
116        assert!(pubkey_decode.is_err());
117        assert!(matches!(
118            pubkey_decode,
119            Err(EcdhError::ParsePublicKeyError(_))
120        ))
121    }
122
123    #[test]
124    fn test_gen_shared_secret() {
125        let keypair_alice = KeyPair::generate();
126        let keypair_bob = KeyPair::generate();
127        let pubkey_alice = keypair_alice.pub_key();
128        let pubkey_bob = keypair_bob.pub_key();
129
130        let public_alice_hex = pubkey_alice.to_hex();
131        let public_bob_hex = pubkey_bob.to_hex();
132
133        let secret_alice = keypair_alice.secret(public_bob_hex);
134        let secret_bob = keypair_bob.secret(public_alice_hex);
135
136        let shared_secret_alice_blake3 = secret_alice.to_blake3();
137        let shared_secret_bob_blake3 = secret_bob.to_blake3();
138
139        assert!(!&shared_secret_alice_blake3.is_err());
140        assert!(!&shared_secret_bob_blake3.is_err());
141
142        assert_eq!(
143            shared_secret_alice_blake3.unwrap(),
144            shared_secret_bob_blake3.unwrap()
145        )
146    }
147
148    #[test]
149    fn test_serialize_deserialize() {
150        let keypair = KeyPair::generate();
151        let pubkey = keypair.pub_key();
152        let pubkey_hex = pubkey.to_hex();
153
154        let bytes_serialized = keypair.to_bytes();
155        let keypair_from_bytes = KeyPair::from_bytes(bytes_serialized);
156        let pubkey_from_bytes = keypair_from_bytes.unwrap().pub_key();
157        let pubkey_from_bytes_hex = pubkey_from_bytes.to_hex();
158
159        assert_eq!(pubkey_hex, pubkey_from_bytes_hex)
160    }
161
162    #[test]
163    fn test_to_keyseucre() {
164        let keypair = KeyPair::generate();
165        let try_keysecure = keypair.to_keysecure(Password::from("test".to_string()));
166        assert!(!try_keysecure.is_err());
167
168        let keysecure = try_keysecure.unwrap();
169        let keysecure_json = keysecure.to_json();
170        assert!(!keysecure_json.is_err());
171    }
172
173    #[test]
174    fn test_secret_from_hex() {
175        let keypair = KeyPair::generate();
176        let pubkey = keypair.pub_key();
177        let pubkey_hex = pubkey.to_hex();
178
179        let keypair_hex = keypair.to_hex();
180        let keypair_from_hex = KeyPair::from_hex(keypair_hex.hex());
181        assert!(!keypair_from_hex.is_err());
182
183        let keypair_generated = keypair_from_hex.unwrap();
184        let pubkey_generated = keypair_generated.pub_key();
185        let pubkey_generated_hex = pubkey_generated.to_hex();
186        assert_eq!(pubkey_hex, pubkey_generated_hex)
187    }
188}