1use crate::error::{Result, WebAuthnError};
13
14pub fn der_length(len: usize) -> Vec<u8> {
22 if len < 0x80 {
23 vec![len as u8]
24 } else if len <= 0xFF {
25 vec![0x81, len as u8]
26 } else if len <= 0xFFFF {
27 vec![0x82, (len >> 8) as u8, (len & 0xFF) as u8]
28 } else {
29 vec![
31 0x84,
32 (len >> 24) as u8,
33 (len >> 16) as u8,
34 (len >> 8) as u8,
35 len as u8,
36 ]
37 }
38}
39
40pub fn der_sequence(contents: &[u8]) -> Vec<u8> {
42 let mut out = vec![0x30];
43 out.extend_from_slice(&der_length(contents.len()));
44 out.extend_from_slice(contents);
45 out
46}
47
48pub fn der_integer(value: &[u8]) -> Vec<u8> {
53 let needs_pad = !value.is_empty() && value[0] & 0x80 != 0;
54 let content_len = value.len() + if needs_pad { 1 } else { 0 };
55
56 let mut out = vec![0x02];
57 out.extend_from_slice(&der_length(content_len));
58 if needs_pad {
59 out.push(0x00);
60 }
61 out.extend_from_slice(value);
62 out
63}
64
65pub fn der_bit_string(contents: &[u8]) -> Vec<u8> {
70 let content_len = contents.len() + 1; let mut out = vec![0x03];
72 out.extend_from_slice(&der_length(content_len));
73 out.push(0x00); out.extend_from_slice(contents);
75 out
76}
77
78pub fn der_oid(oid_bytes: &[u8]) -> Vec<u8> {
82 let mut out = vec![0x06];
83 out.extend_from_slice(&der_length(oid_bytes.len()));
84 out.extend_from_slice(oid_bytes);
85 out
86}
87
88pub fn der_null() -> Vec<u8> {
90 vec![0x05, 0x00]
91}
92
93pub fn rsa_components_to_der(n: &[u8], e: &[u8]) -> Result<Vec<u8>> {
115 if n.is_empty() {
116 return Err(WebAuthnError::InvalidPublicKey(
117 "RSA modulus (n) must not be empty".to_string(),
118 ));
119 }
120 if e.is_empty() {
121 return Err(WebAuthnError::InvalidPublicKey(
122 "RSA exponent (e) must not be empty".to_string(),
123 ));
124 }
125
126 let mut contents = der_integer(n);
128 contents.extend_from_slice(&der_integer(e));
129 Ok(der_sequence(&contents))
130}
131
132#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
141 fn der_length_short_form() {
142 assert_eq!(der_length(0), [0x00]);
143 assert_eq!(der_length(1), [0x01]);
144 assert_eq!(der_length(127), [0x7f]);
145 }
146
147 #[test]
148 fn der_length_one_byte_long_form() {
149 assert_eq!(der_length(128), [0x81, 0x80]);
150 assert_eq!(der_length(255), [0x81, 0xff]);
151 }
152
153 #[test]
154 fn der_length_two_byte_long_form() {
155 assert_eq!(der_length(256), [0x82, 0x01, 0x00]);
156 assert_eq!(der_length(290), [0x82, 0x01, 0x22]);
157 assert_eq!(der_length(65535), [0x82, 0xff, 0xff]);
158 }
159
160 #[test]
163 fn der_sequence_empty() {
164 let encoded = der_sequence(&[]);
165 assert_eq!(encoded, [0x30, 0x00]);
166 }
167
168 #[test]
169 fn der_sequence_wraps_contents() {
170 let encoded = der_sequence(&[0xAA, 0xBB]);
171 assert_eq!(encoded, [0x30, 0x02, 0xAA, 0xBB]);
172 }
173
174 #[test]
177 fn der_integer_no_padding_needed() {
178 let encoded = der_integer(&[0x01, 0x00, 0x01]);
180 assert_eq!(encoded, [0x02, 0x03, 0x01, 0x00, 0x01]);
181 }
182
183 #[test]
184 fn der_integer_padding_needed_for_high_bit() {
185 let encoded = der_integer(&[0x80]);
187 assert_eq!(encoded, [0x02, 0x02, 0x00, 0x80]);
188 }
189
190 #[test]
191 fn der_integer_ff_byte_gets_padded() {
192 let encoded = der_integer(&[0xFF, 0x00]);
193 assert_eq!(encoded, [0x02, 0x03, 0x00, 0xFF, 0x00]);
194 }
195
196 #[test]
197 fn der_integer_256_byte_value() {
198 let n = [0xB7u8; 256];
200 let encoded = der_integer(&n);
201 assert_eq!(encoded[0], 0x02);
203 assert_eq!(&encoded[1..4], [0x82, 0x01, 0x01]);
204 assert_eq!(encoded[4], 0x00); assert_eq!(encoded[5], 0xB7); assert_eq!(encoded.len(), 1 + 3 + 1 + 256); }
208
209 #[test]
212 fn der_bit_string_prepends_unused_bits_byte() {
213 let encoded = der_bit_string(&[0xAB, 0xCD]);
214 assert_eq!(encoded, [0x03, 0x03, 0x00, 0xAB, 0xCD]);
216 }
217
218 #[test]
221 fn der_oid_rsa_encryption() {
222 let encoded = der_oid(&[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]);
223 assert_eq!(encoded[0], 0x06); assert_eq!(encoded[1], 9); assert_eq!(
226 &encoded[2..],
227 [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]
228 );
229 }
230
231 #[test]
234 fn der_null_is_two_bytes() {
235 assert_eq!(der_null(), [0x05, 0x00]);
236 }
237
238 #[test]
241 fn rsa_components_to_der_rejects_empty_n() {
242 let err = rsa_components_to_der(&[], &[0x01, 0x00, 0x01]).expect_err("expected error");
243 assert!(matches!(err, WebAuthnError::InvalidPublicKey(ref m) if m.contains("n")));
244 }
245
246 #[test]
247 fn rsa_components_to_der_rejects_empty_e() {
248 let err = rsa_components_to_der(&[0x01u8; 256], &[]).expect_err("expected error");
249 assert!(matches!(err, WebAuthnError::InvalidPublicKey(ref m) if m.contains("e")));
250 }
251
252 #[test]
253 fn rsa_components_to_der_produces_correct_size_for_2048_bit_key() {
254 let n = vec![0x01u8; 256];
259 let e = [0x01u8, 0x00, 0x01];
260 let der = rsa_components_to_der(&n, &e).expect("test setup");
261 assert_eq!(der[0], 0x30, "must start with SEQUENCE tag");
262 assert_eq!(
263 der.len(),
264 269,
265 "RSAPublicKey for 2048-bit key (no DER padding) should be 269 bytes"
266 );
267 }
268
269 #[test]
270 fn rsa_components_to_der_produces_correct_size_with_high_bit_modulus() {
271 let n = vec![0xb7u8; 256];
276 let e = [0x01u8, 0x00, 0x01];
277 let der = rsa_components_to_der(&n, &e).expect("test setup");
278 assert_eq!(der[0], 0x30);
279 assert_eq!(
280 der.len(),
281 270,
282 "RSAPublicKey with 0x00-padded modulus should be 270 bytes"
283 );
284 }
285
286 #[test]
287 fn rsa_components_to_der_accepted_by_ring() {
288 let n: &[u8] = &[
291 0xb7, 0xe0, 0x0f, 0xc9, 0xdb, 0xfa, 0xce, 0x64, 0xa6, 0xe2, 0xb7, 0xfb, 0xa2, 0x1c,
292 0x09, 0x14, 0xfb, 0xd6, 0x26, 0xe5, 0x17, 0xcc, 0xf6, 0x6b, 0xf5, 0x8e, 0xbb, 0x69,
293 0x07, 0x50, 0xc0, 0xbb, 0x4c, 0xe7, 0x6e, 0xd8, 0xa4, 0x6a, 0x69, 0x29, 0xfc, 0xc9,
294 0x52, 0x0c, 0xdb, 0x04, 0xec, 0xa2, 0xef, 0x27, 0x7d, 0x8f, 0xfa, 0x9d, 0xaa, 0x10,
295 0x59, 0x54, 0x7b, 0x42, 0x78, 0xdb, 0xae, 0xd4, 0x24, 0x0a, 0xd4, 0x06, 0x69, 0xb0,
296 0xe2, 0xa5, 0x68, 0xca, 0x2d, 0x41, 0x34, 0xb0, 0x64, 0xaf, 0x61, 0x13, 0xc9, 0x32,
297 0xfc, 0x93, 0x56, 0x4f, 0x82, 0x7b, 0xea, 0xff, 0x20, 0xe5, 0x1c, 0x56, 0xb6, 0xe0,
298 0xf4, 0xaa, 0x6a, 0x20, 0xd2, 0x1c, 0x46, 0x71, 0xe6, 0x05, 0x9a, 0x96, 0x99, 0xad,
299 0x5a, 0x6f, 0x78, 0xfd, 0xa7, 0x06, 0xf8, 0xfd, 0x2d, 0xea, 0x91, 0xf2, 0x9e, 0xac,
300 0xc0, 0x43, 0x45, 0x2d, 0x79, 0xb0, 0xf2, 0x24, 0x5a, 0x8c, 0x91, 0xe6, 0xc6, 0xc2,
301 0xfe, 0x50, 0x8d, 0x64, 0x82, 0x06, 0x77, 0x6e, 0xef, 0x7d, 0x61, 0x6e, 0x80, 0xd1,
302 0x87, 0xfb, 0x25, 0x35, 0xc6, 0xe8, 0x3a, 0xec, 0x38, 0xce, 0x45, 0x70, 0xf8, 0x56,
303 0xc7, 0x6e, 0xb7, 0x20, 0xdb, 0x72, 0x51, 0x82, 0xd0, 0xd2, 0xd2, 0xbd, 0xc9, 0xe0,
304 0x3c, 0xef, 0xbb, 0x93, 0x70, 0xdd, 0xfb, 0xd4, 0xda, 0x6e, 0xf6, 0x73, 0xb3, 0x79,
305 0xf7, 0xe8, 0x49, 0x72, 0x22, 0x44, 0x92, 0xd8, 0xe4, 0x3e, 0x04, 0xbc, 0x83, 0xb2,
306 0x6c, 0x59, 0x4a, 0x79, 0x11, 0x1e, 0x33, 0xd6, 0x4b, 0xe6, 0x24, 0x7b, 0xdf, 0x93,
307 0x18, 0x1d, 0xb3, 0x27, 0x0b, 0x73, 0xbb, 0xff, 0xa8, 0xe2, 0x13, 0xa0, 0x8f, 0x39,
308 0x2c, 0x21, 0xc1, 0x5e, 0xf1, 0xa8, 0x82, 0x25, 0x28, 0x19, 0xae, 0xc9, 0x3f, 0x09,
309 0x2d, 0x8c, 0x81, 0xa5,
310 ];
311 let e: &[u8] = &[0x01, 0x00, 0x01];
312
313 let der = rsa_components_to_der(n, e).expect("test setup");
314 assert_eq!(der[0], 0x30);
315 assert_eq!(
316 der.len(),
317 270,
318 "RSAPublicKey for RSA 2048 (high-bit modulus) should be 270 bytes"
319 );
320
321 }
324}