sphinx_packet/crypto/
mod.rs1use aes::{
16 cipher::{KeyIvInit, StreamCipher},
17 Aes128,
18};
19use digest::{
20 block_buffer::Eager,
21 consts::U256,
22 core_api::{BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore},
23 generic_array::GenericArray,
24 typenum::{IsLess, Le, NonZero},
25 CtOutput, HashMarker,
26};
27use hmac::{Hmac, Mac};
28
29pub use x25519_dalek::PublicKey;
31pub type PrivateKey = x25519_dalek::StaticSecret;
32
33pub const STREAM_CIPHER_KEY_SIZE: usize = 16;
34pub const STREAM_CIPHER_INIT_VECTOR: [u8; 16] = [0u8; 16];
35
36pub type HmacOutput<D> = CtOutput<Hmac<D>>;
38type Aes128Ctr = ctr::Ctr64BE<Aes128>;
39
40pub fn generate_pseudorandom_bytes(
41 key: &[u8; STREAM_CIPHER_KEY_SIZE],
44 iv: &[u8; STREAM_CIPHER_KEY_SIZE],
45 length: usize,
46) -> Vec<u8> {
47 let cipher_key = GenericArray::from_slice(&key[..]);
48 let cipher_nonce = GenericArray::from_slice(&iv[..]);
49
50 let mut cipher = Aes128Ctr::new(cipher_key, cipher_nonce);
52 let mut data = vec![0u8; length];
53 cipher.apply_keystream(&mut data);
54 data
55}
56
57pub fn compute_keyed_hmac<D>(key: &[u8], data: &[u8]) -> HmacOutput<D>
59where
60 D: CoreProxy,
61 D::Core: HashMarker + FixedOutputCore + BufferKindUser<BufferKind = Eager> + Default + Clone,
62 <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
63 Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
64{
65 #[allow(clippy::expect_used)]
66 let mut hmac =
67 Hmac::<D>::new_from_slice(key).expect("HMAC should be able to take key of any size!");
68 hmac.update(data);
69 hmac.finalize()
70}
71
72#[cfg(test)]
73mod generating_pseudorandom_bytes {
74 use super::*;
75
76 #[test]
78 fn it_generates_output_of_size_10000() {
79 let key: [u8; STREAM_CIPHER_KEY_SIZE] =
80 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
81 let iv: [u8; STREAM_CIPHER_KEY_SIZE] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
82
83 let rand_bytes = generate_pseudorandom_bytes(&key, &iv, 10000);
84 assert_eq!(10000, rand_bytes.len());
85 }
86}