paseto_v1/core/
pie_wrap.rs1use alloc::vec::Vec;
2
3use cipher::StreamCipher;
4use digest::Mac;
5use generic_array::GenericArray;
6use generic_array::sequence::Split;
7use generic_array::typenum::U48;
8use paseto_core::PasetoError;
9use paseto_core::paserk::PieWrapVersion;
10
11use super::{LocalKey, V1};
12
13impl LocalKey {
14 fn wrap_keys(&self, nonce: &[u8; 32]) -> (ctr::Ctr64BE<aes::Aes256>, hmac::Hmac<sha2::Sha384>) {
15 use cipher::KeyIvInit;
16 use digest::Mac;
17
18 let (ek, n2) = kdf(&self.0, 0x80, nonce).split();
19 let ak = kdf(&self.0, 0x81, nonce);
20
21 let cipher = ctr::Ctr64BE::<aes::Aes256>::new(&ek, &n2);
22 let mac = hmac::Hmac::new_from_slice(&ak[..32]).expect("key should be valid");
23 (cipher, mac)
24 }
25}
26
27impl PieWrapVersion for V1 {
28 fn pie_wrap_key(
29 header: &'static str,
30 wrapping_key: &super::LocalKey,
31 mut key_data: Vec<u8>,
32 ) -> Result<Vec<u8>, PasetoError> {
33 let mut nonce = [0u8; 32];
34 getrandom::fill(&mut nonce).map_err(|_| PasetoError::CryptoError)?;
35
36 let (mut cipher, mut mac) = wrapping_key.wrap_keys(&nonce);
37
38 cipher.apply_keystream(&mut key_data);
39 auth(&mut mac, header, &nonce, &key_data);
40
41 let mut out = Vec::with_capacity(80 + key_data.len());
42 out.extend_from_slice(&mac.finalize().into_bytes());
43 out.extend_from_slice(&nonce);
44 out.extend_from_slice(&key_data);
45 Ok(out)
46 }
47
48 fn pie_unwrap_key<'key>(
49 header: &'static str,
50 wrapping_key: &super::LocalKey,
51 key_data: &'key mut [u8],
52 ) -> Result<&'key [u8], PasetoError> {
53 let (tag, ciphertext) = key_data
54 .split_first_chunk_mut()
55 .ok_or(PasetoError::InvalidKey)?;
56 let (nonce, ciphertext) = ciphertext
57 .split_first_chunk_mut()
58 .ok_or(PasetoError::InvalidKey)?;
59 let tag: &[u8; 48] = tag;
60
61 let (mut cipher, mut mac) = wrapping_key.wrap_keys(nonce);
62 auth(&mut mac, header, nonce, ciphertext);
63 mac.verify(tag.into())
64 .map_err(|_| PasetoError::CryptoError)?;
65
66 cipher.apply_keystream(ciphertext);
67
68 Ok(ciphertext)
69 }
70}
71
72fn kdf(key: &[u8], sep: u8, nonce: &[u8]) -> GenericArray<u8, U48> {
73 let mut mac = hmac::Hmac::<sha2::Sha384>::new_from_slice(key).expect("key should be valid");
74 mac.update(&[sep]);
75 mac.update(nonce);
76 mac.finalize().into_bytes()
77}
78
79fn auth(
80 mac: &mut hmac::Hmac<sha2::Sha384>,
81 encoding: &'static str,
82 nonce: &[u8],
83 ciphertext: &[u8],
84) {
85 mac.update(b"k1");
86 mac.update(encoding.as_bytes());
87 mac.update(nonce);
88 mac.update(ciphertext);
89}