isideload_x509_certificate/
signing.rs1use {
6 crate::{
7 EcdsaCurve, KeyAlgorithm, SignatureAlgorithm, X509CertificateError as Error,
8 rfc3447::RsaPrivateKey, rfc5958::OneAsymmetricKey,
9 },
10 aws_lc_rs::{
11 rand::SystemRandom,
12 signature::{self as ringsig, KeyPair},
13 },
14 bcder::decode::Constructed,
15 bytes::Bytes,
16 der::SecretDocument,
17 signature::{SignatureEncoding as SignatureTrait, Signer},
18 zeroize::Zeroizing,
19};
20
21pub trait Sign {
23 #[deprecated(since = "0.13.0", note = "use the signature::Signer trait instead")]
31 fn sign(&self, message: &[u8]) -> Result<(Vec<u8>, SignatureAlgorithm), Error>;
32
33 fn key_algorithm(&self) -> Option<KeyAlgorithm>;
37
38 fn public_key_data(&self) -> Bytes;
43
44 fn signature_algorithm(&self) -> Result<SignatureAlgorithm, Error>;
49
50 fn private_key_data(&self) -> Option<Zeroizing<Vec<u8>>>;
52
53 #[allow(clippy::type_complexity)]
55 fn rsa_primes(&self) -> Result<Option<(Zeroizing<Vec<u8>>, Zeroizing<Vec<u8>>)>, Error>;
56}
57
58pub trait KeyInfoSigner: Signer<Signature> + Sign {}
60
61#[derive(Clone, Debug)]
62pub struct Signature(Vec<u8>);
63
64impl From<Vec<u8>> for Signature {
65 fn from(v: Vec<u8>) -> Self {
66 Self(v)
67 }
68}
69
70impl From<Signature> for Vec<u8> {
71 fn from(v: Signature) -> Vec<u8> {
72 v.0
73 }
74}
75
76impl From<Signature> for Bytes {
77 fn from(v: Signature) -> Self {
78 Self::copy_from_slice(&v.0)
79 }
80}
81
82impl AsRef<[u8]> for Signature {
83 fn as_ref(&self) -> &[u8] {
84 &self.0
85 }
86}
87
88impl SignatureTrait for Signature {
89 type Repr = Vec<u8>;
90}
91
92impl TryFrom<&[u8]> for Signature {
93 type Error = ();
94
95 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
96 Ok(Self(value.to_vec()))
97 }
98}
99
100#[derive(Debug)]
102pub struct EcdsaKeyPair {
103 pkcs8_der: SecretDocument,
104 ring_pair: ringsig::EcdsaKeyPair,
105 curve: EcdsaCurve,
106 private_key: Zeroizing<Vec<u8>>,
107}
108
109#[derive(Debug)]
111pub struct Ed25519KeyPair {
112 pkcs8_der: SecretDocument,
113 ring_pair: ringsig::Ed25519KeyPair,
114}
115
116#[derive(Debug)]
118pub struct RsaKeyPair {
119 pkcs8_der: SecretDocument,
120 ring_pair: ringsig::RsaKeyPair,
121 private_key: Zeroizing<Vec<u8>>,
122}
123
124#[derive(Debug)]
129pub enum InMemorySigningKeyPair {
130 Ecdsa(Box<EcdsaKeyPair>),
132
133 Ed25519(Box<Ed25519KeyPair>),
135
136 Rsa(Box<RsaKeyPair>),
138}
139
140impl Signer<Signature> for InMemorySigningKeyPair {
141 fn try_sign(&self, msg: &[u8]) -> Result<Signature, signature::Error> {
142 match self {
143 Self::Rsa(kp) => {
144 let mut signature = vec![0; kp.ring_pair.public_key().modulus_len()];
145
146 kp.ring_pair
147 .sign(
148 &ringsig::RSA_PKCS1_SHA256,
149 &aws_lc_rs::rand::SystemRandom::new(),
150 msg,
151 &mut signature,
152 )
153 .map_err(|_| signature::Error::new())?;
154
155 Ok(signature.into())
156 }
157 Self::Ecdsa(kp) => {
158 let signature = kp
159 .ring_pair
160 .sign(&aws_lc_rs::rand::SystemRandom::new(), msg)
161 .map_err(|_| signature::Error::new())?;
162
163 Ok(Signature::from(signature.as_ref().to_vec()))
164 }
165 Self::Ed25519(kp) => {
166 let signature = kp.ring_pair.sign(msg);
167
168 Ok(Signature::from(signature.as_ref().to_vec()))
169 }
170 }
171 }
172}
173
174impl Sign for InMemorySigningKeyPair {
175 fn sign(&self, message: &[u8]) -> Result<(Vec<u8>, SignatureAlgorithm), Error> {
181 let algorithm = self.signature_algorithm()?;
182
183 Ok((self.try_sign(message)?.into(), algorithm))
184 }
185
186 fn key_algorithm(&self) -> Option<KeyAlgorithm> {
187 Some(match self {
188 Self::Rsa(_) => KeyAlgorithm::Rsa,
189 Self::Ed25519(_) => KeyAlgorithm::Ed25519,
190 Self::Ecdsa(kp) => KeyAlgorithm::Ecdsa(kp.curve),
191 })
192 }
193
194 fn public_key_data(&self) -> Bytes {
195 match self {
196 Self::Rsa(kp) => Bytes::copy_from_slice(kp.ring_pair.public_key().as_ref()),
197 Self::Ecdsa(kp) => Bytes::copy_from_slice(kp.ring_pair.public_key().as_ref()),
198 Self::Ed25519(kp) => Bytes::copy_from_slice(kp.ring_pair.public_key().as_ref()),
199 }
200 }
201
202 fn signature_algorithm(&self) -> Result<SignatureAlgorithm, Error> {
203 Ok(match self {
204 Self::Rsa(_) => SignatureAlgorithm::RsaSha256,
205 Self::Ecdsa(kp) => {
206 match kp.curve {
210 EcdsaCurve::Secp256r1 => SignatureAlgorithm::EcdsaSha256,
211 EcdsaCurve::Secp384r1 => SignatureAlgorithm::EcdsaSha384,
212 }
213 }
214 Self::Ed25519(_) => SignatureAlgorithm::Ed25519,
215 })
216 }
217
218 fn private_key_data(&self) -> Option<Zeroizing<Vec<u8>>> {
219 match self {
220 Self::Rsa(kp) => Some(kp.private_key.clone()),
221 Self::Ecdsa(kp) => Some(kp.private_key.clone()),
222 Self::Ed25519(_) => None,
223 }
224 }
225
226 fn rsa_primes(&self) -> Result<Option<(Zeroizing<Vec<u8>>, Zeroizing<Vec<u8>>)>, Error> {
227 match self {
228 Self::Rsa(kp) => {
229 let key = Constructed::decode(kp.private_key.as_ref(), bcder::Mode::Der, |cons| {
230 RsaPrivateKey::take_from(cons)
231 })?;
232
233 Ok(Some((
234 Zeroizing::new(key.p.as_slice().to_vec()),
235 Zeroizing::new(key.q.as_slice().to_vec()),
236 )))
237 }
238 Self::Ecdsa(_) => Ok(None),
239 Self::Ed25519(_) => Ok(None),
240 }
241 }
242}
243
244impl KeyInfoSigner for InMemorySigningKeyPair {}
245
246impl InMemorySigningKeyPair {
247 pub fn from_pkcs8_der(data: impl AsRef<[u8]>) -> Result<Self, Error> {
251 let pkcs8_der = SecretDocument::try_from(data.as_ref())?;
252
253 let key = Constructed::decode(data.as_ref(), bcder::Mode::Der, |cons| {
255 OneAsymmetricKey::take_from(cons)
256 })?;
257
258 let algorithm = KeyAlgorithm::try_from(&key.private_key_algorithm)?;
259
260 match algorithm {
263 KeyAlgorithm::Rsa => {
264 let pair = ringsig::RsaKeyPair::from_pkcs8(data.as_ref())?;
265
266 Ok(Self::Rsa(Box::new(RsaKeyPair {
267 pkcs8_der,
268 ring_pair: pair,
269 private_key: Zeroizing::new(key.private_key.into_bytes().to_vec()),
270 })))
271 }
272 KeyAlgorithm::Ecdsa(curve) => {
273 let pair = ringsig::EcdsaKeyPair::from_pkcs8(curve.into(), data.as_ref())?;
274
275 Ok(Self::Ecdsa(Box::new(EcdsaKeyPair {
276 pkcs8_der,
277 ring_pair: pair,
278 curve,
279 private_key: Zeroizing::new(data.as_ref().to_vec()),
280 })))
281 }
282 KeyAlgorithm::Ed25519 => Ok(Self::Ed25519(Box::new(Ed25519KeyPair {
283 pkcs8_der,
284 ring_pair: ringsig::Ed25519KeyPair::from_pkcs8(data.as_ref())?,
285 }))),
286 }
287 }
288
289 pub fn from_pkcs8_pem(data: impl AsRef<[u8]>) -> Result<Self, Error> {
294 let der = pem::parse(data.as_ref()).map_err(Error::PemDecode)?;
295
296 Self::from_pkcs8_der(der.contents())
297 }
298
299 pub fn generate_random(key_algorithm: KeyAlgorithm) -> Result<Self, Error> {
305 let rng = SystemRandom::new();
306
307 let document = match key_algorithm {
308 KeyAlgorithm::Ed25519 => ringsig::Ed25519KeyPair::generate_pkcs8(&rng)
309 .map_err(|_| Error::KeyPairGenerationError),
310 KeyAlgorithm::Ecdsa(curve) => ringsig::EcdsaKeyPair::generate_pkcs8(curve.into(), &rng)
311 .map_err(|_| Error::KeyPairGenerationError),
312 KeyAlgorithm::Rsa => Err(Error::RsaKeyGenerationNotSupported),
313 }?;
314
315 Self::from_pkcs8_der(document.as_ref())
316 }
317
318 pub fn verification_algorithm(
325 &self,
326 ) -> Result<&'static dyn ringsig::VerificationAlgorithm, Error> {
327 Ok(self.signature_algorithm()?
328 .resolve_verification_algorithm(self.key_algorithm().expect("key algorithm should be known for InMemorySigningKeyPair")).expect(
329 "illegal combination of key algorithm in signature algorithm: this should not occur"
330 ))
331 }
332
333 pub fn to_pkcs8_one_asymmetric_key_der(&self) -> Zeroizing<Vec<u8>> {
335 match self {
336 Self::Ecdsa(kp) => kp.pkcs8_der.to_bytes(),
337 Self::Ed25519(kp) => kp.pkcs8_der.to_bytes(),
338 Self::Rsa(kp) => kp.pkcs8_der.to_bytes(),
339 }
340 }
341}
342
343impl From<&InMemorySigningKeyPair> for KeyAlgorithm {
344 fn from(key: &InMemorySigningKeyPair) -> Self {
345 match key {
346 InMemorySigningKeyPair::Rsa(_) => KeyAlgorithm::Rsa,
347 InMemorySigningKeyPair::Ecdsa(kp) => KeyAlgorithm::Ecdsa(kp.curve),
348 InMemorySigningKeyPair::Ed25519(_) => KeyAlgorithm::Ed25519,
349 }
350 }
351}
352
353#[cfg(test)]
354mod test {
355 use {super::*, crate::rfc5280, crate::testutil::*, ringsig::UnparsedPublicKey};
356
357 #[test]
358 fn generate_random_ecdsa() {
359 for curve in EcdsaCurve::all() {
360 InMemorySigningKeyPair::generate_random(KeyAlgorithm::Ecdsa(*curve)).unwrap();
361 }
362 }
363
364 #[test]
365 fn generate_random_ed25519() {
366 InMemorySigningKeyPair::generate_random(KeyAlgorithm::Ed25519).unwrap();
367 }
368
369 #[test]
370 fn generate_random_rsa() {
371 assert!(InMemorySigningKeyPair::generate_random(KeyAlgorithm::Rsa).is_err());
372 }
373
374 #[test]
375 fn signing_key_from_ecdsa_pkcs8() {
376 let rng = aws_lc_rs::rand::SystemRandom::new();
377
378 for alg in &[
379 &ringsig::ECDSA_P256_SHA256_ASN1_SIGNING,
380 &ringsig::ECDSA_P384_SHA384_ASN1_SIGNING,
381 ] {
382 let doc = ringsig::EcdsaKeyPair::generate_pkcs8(alg, &rng).unwrap();
383
384 let signing_key = InMemorySigningKeyPair::from_pkcs8_der(doc.as_ref()).unwrap();
385 assert!(matches!(signing_key, InMemorySigningKeyPair::Ecdsa(_,)));
386
387 let pem_data = pem::Pem::new("PRIVATE KEY", doc.as_ref()).to_string();
388
389 let signing_key = InMemorySigningKeyPair::from_pkcs8_pem(pem_data.as_bytes()).unwrap();
390 assert!(matches!(signing_key, InMemorySigningKeyPair::Ecdsa(_)));
391
392 let key_pair_asn1 = Constructed::decode(doc.as_ref(), bcder::Mode::Der, |cons| {
393 OneAsymmetricKey::take_from(cons)
394 })
395 .unwrap();
396 assert_eq!(
397 key_pair_asn1.private_key_algorithm.algorithm,
398 KeyAlgorithm::Ecdsa(EcdsaCurve::Secp256r1).into()
400 );
401
402 let expected = if *alg == &ringsig::ECDSA_P256_SHA256_ASN1_SIGNING {
403 EcdsaCurve::Secp256r1
404 } else if *alg == &ringsig::ECDSA_P384_SHA384_ASN1_SIGNING {
405 EcdsaCurve::Secp384r1
406 } else {
407 panic!("unhandled test case");
408 };
409
410 assert!(key_pair_asn1.private_key_algorithm.parameters.is_some());
411 let oid = key_pair_asn1
412 .private_key_algorithm
413 .parameters
414 .unwrap()
415 .decode_oid()
416 .unwrap();
417
418 assert_eq!(EcdsaCurve::try_from(&oid).unwrap(), expected);
419 }
420 }
421
422 #[test]
423 fn signing_key_from_ed25519_pkcs8() {
424 let rng = aws_lc_rs::rand::SystemRandom::new();
425
426 let doc = ringsig::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
427
428 let signing_key = InMemorySigningKeyPair::from_pkcs8_der(doc.as_ref()).unwrap();
429 assert!(matches!(signing_key, InMemorySigningKeyPair::Ed25519(_)));
430
431 let pem_data = pem::Pem::new("PRIVATE KEY", doc.as_ref()).to_string();
432
433 let signing_key = InMemorySigningKeyPair::from_pkcs8_pem(pem_data.as_bytes()).unwrap();
434 assert!(matches!(signing_key, InMemorySigningKeyPair::Ed25519(_)));
435
436 let key_pair_asn1 = Constructed::decode(doc.as_ref(), bcder::Mode::Der, |cons| {
437 OneAsymmetricKey::take_from(cons)
438 })
439 .unwrap();
440 assert_eq!(
441 key_pair_asn1.private_key_algorithm.algorithm,
442 SignatureAlgorithm::Ed25519.into()
443 );
444 assert!(key_pair_asn1.private_key_algorithm.parameters.is_none());
445 }
446
447 #[test]
448 fn ecdsa_self_signed_certificate_verification() {
449 for curve in EcdsaCurve::all() {
450 let (cert, _) = self_signed_ecdsa_key_pair(Some(*curve));
451 cert.verify_signed_by_certificate(&cert).unwrap();
452
453 let raw: &rfc5280::Certificate = cert.as_ref();
454
455 let tbs_signature_algorithm =
456 SignatureAlgorithm::try_from(&raw.tbs_certificate.signature).unwrap();
457 let expected = match curve {
458 EcdsaCurve::Secp256r1 => SignatureAlgorithm::EcdsaSha256,
459 EcdsaCurve::Secp384r1 => SignatureAlgorithm::EcdsaSha384,
460 };
461 assert_eq!(tbs_signature_algorithm, expected);
462
463 let spki = &raw.tbs_certificate.subject_public_key_info;
464
465 assert_eq!(
467 spki.algorithm.algorithm,
468 crate::algorithm::OID_EC_PUBLIC_KEY
469 );
470 let expected = match curve {
472 EcdsaCurve::Secp256r1 => crate::algorithm::OID_EC_SECP256R1,
473 EcdsaCurve::Secp384r1 => crate::algorithm::OID_EC_SECP384R1,
474 };
475 assert!(spki.algorithm.parameters.is_some());
476 assert_eq!(
477 spki.algorithm
478 .parameters
479 .as_ref()
480 .unwrap()
481 .decode_oid()
482 .unwrap(),
483 expected
484 );
485
486 let cert_algorithm = SignatureAlgorithm::try_from(&raw.signature_algorithm).unwrap();
488 assert_eq!(cert_algorithm, tbs_signature_algorithm);
489 }
490 }
491
492 #[test]
493 fn ed25519_self_signed_certificate_verification() {
494 let (cert, _) = self_signed_ed25519_key_pair();
495 cert.verify_signed_by_certificate(&cert).unwrap();
496 }
497
498 #[test]
499 fn rsa_signing_roundtrip() {
500 let key = rsa_private_key();
501 let cert = rsa_cert();
502 let message = b"hello, world";
503
504 let signature = Signer::try_sign(&key, message).unwrap();
505
506 let public_key = UnparsedPublicKey::new(
507 key.verification_algorithm().unwrap(),
508 cert.public_key_data(),
509 );
510
511 public_key.verify(message, signature.as_ref()).unwrap();
512 }
513}