1 | #![allow (clippy::duplicate_mod)] |
2 | |
3 | use alloc::boxed::Box; |
4 | use alloc::string::ToString; |
5 | use alloc::vec::Vec; |
6 | use alloc::{format, vec}; |
7 | use core::fmt::{self, Debug, Formatter}; |
8 | |
9 | use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, SubjectPublicKeyInfoDer, alg_id}; |
10 | |
11 | use super::ring_like::rand::{SecureRandom, SystemRandom}; |
12 | use super::ring_like::signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, RsaKeyPair}; |
13 | use crate::crypto::signer::{Signer, SigningKey, public_key_to_spki}; |
14 | use crate::enums::{SignatureAlgorithm, SignatureScheme}; |
15 | use crate::error::Error; |
16 | use crate::sync::Arc; |
17 | use crate::x509::{wrap_concat_in_sequence, wrap_in_octet_string}; |
18 | |
19 | /// Parse `der` as any supported key encoding/type, returning |
20 | /// the first which works. |
21 | pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> { |
22 | if let Ok(rsa: RsaSigningKey) = RsaSigningKey::new(der) { |
23 | return Ok(Arc::new(data:rsa)); |
24 | } |
25 | |
26 | if let Ok(ecdsa: Arc) = any_ecdsa_type(der) { |
27 | return Ok(ecdsa); |
28 | } |
29 | |
30 | if let PrivateKeyDer::Pkcs8(pkcs8: &PrivatePkcs8KeyDer<'_>) = der { |
31 | if let Ok(eddsa: Arc) = any_eddsa_type(der:pkcs8) { |
32 | return Ok(eddsa); |
33 | } |
34 | } |
35 | |
36 | Err(Error::General( |
37 | "failed to parse private key as RSA, ECDSA, or EdDSA" .into(), |
38 | )) |
39 | } |
40 | |
41 | /// Parse `der` as any ECDSA key type, returning the first which works. |
42 | /// |
43 | /// Both SEC1 (PEM section starting with 'BEGIN EC PRIVATE KEY') and PKCS8 |
44 | /// (PEM section starting with 'BEGIN PRIVATE KEY') encodings are supported. |
45 | pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> { |
46 | if let Ok(ecdsa_p256: EcdsaSigningKey) = EcdsaSigningKey::new( |
47 | der, |
48 | scheme:SignatureScheme::ECDSA_NISTP256_SHA256, |
49 | &signature::ECDSA_P256_SHA256_ASN1_SIGNING, |
50 | ) { |
51 | return Ok(Arc::new(data:ecdsa_p256)); |
52 | } |
53 | |
54 | if let Ok(ecdsa_p384: EcdsaSigningKey) = EcdsaSigningKey::new( |
55 | der, |
56 | scheme:SignatureScheme::ECDSA_NISTP384_SHA384, |
57 | &signature::ECDSA_P384_SHA384_ASN1_SIGNING, |
58 | ) { |
59 | return Ok(Arc::new(data:ecdsa_p384)); |
60 | } |
61 | |
62 | Err(Error::General( |
63 | "failed to parse ECDSA private key as PKCS#8 or SEC1" .into(), |
64 | )) |
65 | } |
66 | |
67 | /// Parse `der` as any EdDSA key type, returning the first which works. |
68 | /// |
69 | /// Note that, at the time of writing, Ed25519 does not have wide support |
70 | /// in browsers. It is also not supported by the WebPKI, because the |
71 | /// CA/Browser Forum Baseline Requirements do not support it for publicly |
72 | /// trusted certificates. |
73 | pub fn any_eddsa_type(der: &PrivatePkcs8KeyDer<'_>) -> Result<Arc<dyn SigningKey>, Error> { |
74 | // TODO: Add support for Ed448 |
75 | Ok(Arc::new(data:Ed25519SigningKey::new( |
76 | der, |
77 | scheme:SignatureScheme::ED25519, |
78 | )?)) |
79 | } |
80 | |
81 | /// A `SigningKey` for RSA-PKCS1 or RSA-PSS. |
82 | /// |
83 | /// This is used by the test suite, so it must be `pub`, but it isn't part of |
84 | /// the public, stable, API. |
85 | #[doc (hidden)] |
86 | pub struct RsaSigningKey { |
87 | key: Arc<RsaKeyPair>, |
88 | } |
89 | |
90 | static ALL_RSA_SCHEMES: &[SignatureScheme] = &[ |
91 | SignatureScheme::RSA_PSS_SHA512, |
92 | SignatureScheme::RSA_PSS_SHA384, |
93 | SignatureScheme::RSA_PSS_SHA256, |
94 | SignatureScheme::RSA_PKCS1_SHA512, |
95 | SignatureScheme::RSA_PKCS1_SHA384, |
96 | SignatureScheme::RSA_PKCS1_SHA256, |
97 | ]; |
98 | |
99 | impl RsaSigningKey { |
100 | /// Make a new `RsaSigningKey` from a DER encoding, in either |
101 | /// PKCS#1 or PKCS#8 format. |
102 | pub fn new(der: &PrivateKeyDer<'_>) -> Result<Self, Error> { |
103 | let key_pair: KeyPair = match der { |
104 | PrivateKeyDer::Pkcs1(pkcs1) => RsaKeyPair::from_der(pkcs1.secret_pkcs1_der()), |
105 | PrivateKeyDer::Pkcs8(pkcs8) => RsaKeyPair::from_pkcs8(pkcs8.secret_pkcs8_der()), |
106 | _ => { |
107 | return Err(Error::General( |
108 | "failed to parse RSA private key as either PKCS#1 or PKCS#8" .into(), |
109 | )); |
110 | } |
111 | } |
112 | .map_err(|key_rejected: KeyRejected| { |
113 | Error::General(format!("failed to parse RSA private key: {}" , key_rejected)) |
114 | })?; |
115 | |
116 | Ok(Self { |
117 | key: Arc::new(data:key_pair), |
118 | }) |
119 | } |
120 | } |
121 | |
122 | impl SigningKey for RsaSigningKey { |
123 | fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { |
124 | ALL_RSA_SCHEMESOption<&SignatureScheme> |
125 | .iter() |
126 | .find(|scheme: &&SignatureScheme| offered.contains(scheme)) |
127 | .map(|scheme: &SignatureScheme| RsaSigner::new(key:Arc::clone(&self.key), *scheme)) |
128 | } |
129 | |
130 | fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> { |
131 | Some(public_key_to_spki( |
132 | &alg_id::RSA_ENCRYPTION, |
133 | self.key.public_key(), |
134 | )) |
135 | } |
136 | |
137 | fn algorithm(&self) -> SignatureAlgorithm { |
138 | SignatureAlgorithm::RSA |
139 | } |
140 | } |
141 | |
142 | impl Debug for RsaSigningKey { |
143 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
144 | f&mut DebugStruct<'_, '_>.debug_struct("RsaSigningKey" ) |
145 | .field(name:"algorithm" , &self.algorithm()) |
146 | .finish() |
147 | } |
148 | } |
149 | |
150 | struct RsaSigner { |
151 | key: Arc<RsaKeyPair>, |
152 | scheme: SignatureScheme, |
153 | encoding: &'static dyn signature::RsaEncoding, |
154 | } |
155 | |
156 | impl RsaSigner { |
157 | fn new(key: Arc<RsaKeyPair>, scheme: SignatureScheme) -> Box<dyn Signer> { |
158 | let encoding: &dyn signature::RsaEncoding = match scheme { |
159 | SignatureScheme::RSA_PKCS1_SHA256 => &signature::RSA_PKCS1_SHA256, |
160 | SignatureScheme::RSA_PKCS1_SHA384 => &signature::RSA_PKCS1_SHA384, |
161 | SignatureScheme::RSA_PKCS1_SHA512 => &signature::RSA_PKCS1_SHA512, |
162 | SignatureScheme::RSA_PSS_SHA256 => &signature::RSA_PSS_SHA256, |
163 | SignatureScheme::RSA_PSS_SHA384 => &signature::RSA_PSS_SHA384, |
164 | SignatureScheme::RSA_PSS_SHA512 => &signature::RSA_PSS_SHA512, |
165 | _ => unreachable!(), |
166 | }; |
167 | |
168 | Box::new(Self { |
169 | key, |
170 | scheme, |
171 | encoding, |
172 | }) |
173 | } |
174 | } |
175 | |
176 | impl Signer for RsaSigner { |
177 | fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { |
178 | let mut sig: Vec = vec![0; self.key.public().modulus_len()]; |
179 | |
180 | let rng: SystemRandom = SystemRandom::new(); |
181 | self.key |
182 | .sign(self.encoding, &rng, message, &mut sig) |
183 | .map(|_| sig) |
184 | .map_err(|_| Error::General("signing failed" .to_string())) |
185 | } |
186 | |
187 | fn scheme(&self) -> SignatureScheme { |
188 | self.scheme |
189 | } |
190 | } |
191 | |
192 | impl Debug for RsaSigner { |
193 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
194 | f&mut DebugStruct<'_, '_>.debug_struct("RsaSigner" ) |
195 | .field(name:"scheme" , &self.scheme) |
196 | .finish() |
197 | } |
198 | } |
199 | |
200 | /// A SigningKey that uses exactly one TLS-level SignatureScheme |
201 | /// and one ring-level signature::SigningAlgorithm. |
202 | /// |
203 | /// Compare this to RsaSigningKey, which for a particular key is |
204 | /// willing to sign with several algorithms. This is quite poor |
205 | /// cryptography practice, but is necessary because a given RSA key |
206 | /// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3 |
207 | /// (PSS signatures) -- nobody is willing to obtain certificates for |
208 | /// different protocol versions. |
209 | /// |
210 | /// Currently this is only implemented for ECDSA keys. |
211 | struct EcdsaSigningKey { |
212 | key: Arc<EcdsaKeyPair>, |
213 | scheme: SignatureScheme, |
214 | } |
215 | |
216 | impl EcdsaSigningKey { |
217 | /// Make a new `ECDSASigningKey` from a DER encoding in PKCS#8 or SEC1 |
218 | /// format, expecting a key usable with precisely the given signature |
219 | /// scheme. |
220 | fn new( |
221 | der: &PrivateKeyDer<'_>, |
222 | scheme: SignatureScheme, |
223 | sigalg: &'static signature::EcdsaSigningAlgorithm, |
224 | ) -> Result<Self, ()> { |
225 | let rng = SystemRandom::new(); |
226 | let key_pair = match der { |
227 | PrivateKeyDer::Sec1(sec1) => { |
228 | Self::convert_sec1_to_pkcs8(scheme, sigalg, sec1.secret_sec1_der(), &rng)? |
229 | } |
230 | PrivateKeyDer::Pkcs8(pkcs8) => { |
231 | EcdsaKeyPair::from_pkcs8(sigalg, pkcs8.secret_pkcs8_der(), &rng).map_err(|_| ())? |
232 | } |
233 | _ => return Err(()), |
234 | }; |
235 | |
236 | Ok(Self { |
237 | key: Arc::new(key_pair), |
238 | scheme, |
239 | }) |
240 | } |
241 | |
242 | /// Convert a SEC1 encoding to PKCS8, and ask ring to parse it. This |
243 | /// can be removed once <https://github.com/briansmith/ring/pull/1456> |
244 | /// (or equivalent) is landed. |
245 | fn convert_sec1_to_pkcs8( |
246 | scheme: SignatureScheme, |
247 | sigalg: &'static signature::EcdsaSigningAlgorithm, |
248 | maybe_sec1_der: &[u8], |
249 | rng: &dyn SecureRandom, |
250 | ) -> Result<EcdsaKeyPair, ()> { |
251 | let pkcs8_prefix = match scheme { |
252 | SignatureScheme::ECDSA_NISTP256_SHA256 => &PKCS8_PREFIX_ECDSA_NISTP256, |
253 | SignatureScheme::ECDSA_NISTP384_SHA384 => &PKCS8_PREFIX_ECDSA_NISTP384, |
254 | _ => unreachable!(), // all callers are in this file |
255 | }; |
256 | |
257 | let sec1_wrap = wrap_in_octet_string(maybe_sec1_der); |
258 | let pkcs8 = wrap_concat_in_sequence(pkcs8_prefix, &sec1_wrap); |
259 | |
260 | EcdsaKeyPair::from_pkcs8(sigalg, &pkcs8, rng).map_err(|_| ()) |
261 | } |
262 | } |
263 | |
264 | // This is (line-by-line): |
265 | // - INTEGER Version = 0 |
266 | // - SEQUENCE (privateKeyAlgorithm) |
267 | // - id-ecPublicKey OID |
268 | // - prime256v1 OID |
269 | const PKCS8_PREFIX_ECDSA_NISTP256: &[u8] = b" \x02\x01\x00\ |
270 | \x30\x13\ |
271 | \x06\x07\x2a\x86\x48\xce\x3d\x02\x01\ |
272 | \x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" ; |
273 | |
274 | // This is (line-by-line): |
275 | // - INTEGER Version = 0 |
276 | // - SEQUENCE (privateKeyAlgorithm) |
277 | // - id-ecPublicKey OID |
278 | // - secp384r1 OID |
279 | const PKCS8_PREFIX_ECDSA_NISTP384: &[u8] = b" \x02\x01\x00\ |
280 | \x30\x10\ |
281 | \x06\x07\x2a\x86\x48\xce\x3d\x02\x01\ |
282 | \x06\x05\x2b\x81\x04\x00\x22" ; |
283 | |
284 | impl SigningKey for EcdsaSigningKey { |
285 | fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { |
286 | if offered.contains(&self.scheme) { |
287 | Some(Box::new(EcdsaSigner { |
288 | key: Arc::clone(&self.key), |
289 | scheme: self.scheme, |
290 | })) |
291 | } else { |
292 | None |
293 | } |
294 | } |
295 | |
296 | fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> { |
297 | let id = match self.scheme { |
298 | SignatureScheme::ECDSA_NISTP256_SHA256 => alg_id::ECDSA_P256, |
299 | SignatureScheme::ECDSA_NISTP384_SHA384 => alg_id::ECDSA_P384, |
300 | _ => unreachable!(), |
301 | }; |
302 | |
303 | Some(public_key_to_spki(&id, self.key.public_key())) |
304 | } |
305 | |
306 | fn algorithm(&self) -> SignatureAlgorithm { |
307 | self.scheme.algorithm() |
308 | } |
309 | } |
310 | |
311 | impl Debug for EcdsaSigningKey { |
312 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
313 | f&mut DebugStruct<'_, '_>.debug_struct("EcdsaSigningKey" ) |
314 | .field(name:"algorithm" , &self.algorithm()) |
315 | .finish() |
316 | } |
317 | } |
318 | |
319 | struct EcdsaSigner { |
320 | key: Arc<EcdsaKeyPair>, |
321 | scheme: SignatureScheme, |
322 | } |
323 | |
324 | impl Signer for EcdsaSigner { |
325 | fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { |
326 | let rng: SystemRandom = SystemRandom::new(); |
327 | self.key |
328 | .sign(&rng, message) |
329 | .map_err(|_| Error::General("signing failed" .into())) |
330 | .map(|sig: Signature| sig.as_ref().into()) |
331 | } |
332 | |
333 | fn scheme(&self) -> SignatureScheme { |
334 | self.scheme |
335 | } |
336 | } |
337 | |
338 | impl Debug for EcdsaSigner { |
339 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
340 | f&mut DebugStruct<'_, '_>.debug_struct("EcdsaSigner" ) |
341 | .field(name:"scheme" , &self.scheme) |
342 | .finish() |
343 | } |
344 | } |
345 | |
346 | /// A SigningKey that uses exactly one TLS-level SignatureScheme |
347 | /// and one ring-level signature::SigningAlgorithm. |
348 | /// |
349 | /// Compare this to RsaSigningKey, which for a particular key is |
350 | /// willing to sign with several algorithms. This is quite poor |
351 | /// cryptography practice, but is necessary because a given RSA key |
352 | /// is expected to work in TLS1.2 (PKCS#1 signatures) and TLS1.3 |
353 | /// (PSS signatures) -- nobody is willing to obtain certificates for |
354 | /// different protocol versions. |
355 | /// |
356 | /// Currently this is only implemented for Ed25519 keys. |
357 | struct Ed25519SigningKey { |
358 | key: Arc<Ed25519KeyPair>, |
359 | scheme: SignatureScheme, |
360 | } |
361 | |
362 | impl Ed25519SigningKey { |
363 | /// Make a new `Ed25519SigningKey` from a DER encoding in PKCS#8 format, |
364 | /// expecting a key usable with precisely the given signature scheme. |
365 | fn new(der: &PrivatePkcs8KeyDer<'_>, scheme: SignatureScheme) -> Result<Self, Error> { |
366 | match Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8:der.secret_pkcs8_der()) { |
367 | Ok(key_pair: Ed25519KeyPair) => Ok(Self { |
368 | key: Arc::new(data:key_pair), |
369 | scheme, |
370 | }), |
371 | Err(e: KeyRejected) => Err(Error::General(format!( |
372 | "failed to parse Ed25519 private key: {e}" |
373 | ))), |
374 | } |
375 | } |
376 | } |
377 | |
378 | impl SigningKey for Ed25519SigningKey { |
379 | fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { |
380 | if offered.contains(&self.scheme) { |
381 | Some(Box::new(Ed25519Signer { |
382 | key: Arc::clone(&self.key), |
383 | scheme: self.scheme, |
384 | })) |
385 | } else { |
386 | None |
387 | } |
388 | } |
389 | |
390 | fn public_key(&self) -> Option<SubjectPublicKeyInfoDer<'_>> { |
391 | Some(public_key_to_spki(&alg_id::ED25519, self.key.public_key())) |
392 | } |
393 | |
394 | fn algorithm(&self) -> SignatureAlgorithm { |
395 | self.scheme.algorithm() |
396 | } |
397 | } |
398 | |
399 | impl Debug for Ed25519SigningKey { |
400 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
401 | f&mut DebugStruct<'_, '_>.debug_struct("Ed25519SigningKey" ) |
402 | .field(name:"algorithm" , &self.algorithm()) |
403 | .finish() |
404 | } |
405 | } |
406 | |
407 | struct Ed25519Signer { |
408 | key: Arc<Ed25519KeyPair>, |
409 | scheme: SignatureScheme, |
410 | } |
411 | |
412 | impl Signer for Ed25519Signer { |
413 | fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { |
414 | Ok(self.key.sign(msg:message).as_ref().into()) |
415 | } |
416 | |
417 | fn scheme(&self) -> SignatureScheme { |
418 | self.scheme |
419 | } |
420 | } |
421 | |
422 | impl Debug for Ed25519Signer { |
423 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
424 | f&mut DebugStruct<'_, '_>.debug_struct("Ed25519Signer" ) |
425 | .field(name:"scheme" , &self.scheme) |
426 | .finish() |
427 | } |
428 | } |
429 | |
430 | #[cfg (test)] |
431 | mod tests { |
432 | use alloc::format; |
433 | |
434 | use pki_types::{PrivatePkcs1KeyDer, PrivateSec1KeyDer}; |
435 | |
436 | use super::*; |
437 | |
438 | #[test ] |
439 | fn can_load_ecdsa_nistp256_pkcs8() { |
440 | let key = |
441 | PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp256key.pkcs8.der" )[..]); |
442 | assert!(any_eddsa_type(&key).is_err()); |
443 | let key = PrivateKeyDer::Pkcs8(key); |
444 | assert!(any_supported_type(&key).is_ok()); |
445 | assert!(any_ecdsa_type(&key).is_ok()); |
446 | } |
447 | |
448 | #[test ] |
449 | fn can_load_ecdsa_nistp256_sec1() { |
450 | let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from( |
451 | &include_bytes!("../../testdata/nistp256key.der" )[..], |
452 | )); |
453 | assert!(any_supported_type(&key).is_ok()); |
454 | assert!(any_ecdsa_type(&key).is_ok()); |
455 | } |
456 | |
457 | #[test ] |
458 | fn can_sign_ecdsa_nistp256() { |
459 | let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from( |
460 | &include_bytes!("../../testdata/nistp256key.der" )[..], |
461 | )); |
462 | |
463 | let k = any_supported_type(&key).unwrap(); |
464 | assert_eq!(format!("{:?}" , k), "EcdsaSigningKey { algorithm: ECDSA }" ); |
465 | assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); |
466 | |
467 | assert!( |
468 | k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256]) |
469 | .is_none() |
470 | ); |
471 | assert!( |
472 | k.choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384]) |
473 | .is_none() |
474 | ); |
475 | let s = k |
476 | .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) |
477 | .unwrap(); |
478 | assert_eq!( |
479 | format!("{:?}" , s), |
480 | "EcdsaSigner { scheme: ECDSA_NISTP256_SHA256 }" |
481 | ); |
482 | assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP256_SHA256); |
483 | // nb. signature is variable length and asn.1-encoded |
484 | assert!( |
485 | s.sign(b"hello" ) |
486 | .unwrap() |
487 | .starts_with(&[0x30]) |
488 | ); |
489 | } |
490 | |
491 | #[test ] |
492 | fn can_load_ecdsa_nistp384_pkcs8() { |
493 | let key = |
494 | PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/nistp384key.pkcs8.der" )[..]); |
495 | assert!(any_eddsa_type(&key).is_err()); |
496 | let key = PrivateKeyDer::Pkcs8(key); |
497 | assert!(any_supported_type(&key).is_ok()); |
498 | assert!(any_ecdsa_type(&key).is_ok()); |
499 | } |
500 | |
501 | #[test ] |
502 | fn can_load_ecdsa_nistp384_sec1() { |
503 | let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from( |
504 | &include_bytes!("../../testdata/nistp384key.der" )[..], |
505 | )); |
506 | assert!(any_supported_type(&key).is_ok()); |
507 | assert!(any_ecdsa_type(&key).is_ok()); |
508 | } |
509 | |
510 | #[test ] |
511 | fn can_sign_ecdsa_nistp384() { |
512 | let key = PrivateKeyDer::Sec1(PrivateSec1KeyDer::from( |
513 | &include_bytes!("../../testdata/nistp384key.der" )[..], |
514 | )); |
515 | |
516 | let k = any_supported_type(&key).unwrap(); |
517 | assert_eq!(format!("{:?}" , k), "EcdsaSigningKey { algorithm: ECDSA }" ); |
518 | assert_eq!(k.algorithm(), SignatureAlgorithm::ECDSA); |
519 | |
520 | assert!( |
521 | k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256]) |
522 | .is_none() |
523 | ); |
524 | assert!( |
525 | k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) |
526 | .is_none() |
527 | ); |
528 | let s = k |
529 | .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384]) |
530 | .unwrap(); |
531 | assert_eq!( |
532 | format!("{:?}" , s), |
533 | "EcdsaSigner { scheme: ECDSA_NISTP384_SHA384 }" |
534 | ); |
535 | assert_eq!(s.scheme(), SignatureScheme::ECDSA_NISTP384_SHA384); |
536 | // nb. signature is variable length and asn.1-encoded |
537 | assert!( |
538 | s.sign(b"hello" ) |
539 | .unwrap() |
540 | .starts_with(&[0x30]) |
541 | ); |
542 | } |
543 | |
544 | #[test ] |
545 | fn can_load_eddsa_pkcs8() { |
546 | let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der" )[..]); |
547 | assert!(any_eddsa_type(&key).is_ok()); |
548 | let key = PrivateKeyDer::Pkcs8(key); |
549 | assert!(any_supported_type(&key).is_ok()); |
550 | assert!(any_ecdsa_type(&key).is_err()); |
551 | } |
552 | |
553 | #[test ] |
554 | fn can_sign_eddsa() { |
555 | let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der" )[..]); |
556 | |
557 | let k = any_eddsa_type(&key).unwrap(); |
558 | assert_eq!( |
559 | format!("{:?}" , k), |
560 | "Ed25519SigningKey { algorithm: ED25519 }" |
561 | ); |
562 | assert_eq!(k.algorithm(), SignatureAlgorithm::ED25519); |
563 | |
564 | assert!( |
565 | k.choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256]) |
566 | .is_none() |
567 | ); |
568 | assert!( |
569 | k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) |
570 | .is_none() |
571 | ); |
572 | let s = k |
573 | .choose_scheme(&[SignatureScheme::ED25519]) |
574 | .unwrap(); |
575 | assert_eq!(format!("{:?}" , s), "Ed25519Signer { scheme: ED25519 }" ); |
576 | assert_eq!(s.scheme(), SignatureScheme::ED25519); |
577 | assert_eq!(s.sign(b"hello" ).unwrap().len(), 64); |
578 | } |
579 | |
580 | #[test ] |
581 | fn can_load_rsa2048_pkcs8() { |
582 | let key = |
583 | PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/rsa2048key.pkcs8.der" )[..]); |
584 | assert!(any_eddsa_type(&key).is_err()); |
585 | let key = PrivateKeyDer::Pkcs8(key); |
586 | assert!(any_supported_type(&key).is_ok()); |
587 | assert!(any_ecdsa_type(&key).is_err()); |
588 | } |
589 | |
590 | #[test ] |
591 | fn can_load_rsa2048_pkcs1() { |
592 | let key = PrivateKeyDer::Pkcs1(PrivatePkcs1KeyDer::from( |
593 | &include_bytes!("../../testdata/rsa2048key.pkcs1.der" )[..], |
594 | )); |
595 | assert!(any_supported_type(&key).is_ok()); |
596 | assert!(any_ecdsa_type(&key).is_err()); |
597 | } |
598 | |
599 | #[test ] |
600 | fn can_sign_rsa2048() { |
601 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
602 | &include_bytes!("../../testdata/rsa2048key.pkcs8.der" )[..], |
603 | )); |
604 | |
605 | let k = any_supported_type(&key).unwrap(); |
606 | assert_eq!(format!("{:?}" , k), "RsaSigningKey { algorithm: RSA }" ); |
607 | assert_eq!(k.algorithm(), SignatureAlgorithm::RSA); |
608 | |
609 | assert!( |
610 | k.choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) |
611 | .is_none() |
612 | ); |
613 | assert!( |
614 | k.choose_scheme(&[SignatureScheme::ED25519]) |
615 | .is_none() |
616 | ); |
617 | |
618 | let s = k |
619 | .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256]) |
620 | .unwrap(); |
621 | assert_eq!(format!("{:?}" , s), "RsaSigner { scheme: RSA_PSS_SHA256 }" ); |
622 | assert_eq!(s.scheme(), SignatureScheme::RSA_PSS_SHA256); |
623 | assert_eq!(s.sign(b"hello" ).unwrap().len(), 256); |
624 | |
625 | for scheme in &[ |
626 | SignatureScheme::RSA_PKCS1_SHA256, |
627 | SignatureScheme::RSA_PKCS1_SHA384, |
628 | SignatureScheme::RSA_PKCS1_SHA512, |
629 | SignatureScheme::RSA_PSS_SHA256, |
630 | SignatureScheme::RSA_PSS_SHA384, |
631 | SignatureScheme::RSA_PSS_SHA512, |
632 | ] { |
633 | k.choose_scheme(&[*scheme]).unwrap(); |
634 | } |
635 | } |
636 | |
637 | #[test ] |
638 | fn cannot_load_invalid_pkcs8_encoding() { |
639 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(&b"invalid" [..])); |
640 | assert_eq!( |
641 | any_supported_type(&key).err(), |
642 | Some(Error::General( |
643 | "failed to parse private key as RSA, ECDSA, or EdDSA" .into() |
644 | )) |
645 | ); |
646 | assert_eq!( |
647 | any_ecdsa_type(&key).err(), |
648 | Some(Error::General( |
649 | "failed to parse ECDSA private key as PKCS#8 or SEC1" .into() |
650 | )) |
651 | ); |
652 | assert_eq!( |
653 | RsaSigningKey::new(&key).err(), |
654 | Some(Error::General( |
655 | "failed to parse RSA private key: InvalidEncoding" .into() |
656 | )) |
657 | ); |
658 | } |
659 | } |
660 | |
661 | #[cfg (bench)] |
662 | mod benchmarks { |
663 | use super::{PrivateKeyDer, PrivatePkcs8KeyDer, SignatureScheme}; |
664 | |
665 | #[bench ] |
666 | fn bench_rsa2048_pkcs1_sha256(b: &mut test::Bencher) { |
667 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
668 | &include_bytes!("../../testdata/rsa2048key.pkcs8.der" )[..], |
669 | )); |
670 | let sk = super::any_supported_type(&key).unwrap(); |
671 | let signer = sk |
672 | .choose_scheme(&[SignatureScheme::RSA_PKCS1_SHA256]) |
673 | .unwrap(); |
674 | |
675 | b.iter(|| { |
676 | test::black_box( |
677 | signer |
678 | .sign(SAMPLE_TLS13_MESSAGE) |
679 | .unwrap(), |
680 | ); |
681 | }); |
682 | } |
683 | |
684 | #[bench ] |
685 | fn bench_rsa2048_pss_sha256(b: &mut test::Bencher) { |
686 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
687 | &include_bytes!("../../testdata/rsa2048key.pkcs8.der" )[..], |
688 | )); |
689 | let sk = super::any_supported_type(&key).unwrap(); |
690 | let signer = sk |
691 | .choose_scheme(&[SignatureScheme::RSA_PSS_SHA256]) |
692 | .unwrap(); |
693 | |
694 | b.iter(|| { |
695 | test::black_box( |
696 | signer |
697 | .sign(SAMPLE_TLS13_MESSAGE) |
698 | .unwrap(), |
699 | ); |
700 | }); |
701 | } |
702 | |
703 | #[bench ] |
704 | fn bench_eddsa(b: &mut test::Bencher) { |
705 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
706 | &include_bytes!("../../testdata/eddsakey.der" )[..], |
707 | )); |
708 | let sk = super::any_supported_type(&key).unwrap(); |
709 | let signer = sk |
710 | .choose_scheme(&[SignatureScheme::ED25519]) |
711 | .unwrap(); |
712 | |
713 | b.iter(|| { |
714 | test::black_box( |
715 | signer |
716 | .sign(SAMPLE_TLS13_MESSAGE) |
717 | .unwrap(), |
718 | ); |
719 | }); |
720 | } |
721 | |
722 | #[bench ] |
723 | fn bench_ecdsa_p256_sha256(b: &mut test::Bencher) { |
724 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
725 | &include_bytes!("../../testdata/nistp256key.pkcs8.der" )[..], |
726 | )); |
727 | let sk = super::any_supported_type(&key).unwrap(); |
728 | let signer = sk |
729 | .choose_scheme(&[SignatureScheme::ECDSA_NISTP256_SHA256]) |
730 | .unwrap(); |
731 | |
732 | b.iter(|| { |
733 | test::black_box( |
734 | signer |
735 | .sign(SAMPLE_TLS13_MESSAGE) |
736 | .unwrap(), |
737 | ); |
738 | }); |
739 | } |
740 | |
741 | #[bench ] |
742 | fn bench_ecdsa_p384_sha384(b: &mut test::Bencher) { |
743 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
744 | &include_bytes!("../../testdata/nistp384key.pkcs8.der" )[..], |
745 | )); |
746 | let sk = super::any_supported_type(&key).unwrap(); |
747 | let signer = sk |
748 | .choose_scheme(&[SignatureScheme::ECDSA_NISTP384_SHA384]) |
749 | .unwrap(); |
750 | |
751 | b.iter(|| { |
752 | test::black_box( |
753 | signer |
754 | .sign(SAMPLE_TLS13_MESSAGE) |
755 | .unwrap(), |
756 | ); |
757 | }); |
758 | } |
759 | |
760 | #[bench ] |
761 | fn bench_load_and_validate_rsa2048(b: &mut test::Bencher) { |
762 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
763 | &include_bytes!("../../testdata/rsa2048key.pkcs8.der" )[..], |
764 | )); |
765 | |
766 | b.iter(|| { |
767 | test::black_box(super::any_supported_type(&key).unwrap()); |
768 | }); |
769 | } |
770 | |
771 | #[bench ] |
772 | fn bench_load_and_validate_rsa4096(b: &mut test::Bencher) { |
773 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
774 | &include_bytes!("../../testdata/rsa4096key.pkcs8.der" )[..], |
775 | )); |
776 | |
777 | b.iter(|| { |
778 | test::black_box(super::any_supported_type(&key).unwrap()); |
779 | }); |
780 | } |
781 | |
782 | #[bench ] |
783 | fn bench_load_and_validate_p256(b: &mut test::Bencher) { |
784 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
785 | &include_bytes!("../../testdata/nistp256key.pkcs8.der" )[..], |
786 | )); |
787 | |
788 | b.iter(|| { |
789 | test::black_box(super::any_ecdsa_type(&key).unwrap()); |
790 | }); |
791 | } |
792 | |
793 | #[bench ] |
794 | fn bench_load_and_validate_p384(b: &mut test::Bencher) { |
795 | let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( |
796 | &include_bytes!("../../testdata/nistp384key.pkcs8.der" )[..], |
797 | )); |
798 | |
799 | b.iter(|| { |
800 | test::black_box(super::any_ecdsa_type(&key).unwrap()); |
801 | }); |
802 | } |
803 | |
804 | #[bench ] |
805 | fn bench_load_and_validate_eddsa(b: &mut test::Bencher) { |
806 | let key = PrivatePkcs8KeyDer::from(&include_bytes!("../../testdata/eddsakey.der" )[..]); |
807 | |
808 | b.iter(|| { |
809 | test::black_box(super::any_eddsa_type(&key).unwrap()); |
810 | }); |
811 | } |
812 | |
813 | const SAMPLE_TLS13_MESSAGE: &[u8] = &[ |
814 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
815 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
816 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
817 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
818 | 0x20, 0x20, 0x20, 0x20, 0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c, 0x20, 0x73, 0x65, |
819 | 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, |
820 | 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x04, 0xca, 0xc4, 0x48, 0x0e, 0x70, 0xf2, |
821 | 0x1b, 0xa9, 0x1c, 0x16, 0xca, 0x90, 0x48, 0xbe, 0x28, 0x2f, 0xc7, 0xf8, 0x9b, 0x87, 0x72, |
822 | 0x93, 0xda, 0x4d, 0x2f, 0x80, 0x80, 0x60, 0x1a, 0xd3, 0x08, 0xe2, 0xb7, 0x86, 0x14, 0x1b, |
823 | 0x54, 0xda, 0x9a, 0xc9, 0x6d, 0xe9, 0x66, 0xb4, 0x9f, 0xe2, 0x2c, |
824 | ]; |
825 | } |
826 | |