1use alloc::boxed::Box;
2use alloc::vec::Vec;
3
4use cipher::StreamCipher;
5use generic_array::sequence::Split;
6use hmac::Mac;
7use paseto_core::PasetoError;
8use paseto_core::key::HasKey;
9use paseto_core::paserk::{PkeSealingVersion, PkeUnsealingVersion};
10use paseto_core::version::{PkePublic, PkeSecret};
11use rsa::BigUint;
12use rsa::hazmat::{rsa_decrypt_and_check, rsa_encrypt};
13use rsa::traits::PublicKeyParts;
14use sha2::Digest;
15use zerocopy::IntoBytes;
16
17use super::{LocalKey, V1};
18
19#[derive(Clone)]
20pub struct PkeSecretKey(rsa::RsaPrivateKey);
21
22#[derive(Clone)]
23pub struct PkePublicKey(rsa::RsaPublicKey);
24
25impl HasKey<PkePublic> for V1 {
26 type Key = PkePublicKey;
27 fn decode(bytes: &[u8]) -> Result<PkePublicKey, PasetoError> {
28 use rsa::pkcs8::spki::DecodePublicKey;
29
30 let key = if let Ok(key) = rsa::RsaPublicKey::from_public_key_der(bytes) {
31 key
32 } else {
33 let s = str::from_utf8(bytes).map_err(|_| PasetoError::InvalidKey)?;
34 rsa::RsaPublicKey::from_public_key_pem(s).map_err(|_| PasetoError::InvalidKey)?
35 };
36
37 if key.n().bits() != 4096 {
38 return Err(PasetoError::InvalidKey);
39 }
40
41 Ok(PkePublicKey(key))
42 }
43 fn encode(key: &PkePublicKey) -> Box<[u8]> {
44 use rsa::pkcs8::spki::EncodePublicKey;
45
46 key.0
47 .to_public_key_der()
48 .expect("encoding to spki der should succeed")
49 .into_vec()
50 .into_boxed_slice()
51 }
52}
53
54impl HasKey<PkeSecret> for V1 {
55 type Key = PkeSecretKey;
56 fn decode(bytes: &[u8]) -> Result<PkeSecretKey, PasetoError> {
57 use rsa::pkcs1::DecodeRsaPrivateKey;
58
59 let key = if let Ok(key) = rsa::RsaPrivateKey::from_pkcs1_der(bytes) {
60 key
61 } else {
62 let s = str::from_utf8(bytes).map_err(|_| PasetoError::InvalidKey)?;
63 rsa::RsaPrivateKey::from_pkcs1_pem(s).map_err(|_| PasetoError::InvalidKey)?
64 };
65
66 if key.n().bits() != 4096 {
67 return Err(PasetoError::InvalidKey);
68 }
69
70 Ok(PkeSecretKey(key))
71 }
72 fn encode(key: &PkeSecretKey) -> Box<[u8]> {
73 use rsa::pkcs1::EncodeRsaPrivateKey;
74
75 key.0
76 .to_pkcs1_der()
77 .expect("encoding to pkcs1 der should succeed")
78 .to_bytes()
79 .to_vec()
80 .into_boxed_slice()
81 }
82}
83
84impl PkeSealingVersion for V1 {
85 fn seal_key(sealing_key: &PkePublicKey, key: LocalKey) -> Result<Box<[u8]>, PasetoError> {
86 use cipher::KeyIvInit;
87
88 let mut r = vec![0u8; 512];
89 getrandom::fill(&mut r).map_err(|_| PasetoError::CryptoError)?;
90 r[0] &= 0x7f;
91 r[0] |= 0x40;
92 let c = rsa_encrypt(&sealing_key.0, &BigUint::from_bytes_be(&r))
93 .map_err(|_| PasetoError::CryptoError)?
94 .to_bytes_be();
95
96 let k = sha2::Sha384::digest(&c);
97
98 let mut mac =
99 hmac::Hmac::<sha2::Sha384>::new_from_slice(&k[..]).expect("hmac accepts all key sizes");
100 mac.update(b"\x01k1.seal.");
101 mac.update(r.as_bytes());
102 let (ek, n) = mac.finalize_reset().into_bytes().split();
103
104 mac.update(b"\x02k1.seal.");
105 mac.update(r.as_bytes());
106 let ak = mac.finalize().into_bytes();
107
108 let mut edk = key.0;
109 ctr::Ctr64BE::<aes::Aes256>::new(&ek, &n).apply_keystream(&mut edk);
110
111 let mut tag = hmac::Hmac::<sha2::Sha384>::new_from_slice(&ak).unwrap();
112 tag.update(b"k1.seal.");
113 tag.update(c.as_bytes());
114 tag.update(&edk);
115 let tag = tag.finalize().into_bytes();
116
117 let mut output = Vec::with_capacity(48 + 32 + 512);
118 output.extend_from_slice(&tag);
119 output.extend_from_slice(&edk);
120 output.extend_from_slice(c.as_bytes());
121
122 Ok(output.into_boxed_slice())
123 }
124}
125
126impl PkeUnsealingVersion for V1 {
127 fn unseal_key(
128 unsealing_key: &PkeSecretKey,
129 mut key_data: Box<[u8]>,
130 ) -> Result<LocalKey, PasetoError> {
131 use cipher::KeyIvInit;
132
133 let (tag, key_data) = key_data
134 .split_first_chunk_mut::<48>()
135 .ok_or(PasetoError::InvalidKey)?;
136 let (edk, c) = key_data
137 .split_last_chunk_mut::<512>()
138 .ok_or(PasetoError::InvalidKey)?;
139
140 let c: &[u8] = &*c;
141 let edk: &mut [u8; 32] = edk.try_into().map_err(|_| PasetoError::InvalidKey)?;
142
143 let r = rsa_decrypt_and_check::<rsa::rand_core::OsRng>(
144 &unsealing_key.0,
145 None,
146 &BigUint::from_bytes_be(c),
147 )
148 .map_err(|_| PasetoError::CryptoError)?
149 .to_bytes_be();
150
151 let k = sha2::Sha384::digest(c);
152
153 let mut mac =
154 hmac::Hmac::<sha2::Sha384>::new_from_slice(&k[..]).expect("hmac accepts all key sizes");
155
156 mac.update(b"\x02k1.seal.");
157 mac.update(r.as_bytes());
158 let ak = mac.finalize_reset().into_bytes();
159
160 let mut t2 = hmac::Hmac::<sha2::Sha384>::new_from_slice(&ak).unwrap();
161 t2.update(b"k1.seal.");
162 t2.update(c);
163 t2.update(edk);
164
165 t2.verify((&*tag).into())
167 .map_err(|_| PasetoError::CryptoError)?;
168
169 mac.update(b"\x01k1.seal.");
170 mac.update(r.as_bytes());
171 let (ek, n) = mac.finalize().into_bytes().split();
172
173 ctr::Ctr64BE::<aes::Aes256>::new(&ek, &n).apply_keystream(edk);
174
175 Ok(LocalKey(*edk))
176 }
177}