1#[cfg(test)]
21mod tests;
22
23#[cfg(all(test, not(target_arch = "wasm32")))]
24#[doc(hidden)]
25pub mod test_support;
26
27use sha2::{Digest, Sha256};
28
29const SHA256_DIGEST_INFO: [u8; 19] = [
31 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
32];
33
34const RSA_ENCRYPTION_OID: [u8; 9] = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01];
36
37const MIN_BITS: usize = 2048;
38const MAX_BITS: usize = 8192;
39
40#[derive(Clone)]
42pub struct RsaPublicKey {
43 n: Vec<u32>,
45 k: usize,
47 e: u64,
48 n0_inv: u32,
50 r2: Vec<u32>,
52 n_bytes: Vec<u8>,
54}
55
56impl std::fmt::Debug for RsaPublicKey {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(f, "RsaPublicKey({} bits, e = {})", self.size_bits(), self.e)
59 }
60}
61
62impl PartialEq for RsaPublicKey {
63 fn eq(&self, other: &Self) -> bool {
64 self.n_bytes == other.n_bytes && self.e == other.e
65 }
66}
67
68impl Eq for RsaPublicKey {}
69
70impl RsaPublicKey {
71 pub fn from_components(n: &[u8], e: &[u8]) -> Result<RsaPublicKey, String> {
74 let n = strip_leading_zeros(n);
75 let e_bytes = strip_leading_zeros(e);
76 if n.is_empty() {
77 return Err("RSA modulus is zero".to_string());
78 }
79 let bits = (n.len() - 1) * 8 + (8 - n[0].leading_zeros() as usize);
80 if !(MIN_BITS..=MAX_BITS).contains(&bits) {
81 return Err(format!("RSA key is {bits} bits; {MIN_BITS}–{MAX_BITS} are accepted"));
82 }
83 if n[n.len() - 1] & 1 == 0 {
84 return Err("RSA modulus is even".to_string());
85 }
86 if e_bytes.is_empty() || e_bytes.len() > 8 {
87 return Err("RSA public exponent out of range".to_string());
88 }
89 let e = e_bytes.iter().fold(0u64, |acc, b| (acc << 8) | *b as u64);
90 if e < 3 || e & 1 == 0 {
91 return Err(format!("RSA public exponent {e} is not an odd number of at least 3"));
92 }
93
94 let limbs = n.len().div_ceil(4);
95 let n_limbs = from_be_bytes(n, limbs);
96 let n0_inv = montgomery_n0_inv(n_limbs[0]);
97 let r2 = r_squared_mod(&n_limbs);
98 Ok(RsaPublicKey { n: n_limbs, k: n.len(), e, n0_inv, r2, n_bytes: n.to_vec() })
99 }
100
101 pub fn from_pkcs1_der(der: &[u8]) -> Result<RsaPublicKey, String> {
103 let (seq, rest) = expect_tlv(der, 0x30, "RSAPublicKey")?;
104 if !rest.is_empty() {
105 return Err("trailing bytes after RSAPublicKey".to_string());
106 }
107 let (n, after_n) = expect_tlv(seq, 0x02, "modulus")?;
108 let (e, after_e) = expect_tlv(after_n, 0x02, "public exponent")?;
109 if !after_e.is_empty() {
110 return Err("unexpected fields in RSAPublicKey".to_string());
111 }
112 RsaPublicKey::from_components(positive_integer(n)?, positive_integer(e)?)
113 }
114
115 pub fn from_public_key_der(spki: &[u8]) -> Result<RsaPublicKey, String> {
118 let (seq, rest) = expect_tlv(spki, 0x30, "SubjectPublicKeyInfo")?;
119 if !rest.is_empty() {
120 return Err("trailing bytes after SubjectPublicKeyInfo".to_string());
121 }
122 let (algorithm, after_alg) = expect_tlv(seq, 0x30, "AlgorithmIdentifier")?;
123 let (oid, _params) = expect_tlv(algorithm, 0x06, "algorithm OID")?;
124 if oid != RSA_ENCRYPTION_OID {
125 return Err("not an RSA public key".to_string());
126 }
127 let (bits, after_bits) = expect_tlv(after_alg, 0x03, "subjectPublicKey")?;
128 if !after_bits.is_empty() {
129 return Err("unexpected fields in SubjectPublicKeyInfo".to_string());
130 }
131 match bits.split_first() {
132 Some((0, key)) => RsaPublicKey::from_pkcs1_der(key),
133 _ => Err("subjectPublicKey has unused bits".to_string()),
134 }
135 }
136
137 pub fn from_public_key_pem(pem: &str) -> Result<RsaPublicKey, String> {
140 for (label, spki) in [("PUBLIC KEY", true), ("RSA PUBLIC KEY", false)] {
141 let begin = format!("-----BEGIN {label}-----");
142 let end = format!("-----END {label}-----");
143 if let Some(start) = pem.find(&begin) {
144 let body_start = start + begin.len();
145 let body_end = pem[body_start..].find(&end).map(|i| body_start + i).ok_or("PEM end line missing")?;
146 let der = base64_decode(&pem[body_start..body_end]).ok_or("PEM body is not base64")?;
147 return if spki { RsaPublicKey::from_public_key_der(&der) } else { RsaPublicKey::from_pkcs1_der(&der) };
148 }
149 }
150 Err("no `BEGIN PUBLIC KEY` or `BEGIN RSA PUBLIC KEY` block".to_string())
151 }
152
153 pub fn size_bits(&self) -> usize {
155 (self.k - 1) * 8 + (8 - self.n_bytes[0].leading_zeros() as usize)
156 }
157
158 pub fn modulus(&self) -> &[u8] {
160 &self.n_bytes
161 }
162
163 pub fn exponent(&self) -> u64 {
165 self.e
166 }
167
168 pub fn verify_pkcs1v15_sha256(&self, message: &[u8], signature: &[u8]) -> bool {
171 let hash = Sha256::digest(message);
172 self.verify_pkcs1v15_sha256_prehashed(&hash, signature)
173 }
174
175 pub fn verify_pkcs1v15_sha256_prehashed(&self, hash: &[u8], signature: &[u8]) -> bool {
178 if hash.len() != 32 || signature.len() != self.k {
179 return false;
180 }
181 let s = from_be_bytes(signature, self.n.len());
182 if !less_than(&s, &self.n) {
183 return false;
184 }
185 let m = self.mod_pow(&s);
186 let em = to_be_bytes(&m, self.k);
187
188 let t_len = SHA256_DIGEST_INFO.len() + 32;
190 if self.k < t_len + 11 {
191 return false;
192 }
193 let mut expected = Vec::with_capacity(self.k);
194 expected.extend_from_slice(&[0x00, 0x01]);
195 expected.resize(self.k - t_len - 1, 0xff);
196 expected.push(0x00);
197 expected.extend_from_slice(&SHA256_DIGEST_INFO);
198 expected.extend_from_slice(hash);
199 em == expected
200 }
201
202 fn mod_pow(&self, base: &[u32]) -> Vec<u32> {
204 let one = {
205 let mut v = vec![0u32; self.n.len()];
206 v[0] = 1;
207 v
208 };
209 let base_m = self.mont_mul(base, &self.r2);
210 let mut acc = self.mont_mul(&one, &self.r2); for bit in (0..64 - self.e.leading_zeros()).rev() {
212 acc = self.mont_mul(&acc, &acc);
213 if (self.e >> bit) & 1 == 1 {
214 acc = self.mont_mul(&acc, &base_m);
215 }
216 }
217 self.mont_mul(&acc, &one)
218 }
219
220 fn mont_mul(&self, a: &[u32], b: &[u32]) -> Vec<u32> {
222 let s = self.n.len();
223 let n = &self.n;
224 let mut t = vec![0u32; s + 2];
225 for &bi in b.iter().take(s) {
226 let mut carry: u64 = 0;
227 for j in 0..s {
228 let x = t[j] as u64 + a[j] as u64 * bi as u64 + carry;
229 t[j] = x as u32;
230 carry = x >> 32;
231 }
232 let x = t[s] as u64 + carry;
233 t[s] = x as u32;
234 t[s + 1] = (x >> 32) as u32;
235
236 let m = t[0].wrapping_mul(self.n0_inv);
237 let x = t[0] as u64 + m as u64 * n[0] as u64;
238 let mut carry = x >> 32;
239 for j in 1..s {
240 let x = t[j] as u64 + m as u64 * n[j] as u64 + carry;
241 t[j - 1] = x as u32;
242 carry = x >> 32;
243 }
244 let x = t[s] as u64 + carry;
245 t[s - 1] = x as u32;
246 t[s] = t[s + 1] + (x >> 32) as u32;
247 t[s + 1] = 0;
248 }
249 let mut result = t[..s].to_vec();
250 if t[s] != 0 || !less_than(&result, n) {
251 subtract_in_place(&mut result, n);
252 }
253 result
254 }
255}
256
257fn strip_leading_zeros(bytes: &[u8]) -> &[u8] {
258 let first = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len());
259 &bytes[first..]
260}
261
262fn from_be_bytes(bytes: &[u8], limbs: usize) -> Vec<u32> {
264 let mut out = vec![0u32; limbs.max(bytes.len().div_ceil(4))];
265 for (i, &b) in bytes.iter().rev().enumerate() {
266 out[i / 4] |= (b as u32) << (8 * (i % 4));
267 }
268 out
269}
270
271fn to_be_bytes(limbs: &[u32], len: usize) -> Vec<u8> {
273 let mut out = vec![0u8; len];
274 for i in 0..len {
275 let limb = limbs.get(i / 4).copied().unwrap_or(0);
276 out[len - 1 - i] = (limb >> (8 * (i % 4))) as u8;
277 }
278 out
279}
280
281fn less_than(a: &[u32], b: &[u32]) -> bool {
282 let len = a.len().max(b.len());
283 for i in (0..len).rev() {
284 let (x, y) = (a.get(i).copied().unwrap_or(0), b.get(i).copied().unwrap_or(0));
285 if x != y {
286 return x < y;
287 }
288 }
289 false
290}
291
292fn subtract_in_place(a: &mut [u32], b: &[u32]) {
294 let mut borrow: i64 = 0;
295 for i in 0..a.len() {
296 let x = a[i] as i64 - b.get(i).copied().unwrap_or(0) as i64 - borrow;
297 if x < 0 {
298 a[i] = (x + (1i64 << 32)) as u32;
299 borrow = 1;
300 } else {
301 a[i] = x as u32;
302 borrow = 0;
303 }
304 }
305}
306
307fn montgomery_n0_inv(n0: u32) -> u32 {
310 let mut inv: u32 = 1;
311 for _ in 0..5 {
312 inv = inv.wrapping_mul(2u32.wrapping_sub(n0.wrapping_mul(inv)));
313 }
314 inv.wrapping_neg()
315}
316
317fn r_squared_mod(n: &[u32]) -> Vec<u32> {
320 let s = n.len();
321 let mut x = vec![0u32; s];
322 x[0] = 1;
323 for _ in 0..2 * 32 * s {
324 let mut carry = 0u32;
325 for limb in x.iter_mut() {
326 let next = *limb >> 31;
327 *limb = (*limb << 1) | carry;
328 carry = next;
329 }
330 if carry != 0 || !less_than(&x, n) {
331 subtract_in_place(&mut x, n);
332 }
333 }
334 x
335}
336
337fn expect_tlv<'a>(input: &'a [u8], tag: u8, what: &str) -> Result<(&'a [u8], &'a [u8]), String> {
339 let (&t, rest) = input.split_first().ok_or_else(|| format!("{what}: unexpected end of DER"))?;
340 if t != tag {
341 return Err(format!("{what}: expected DER tag {tag:#04x}, found {t:#04x}"));
342 }
343 let (&first, rest) = rest.split_first().ok_or_else(|| format!("{what}: missing length"))?;
344 let (len, rest) = if first < 0x80 {
345 (first as usize, rest)
346 } else {
347 let count = (first & 0x7f) as usize;
348 if count == 0 || count > 4 || rest.len() < count {
349 return Err(format!("{what}: unsupported DER length"));
350 }
351 let len = rest[..count].iter().fold(0usize, |acc, b| (acc << 8) | *b as usize);
352 (len, &rest[count..])
353 };
354 if rest.len() < len {
355 return Err(format!("{what}: DER length past the end of the input"));
356 }
357 Ok((&rest[..len], &rest[len..]))
358}
359
360fn positive_integer(bytes: &[u8]) -> Result<&[u8], String> {
362 match bytes.first() {
363 None => Err("empty DER INTEGER".to_string()),
364 Some(b) if b & 0x80 != 0 => Err("negative DER INTEGER".to_string()),
365 Some(_) => Ok(strip_leading_zeros(bytes)),
366 }
367}
368
369fn base64_decode(input: &str) -> Option<Vec<u8>> {
371 crate::core::base64::Decoder::STANDARD.skip_whitespace().decode(input).ok()
372}