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