saito_core/core/util/
crypto.rs1use crate::core::defs::{PrintForLog, SaitoHash, SaitoPrivateKey, SaitoPublicKey, SaitoSignature};
2use blake3::Hasher;
3use block_modes::BlockMode;
4pub use merkle::MerkleTree;
5use rand::{thread_rng, Rng, SeedableRng};
6use secp256k1::ecdsa;
7pub use secp256k1::{Message, PublicKey, SecretKey, SECP256K1};
8
9pub const PARALLEL_HASH_BYTE_THRESHOLD: usize = 128_000;
12
13pub fn generate_keys() -> (SaitoPublicKey, SaitoPrivateKey) {
40 let (mut secret_key, mut public_key) =
41 SECP256K1.generate_keypair(&mut secp256k1::rand::thread_rng());
42 while public_key.serialize().to_base58().len() != 44 {
43 let keypair_tuple = SECP256K1.generate_keypair(&mut secp256k1::rand::thread_rng());
45 secret_key = keypair_tuple.0;
46 public_key = keypair_tuple.1;
47 }
48 let mut secret_bytes = [0u8; 32];
49 for i in 0..32 {
50 secret_bytes[i] = secret_key[i];
51 }
52 (public_key.serialize(), secret_bytes)
53}
54
55pub fn generate_keypair_from_private_key(slice: &[u8]) -> (SaitoPublicKey, SaitoPrivateKey) {
57 let secret_key = SecretKey::from_slice(slice).unwrap();
58 let public_key = PublicKey::from_secret_key(SECP256K1, &secret_key);
59 let mut secret_bytes = [0u8; 32];
60 for i in 0..32 {
61 secret_bytes[i] = secret_key[i];
62 }
63 (public_key.serialize(), secret_bytes)
64}
65
66pub fn sign_blob<'a>(vbytes: &'a mut Vec<u8>, private_key: &SaitoPrivateKey) -> &'a mut Vec<u8> {
67 let sig = sign(&hash(vbytes.as_ref()), private_key);
68 vbytes.extend(&sig);
69 vbytes
70}
71#[cfg(test)]
72lazy_static::lazy_static! {
73 pub static ref TEST_RNG: tokio::sync::Mutex<rand::rngs::StdRng> = tokio::sync::Mutex::new(create_test_rng());
74}
75
76fn create_test_rng() -> rand::rngs::StdRng {
77 rand::rngs::StdRng::from_seed([0; 32])
78}
79
80pub async fn generate_random_bytes(len: u64) -> Vec<u8> {
81 if len == 0 {
82 let x: Vec<u8> = vec![];
83 return x;
84 }
85 #[cfg(not(test))]
88 {
89 let mut rng = thread_rng();
90 (0..len).map(|_| rng.gen::<u8>()).collect()
91 }
92 #[cfg(test)]
93 {
94 let mut rng = TEST_RNG.lock().await;
96 (0..len).map(|_| rng.gen::<u8>()).collect()
97 }
98}
99
100pub fn hash(data: &[u8]) -> SaitoHash {
101 let mut hasher = Hasher::new();
102 #[cfg(feature = "with-rayon")]
107 {
108 if data.len() > PARALLEL_HASH_BYTE_THRESHOLD {
109 hasher.update_rayon(data);
110 } else {
111 hasher.update(data);
112 }
113 }
114 #[cfg(not(feature = "with-rayon"))]
115 {
116 hasher.update(data);
117 }
118
119 hasher.finalize().into()
120}
121
122pub fn sign(message_bytes: &[u8], private_key: &SaitoPrivateKey) -> SaitoSignature {
123 let hash = hash(message_bytes);
124 let msg = Message::from_slice(&hash).unwrap();
125 let secret = SecretKey::from_slice(private_key).unwrap();
126 let sig = SECP256K1.sign_ecdsa(&msg, &secret);
127 sig.serialize_compact()
128}
129
130pub fn verify(msg: &[u8], sig: &SaitoSignature, public_key: &SaitoPublicKey) -> bool {
131 let hash = hash(msg);
132 verify_signature(&hash, sig, public_key)
133}
134
135pub fn verify_signature(
136 hash: &SaitoHash,
137 sig: &SaitoSignature,
138 public_key: &SaitoPublicKey,
139) -> bool {
140 let m = Message::from_slice(hash);
141 let p = PublicKey::from_slice(public_key);
142 let s = ecdsa::Signature::from_compact(sig);
143 if m.is_err() || p.is_err() || s.is_err() {
144 false
145 } else {
146 SECP256K1
147 .verify_ecdsa(&m.unwrap(), &s.unwrap(), &p.unwrap())
148 .is_ok()
149 }
150}
151
152pub fn is_valid_public_key(key: &SaitoPublicKey) -> bool {
153 let result = PublicKey::from_slice(key);
154 result.is_ok()
155}
156
157#[cfg(test)]
158mod tests {
159
160 use crate::core::defs::SaitoPrivateKey;
161
162 use super::*;
163
164 #[test]
177 fn keypair_restoration_from_private_key_test() {
178 let (public_key, private_key) = generate_keys();
179 let (public_key2, private_key2) = generate_keypair_from_private_key(&private_key);
180 assert_eq!(public_key, public_key2);
181 assert_eq!(private_key, private_key2);
182 }
183
184 #[test]
185 fn sign_message_test() {
186 let msg = <[u8; 32]>::from_hex(
187 "5a16ffa08e5fc440772ee962c1d730041f12c7008a6e5c704d13dfd3d1906e0d",
188 )
189 .unwrap();
190
191 let hex = hash(msg.as_slice());
192
193 let hex_str = hex.to_hex();
194 assert_eq!(
195 hex_str,
196 "f8b1f22222bdbd2e0bce06707a51f5fffa0753b11483c330e3bfddaf5bacabd6"
197 );
198
199 let private_key: SaitoPrivateKey = <[u8; 32]>::from_hex(
200 "4a16ffa08e5fc440772ee962c1d730041f12c7008a6e5c704d13dfd3d1905e0d",
201 )
202 .unwrap();
203
204 let (public, _) = generate_keypair_from_private_key(&private_key);
205
206 let signature = sign(&msg, &private_key);
207 assert_eq!(signature.len(), 64);
208 let hex_str = signature.to_hex();
209 assert_eq!(hex_str, "11c0e19856726c42c8ac3ec8e469057f5f8a882f7206377525db00899835b03f6ec3010d19534a5703dd9b1004b4f0e31d19582cdd5aec794541d0d0f339db7c");
210
211 let result = verify(&msg, &signature, &public);
212 assert!(result);
213 }
214
215 #[test]
216 fn verify_message_test() {
217 let msg = <[u8; 32]>::from_hex(
218 "dcf6cceb74717f98c3f7239459bb36fdcd8f350eedbfccfbebf7c0b0161fcd8b",
219 )
220 .unwrap();
221
222 let (public_key, private_key) = generate_keys();
223 let (public_key2, private_key2) = generate_keys();
224
225 assert_eq!(verify(&msg, &sign(&msg, &private_key), &public_key), true);
226 assert_eq!(verify(&msg, &sign(&msg, &private_key2), &public_key2), true);
227 assert_eq!(verify(&msg, &sign(&msg, &private_key), &public_key2), false);
228 assert_eq!(verify(&msg, &sign(&msg, &private_key2), &public_key), false);
229 }
230
231 #[test]
232 fn is_valid_public_key_test() {
233 let (public_key, _) = generate_keys();
234 assert!(is_valid_public_key(&public_key));
235
236 let public_key: SaitoPublicKey = [0; 33];
237 assert!(!is_valid_public_key(&public_key));
238
239 let public_key: SaitoPublicKey = [u8::try_from('a').unwrap(); 33];
240 assert!(!is_valid_public_key(&public_key));
241 }
242}