jwt_simple/algorithms/jwe/
rsa_oaep.rs1#[cfg(any(feature = "pure-rust", target_arch = "wasm32", target_arch = "wasm64"))]
9use superboring as boring;
10
11use boring::pkey::{Private, Public};
12use boring::rsa::{Padding, Rsa};
13use serde::{de::DeserializeOwned, Serialize};
14
15use crate::claims::*;
16use crate::error::*;
17use crate::jwe_header::JWEHeader;
18use crate::jwe_token::{DecryptionOptions, EncryptionOptions, JWEToken, JWETokenMetadata};
19
20const MIN_RSA_MODULUS_BITS: i32 = 2048;
21
22fn validate_modulus_bits(bits: i32) -> Result<(), Error> {
23 ensure!(bits >= MIN_RSA_MODULUS_BITS, JWTError::WeakKey);
24 Ok(())
25}
26
27#[derive(Debug, Clone)]
29pub struct RsaOaepEncryptionKey {
30 pk: Rsa<Public>,
31 key_id: Option<String>,
32}
33
34impl RsaOaepEncryptionKey {
35 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
37 let pk = Rsa::<Public>::public_key_from_der(der)
38 .or_else(|_| Rsa::<Public>::public_key_from_der_pkcs1(der))?;
39 validate_modulus_bits(pk.n().num_bits())?;
40 Ok(RsaOaepEncryptionKey { pk, key_id: None })
41 }
42
43 pub fn from_pem(pem: &str) -> Result<Self, Error> {
45 let pem = pem.trim();
46 let pk = Rsa::<Public>::public_key_from_pem(pem.as_bytes())
47 .or_else(|_| Rsa::<Public>::public_key_from_pem_pkcs1(pem.as_bytes()))?;
48 validate_modulus_bits(pk.n().num_bits())?;
49 Ok(RsaOaepEncryptionKey { pk, key_id: None })
50 }
51
52 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
54 self.pk.public_key_to_der().map_err(Into::into)
55 }
56
57 pub fn to_pem(&self) -> Result<String, Error> {
59 let bytes = self.pk.public_key_to_pem()?;
60 Ok(String::from_utf8(bytes)?)
61 }
62
63 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
65 self.key_id = Some(key_id.into());
66 self
67 }
68
69 pub fn key_id(&self) -> Option<&str> {
71 self.key_id.as_deref()
72 }
73
74 fn wrap_key(&self, cek: &[u8]) -> Result<Vec<u8>, Error> {
75 let mut encrypted = vec![0u8; self.pk.size() as usize];
76 let encrypted_len = self
77 .pk
78 .public_encrypt(cek, &mut encrypted, Padding::PKCS1_OAEP)
79 .map_err(|_| JWTError::InvalidEncryptionKey)?;
80 encrypted.truncate(encrypted_len);
81
82 Ok(encrypted)
83 }
84
85 pub fn encrypt<CustomClaims: Serialize>(
87 &self,
88 claims: JWTClaims<CustomClaims>,
89 ) -> Result<String, Error> {
90 self.encrypt_with_options(claims, &EncryptionOptions::default())
91 }
92
93 pub fn encrypt_with_options<CustomClaims: Serialize>(
95 &self,
96 claims: JWTClaims<CustomClaims>,
97 options: &EncryptionOptions,
98 ) -> Result<String, Error> {
99 let content_encryption = options.content_encryption;
100 let mut header = JWEHeader::new("RSA-OAEP", content_encryption.alg_name());
101
102 if let Some(key_id) = &self.key_id {
103 header.key_id = Some(key_id.clone());
104 }
105 if let Some(key_id) = &options.key_id {
106 header.key_id = Some(key_id.clone());
107 }
108 if let Some(cty) = &options.content_type {
109 header.content_type = Some(cty.clone());
110 }
111
112 JWEToken::build_from_claims(&header, &claims, content_encryption, |cek| {
113 self.wrap_key(cek)
114 })
115 }
116}
117
118#[derive(Clone)]
120pub struct RsaOaepDecryptionKey {
121 sk: Rsa<Private>,
122 key_id: Option<String>,
123}
124
125impl std::fmt::Debug for RsaOaepDecryptionKey {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 f.debug_struct("RsaOaepDecryptionKey")
128 .field("key_id", &self.key_id)
129 .field("modulus_bits", &self.sk.n().num_bits())
130 .finish_non_exhaustive()
131 }
132}
133
134impl RsaOaepDecryptionKey {
135 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
137 let sk = Rsa::<Private>::private_key_from_der(der)?;
138 if !sk.check_key()? {
139 bail!(JWTError::InvalidKeyPair);
140 }
141 validate_modulus_bits(sk.n().num_bits())?;
142 Ok(RsaOaepDecryptionKey { sk, key_id: None })
143 }
144
145 pub fn from_pem(pem: &str) -> Result<Self, Error> {
147 let pem = pem.trim();
148 let sk = Rsa::<Private>::private_key_from_pem(pem.as_bytes())?;
149 if !sk.check_key()? {
150 bail!(JWTError::InvalidKeyPair);
151 }
152 validate_modulus_bits(sk.n().num_bits())?;
153 Ok(RsaOaepDecryptionKey { sk, key_id: None })
154 }
155
156 pub fn generate(modulus_bits: usize) -> Result<Self, Error> {
158 match modulus_bits {
159 2048 | 3072 | 4096 => {}
160 _ => bail!(JWTError::UnsupportedRSAModulus),
161 };
162 let sk = Rsa::<Private>::generate(modulus_bits as u32)?;
163 Ok(RsaOaepDecryptionKey { sk, key_id: None })
164 }
165
166 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
168 self.sk.private_key_to_der().map_err(Into::into)
169 }
170
171 pub fn to_pem(&self) -> Result<String, Error> {
173 let bytes = self.sk.private_key_to_pem()?;
174 Ok(String::from_utf8(bytes)?)
175 }
176
177 pub fn encryption_key(&self) -> RsaOaepEncryptionKey {
179 let pk = Rsa::<Public>::from_public_components(
180 self.sk.n().to_owned().expect("failed to get modulus"),
181 self.sk.e().to_owned().expect("failed to get exponent"),
182 )
183 .expect("failed to create public key");
184 RsaOaepEncryptionKey {
185 pk,
186 key_id: self.key_id.clone(),
187 }
188 }
189
190 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
192 self.key_id = Some(key_id.into());
193 self
194 }
195
196 pub fn key_id(&self) -> Option<&str> {
198 self.key_id.as_deref()
199 }
200
201 fn unwrap_key(&self, encrypted_key: &[u8]) -> Result<Vec<u8>, Error> {
202 let mut cek = vec![0u8; self.sk.size() as usize];
203 let cek_len = self
204 .sk
205 .private_decrypt(encrypted_key, &mut cek, Padding::PKCS1_OAEP)
206 .map_err(|_| JWTError::KeyUnwrapFailed)?;
207 cek.truncate(cek_len);
208
209 Ok(cek)
210 }
211
212 pub fn encrypt<CustomClaims: Serialize>(
214 &self,
215 claims: JWTClaims<CustomClaims>,
216 ) -> Result<String, Error> {
217 self.encryption_key().encrypt(claims)
218 }
219
220 pub fn encrypt_with_options<CustomClaims: Serialize>(
222 &self,
223 claims: JWTClaims<CustomClaims>,
224 options: &EncryptionOptions,
225 ) -> Result<String, Error> {
226 self.encryption_key().encrypt_with_options(claims, options)
227 }
228
229 pub fn decrypt_token<CustomClaims: DeserializeOwned>(
231 &self,
232 token: &str,
233 options: Option<DecryptionOptions>,
234 ) -> Result<JWTClaims<CustomClaims>, Error> {
235 JWEToken::decrypt("RSA-OAEP", token, options, |_header, encrypted_key| {
236 self.unwrap_key(encrypted_key)
237 })
238 }
239
240 pub fn decode_metadata(token: &str) -> Result<JWETokenMetadata, Error> {
242 JWEToken::decode_metadata(token)
243 }
244}