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