1use crate::{KeyPair, RandomKeyPairGenerator, SecretKey, SECP256K1};
26use std::io;
27use subtle::ConstantTimeEq;
28
29pub const KEY_LENGTH: usize = 32;
30pub const KEY_ITERATIONS: usize = 10240;
31pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
32
33#[derive(Debug, thiserror::Error)]
34pub enum Error {
35 #[error("secp256k1 error: {0}")]
36 Secp(#[from] secp256k1::Error),
37 #[error("i/o error: {0}")]
38 Io(#[from] io::Error),
39 #[error("invalid message")]
40 InvalidMessage,
41 #[error("aes error")]
42 Aes,
43}
44
45pub mod ecdh {
47 use super::{Error, SecretKey, SECP256K1};
48 use secp256k1::{self, ecdh, key};
49
50 pub fn agree<S, P>(secret: &S, public: &P) -> Result<S, Error>
52 where
53 S: SecretKey,
54 P: AsRef<[u8]>,
55 {
56 let context = &SECP256K1;
57 let pdata = {
58 let mut temp = [4u8; 65];
59 let pub_bytes = public.as_ref();
60 if pub_bytes.len() < 64 {
61 return Err(Error::Secp(secp256k1::Error::InvalidPublicKey));
62 }
63 (&mut temp[1..65]).copy_from_slice(&pub_bytes[0..64]);
64 temp
65 };
66
67 let publ = key::PublicKey::from_slice(context, &pdata)?;
68 let sec = key::SecretKey::from_slice(context, secret.as_ref())?;
69 let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec);
70
71 S::from_unsafe_slice(&shared[0..32])
72 .map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey))
73 }
74}
75
76pub mod ecies {
78 use super::{
79 ecdh, is_equal, Error, KeyPair, RandomKeyPairGenerator, SecretKey,
80 };
81 use cfx_types::H128;
82 use hmac::{Hmac, Mac};
83 use sha2::{Digest, Sha256};
84
85 type HmacSha256 = Hmac<Sha256>;
86
87 pub fn encrypt<G, KP, S, P>(
92 generator: &mut G, public: &P, auth_data: &[u8], plain: &[u8],
93 ) -> Result<Vec<u8>, Error>
94 where
95 G: RandomKeyPairGenerator<KeyPair = KP, Error = std::io::Error>,
96 KP: KeyPair<Secret = S, Public = P>,
97 S: SecretKey,
98 P: AsRef<[u8]>,
99 {
100 let r = generator.generate()?;
101 let z = ecdh::agree(r.secret(), public)?;
102 let mut key = [0u8; 32];
103 kdf(&z, &[0u8; 0], &mut key);
104
105 let ekey = &key[0..16];
106 let mkey = Sha256::digest(&key[16..32]);
107
108 let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32];
109 msg[0] = 0x04u8;
110 {
111 let msgd = &mut msg[1..];
112 let pub_bytes = r.public().as_ref();
113 if pub_bytes.len() < 64 {
114 return Err(Error::InvalidMessage);
115 }
116 msgd[0..64].copy_from_slice(&pub_bytes[0..64]);
117 let iv = H128::random();
118 msgd[64..80].copy_from_slice(iv.as_bytes());
119 {
120 let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
121 super::aes::encrypt_128_ctr(
122 ekey,
123 iv.as_bytes(),
124 plain,
125 cipher,
126 )?;
127 }
128 let mut hmac = HmacSha256::new_from_slice(mkey.as_slice())
129 .expect("output of Sha256 has invalid length");
130 {
131 let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
132 hmac.update(cipher_iv);
133 }
134 hmac.update(auth_data);
135 let sig = hmac.finalize().into_bytes();
136 msgd[(64 + 16 + plain.len())..].copy_from_slice(&sig);
137 }
138 Ok(msg)
139 }
140
141 pub fn decrypt<S>(
144 secret: &S, auth_data: &[u8], encrypted: &[u8],
145 ) -> Result<Vec<u8>, Error>
146 where S: SecretKey {
147 let meta_len = 1 + 64 + 16 + 32;
148 if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 {
149 return Err(Error::InvalidMessage); }
151
152 let e = &encrypted[1..];
153 let mut pub_array = [0u8; 64];
155 pub_array.copy_from_slice(&e[0..64]);
156 let z = ecdh::agree(secret, &pub_array)?;
157 let mut key = [0u8; 32];
158 kdf(&z, &[0u8; 0], &mut key);
159
160 let ekey = &key[0..16];
161 let mkey = Sha256::digest(&key[16..32]);
162
163 let clen = encrypted.len() - meta_len;
164 let cipher_with_iv = &e[64..(64 + 16 + clen)];
165 let cipher_iv = &cipher_with_iv[0..16];
166 let cipher_no_iv = &cipher_with_iv[16..];
167 let msg_mac = &e[(64 + 16 + clen)..];
168
169 let mut hmac = HmacSha256::new_from_slice(mkey.as_slice())
171 .expect("output of Sha256 has invalid length");
172 hmac.update(cipher_with_iv);
173 hmac.update(auth_data);
174 let mac = hmac.finalize().into_bytes();
175
176 if !is_equal(mac.as_slice(), msg_mac) {
177 return Err(Error::InvalidMessage);
178 }
179
180 let mut msg = vec![0u8; clen];
181 super::aes::decrypt_128_ctr(
182 ekey,
183 cipher_iv,
184 cipher_no_iv,
185 &mut msg[..],
186 )?;
187 Ok(msg)
188 }
189
190 fn kdf<S: SecretKey>(secret: &S, s1: &[u8], dest: &mut [u8]) {
191 let mut ctr = 1u32;
195 let mut written = 0usize;
196 while written < dest.len() {
197 let mut hasher = Sha256::new();
198 let ctrs = [
199 (ctr >> 24) as u8,
200 (ctr >> 16) as u8,
201 (ctr >> 8) as u8,
202 ctr as u8,
203 ];
204 hasher.update(&ctrs);
205 hasher.update(secret.as_ref());
206 hasher.update(s1);
207 let d = hasher.finalize();
208 dest[written..(written + 32)].copy_from_slice(&d);
209 written += 32;
210 ctr += 1;
211 }
212 }
213}
214
215pub mod aes {
216 use super::Error;
217 use aes::Aes128;
218 use cbc::{cipher::BlockDecryptMut, Decryptor};
219 use ctr::{
220 cipher::{KeyIvInit as CtrKeyIvInit, StreamCipher},
221 Ctr128BE,
222 };
223
224 type Aes128Ctr = Ctr128BE<Aes128>;
225 type Aes128CbcDec = Decryptor<Aes128>;
226
227 pub fn encrypt_128_ctr(
228 key: &[u8], iv: &[u8], plain: &[u8], ciphertext: &mut [u8],
229 ) -> Result<(), Error> {
230 let mut cipher = Aes128Ctr::new(key.into(), iv.into());
231 ciphertext[..plain.len()].copy_from_slice(plain);
232 cipher
233 .try_apply_keystream(ciphertext)
234 .map_err(|_| Error::Aes)?;
235 Ok(())
236 }
237
238 pub fn decrypt_128_ctr(
239 key: &[u8], iv: &[u8], ciphertext: &[u8], plain: &mut [u8],
240 ) -> Result<(), Error> {
241 let mut cipher = Aes128Ctr::new(key.into(), iv.into());
242 plain[..ciphertext.len()].copy_from_slice(ciphertext);
243 cipher.try_apply_keystream(plain).map_err(|_| Error::Aes)?;
244 Ok(())
245 }
246
247 pub fn decrypt_128_cbc<'a>(
248 key: &[u8], iv: &[u8], data: &[u8], dest: &'a mut [u8],
249 ) -> Result<&'a [u8], String> {
250 if key.len() != 16 {
251 return Err("Key must be exactly 16 bytes for AES-128".to_string());
252 }
253
254 if iv.len() != 16 {
255 return Err("IV must be exactly 16 bytes".to_string());
256 }
257
258 if data.is_empty() {
259 return Err("Data cannot be empty".to_string());
260 }
261
262 if data.len() % 16 != 0 {
263 return Err(
264 "Data length must be a multiple of 16 bytes".to_string()
265 );
266 }
267
268 let decryptor = Aes128CbcDec::new(key.into(), iv.into());
270 dest[..data.len()].copy_from_slice(data);
271
272 let plaintext = decryptor
274 .decrypt_padded_mut::<cbc::cipher::block_padding::Pkcs7>(dest)
275 .map_err(|e| format!("Decryption failed: {}", e))?;
276
277 Ok(plaintext)
278 }
279}
280
281pub mod keccak {
282 use tiny_keccak::{Hasher, Keccak};
283
284 pub trait Keccak256<T> {
285 fn keccak256(&self) -> T
286 where T: Sized;
287 }
288
289 impl<T> Keccak256<[u8; 32]> for T
290 where T: AsRef<[u8]>
291 {
292 fn keccak256(&self) -> [u8; 32] {
293 let mut keccak = Keccak::v256();
294 let mut result = [0u8; 32];
295 keccak.update(self.as_ref());
296 keccak.finalize(&mut result);
297 result
298 }
299 }
300}
301
302pub mod scrypt {
303 use super::{KEY_LENGTH, KEY_LENGTH_AES};
304 use scrypt::{errors, scrypt, Params};
305
306 pub fn derive_key(
307 pass: &[u8], salt: &[u8], n: u32, p: u32, r: u32,
308 ) -> Result<(Vec<u8>, Vec<u8>), String> {
309 let log_n = (32 - n.leading_zeros() - 1) as u8;
311 if log_n as u32 >= r * 16 {
312 return Err(errors::InvalidParams.to_string());
313 }
314
315 if p as u64 > ((u32::MAX as u64 - 1) * 32) / (128 * (r as u64)) {
316 return Err(errors::InvalidParams.to_string());
317 }
318
319 let mut derived_key = vec![0u8; KEY_LENGTH];
320 let scrypt_params =
321 Params::new(log_n, r, p, KEY_LENGTH).map_err(|e| e.to_string())?;
322 scrypt(pass, salt, &scrypt_params, &mut derived_key)
323 .map_err(|e| e.to_string())?;
324 let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
325 let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
326 Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec()))
327 }
328}
329
330pub mod pbkdf2 {
331 use super::{KEY_LENGTH, KEY_LENGTH_AES};
332 use hmac;
333 use pbkdf2;
334 use sha2;
335
336 pub struct Salt<'a>(pub &'a [u8]);
337 pub struct Secret<'a>(pub &'a [u8]);
338
339 pub fn sha256(
340 iter: u32, salt: Salt<'_>, sec: Secret<'_>, out: &mut [u8; 32],
341 ) -> Result<(), String> {
342 pbkdf2::pbkdf2::<hmac::Hmac<sha2::Sha256>>(sec.0, salt.0, iter, out)
343 .map_err(|e| e.to_string())
344 }
345
346 pub fn sha512(
347 iter: u32, salt: Salt<'_>, sec: Secret<'_>, out: &mut [u8; 64],
348 ) -> Result<(), String> {
349 pbkdf2::pbkdf2::<hmac::Hmac<sha2::Sha512>>(sec.0, salt.0, iter, out)
350 .map_err(|e| e.to_string())
351 }
352
353 pub fn derive_key_iterations(
354 password: &[u8], salt: &[u8], c: u32,
355 ) -> Result<(Vec<u8>, Vec<u8>), String> {
356 let mut derived_key = [0u8; KEY_LENGTH];
357 sha256(c, Salt(salt), Secret(password), &mut derived_key)?;
358 let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
359 let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
360 Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec()))
361 }
362}
363
364pub mod digest {
365 use std::{marker::PhantomData, ops::Deref};
366
367 use digest::generic_array::{
368 typenum::{U20, U32, U64},
369 GenericArray,
370 };
371 use ripemd;
372 use sha2::Digest as RDigest;
373
374 pub struct Digest<T>(InnerDigest, PhantomData<T>);
376
377 enum InnerDigest {
378 Sha256(GenericArray<u8, U32>),
379 Sha512(GenericArray<u8, U64>),
380 Ripemd160(GenericArray<u8, U20>),
381 }
382
383 impl<T> Deref for Digest<T> {
384 type Target = [u8];
385
386 fn deref(&self) -> &Self::Target {
387 match self.0 {
388 InnerDigest::Sha256(ref d) => &d[..],
389 InnerDigest::Sha512(ref d) => &d[..],
390 InnerDigest::Ripemd160(ref d) => &d[..],
391 }
392 }
393 }
394
395 pub fn sha256(data: &[u8]) -> Digest<Sha256> {
397 let mut hasher = Hasher::sha256();
398 hasher.update(data);
399 hasher.finish()
400 }
401
402 pub fn sha512(data: &[u8]) -> Digest<Sha512> {
404 let mut hasher = Hasher::sha512();
405 hasher.update(data);
406 hasher.finish()
407 }
408
409 pub fn ripemd160(data: &[u8]) -> Digest<Ripemd160> {
411 let mut hasher = Hasher::ripemd160();
412 hasher.update(data);
413 hasher.finish()
414 }
415
416 #[derive(Debug)]
417 pub enum Sha256 {}
418 #[derive(Debug)]
419 pub enum Sha512 {}
420 #[derive(Debug)]
421 pub enum Ripemd160 {}
422
423 pub struct Hasher<T>(Inner, PhantomData<T>);
425
426 enum Inner {
427 Sha256(sha2::Sha256),
428 Sha512(sha2::Sha512),
429 Ripemd160(ripemd::Ripemd160),
430 }
431
432 impl Hasher<Sha256> {
433 pub fn sha256() -> Hasher<Sha256> {
434 Hasher(Inner::Sha256(sha2::Sha256::default()), PhantomData)
435 }
436 }
437
438 impl Hasher<Sha512> {
439 pub fn sha512() -> Hasher<Sha512> {
440 Hasher(Inner::Sha512(sha2::Sha512::default()), PhantomData)
441 }
442 }
443
444 impl Hasher<Ripemd160> {
445 pub fn ripemd160() -> Hasher<Ripemd160> {
446 Hasher(Inner::Ripemd160(ripemd::Ripemd160::default()), PhantomData)
447 }
448 }
449
450 impl<T> Hasher<T> {
451 pub fn update(&mut self, data: &[u8]) {
452 match self.0 {
453 Inner::Sha256(ref mut ctx) => ctx.update(data),
454 Inner::Sha512(ref mut ctx) => ctx.update(data),
455 Inner::Ripemd160(ref mut ctx) => ctx.update(data),
456 }
457 }
458
459 pub fn finish(self) -> Digest<T> {
460 match self.0 {
461 Inner::Sha256(ctx) => {
462 Digest(InnerDigest::Sha256(ctx.finalize()), PhantomData)
463 }
464 Inner::Sha512(ctx) => {
465 Digest(InnerDigest::Sha512(ctx.finalize()), PhantomData)
466 }
467 Inner::Ripemd160(ctx) => {
468 Digest(InnerDigest::Ripemd160(ctx.finalize()), PhantomData)
469 }
470 }
471 }
472 }
473}
474
475pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec<u8> {
476 let mut mac = vec![0u8; KEY_LENGTH_AES + cipher_text.len()];
477 mac[0..KEY_LENGTH_AES].copy_from_slice(derived_left_bits);
478 mac[KEY_LENGTH_AES..cipher_text.len() + KEY_LENGTH_AES]
479 .copy_from_slice(cipher_text);
480 mac
481}
482
483pub fn is_equal(a: &[u8], b: &[u8]) -> bool { a.ct_eq(b).into() }