Skip to content

Commit 74e48d2

Browse files
committed
Invert KeyPair/SigningKey hierarchy
1 parent 1dd6a29 commit 74e48d2

File tree

6 files changed

+66
-108
lines changed

6 files changed

+66
-108
lines changed

rcgen/src/certificate.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::ENCODE_CONFIG;
1818
use crate::{
1919
oid, write_distinguished_name, write_dt_utc_or_generalized,
2020
write_x509_authority_key_identifier, write_x509_extension, DistinguishedName, Error, Issuer,
21-
KeyIdMethod, KeyPair, KeyUsagePurpose, SanType, SerialNumber,
21+
KeyIdMethod, KeyUsagePurpose, SanType, SerialNumber, SigningKey,
2222
};
2323

2424
/// An issued certificate together with the parameters used to generate it.
@@ -141,7 +141,7 @@ impl CertificateParams {
141141
&self,
142142
public_key: &impl PublicKeyData,
143143
issuer: &CertificateParams,
144-
issuer_key: &KeyPair,
144+
issuer_key: &impl SigningKey,
145145
) -> Result<Certificate, Error> {
146146
let issuer = Issuer {
147147
distinguished_name: &issuer.distinguished_name,
@@ -158,7 +158,7 @@ impl CertificateParams {
158158
///
159159
/// The returned [`Certificate`] may be serialized using [`Certificate::der`] and
160160
/// [`Certificate::pem`].
161-
pub fn self_signed(&self, key_pair: &KeyPair) -> Result<Certificate, Error> {
161+
pub fn self_signed(&self, key_pair: &impl SigningKey) -> Result<Certificate, Error> {
162162
let issuer = Issuer {
163163
distinguished_name: &self.distinguished_name,
164164
key_identifier_method: &self.key_identifier_method,
@@ -514,7 +514,7 @@ impl CertificateParams {
514514
/// same output.
515515
pub fn serialize_request(
516516
&self,
517-
subject_key: &KeyPair,
517+
subject_key: &impl SigningKey,
518518
) -> Result<CertificateSigningRequest, Error> {
519519
self.serialize_request_with_attributes(subject_key, Vec::new())
520520
}
@@ -532,7 +532,7 @@ impl CertificateParams {
532532
/// [RFC 2986]: <https://datatracker.ietf.org/doc/html/rfc2986#section-4>
533533
pub fn serialize_request_with_attributes(
534534
&self,
535-
subject_key: &KeyPair,
535+
subject_key: &impl SigningKey,
536536
attrs: Vec<Attribute>,
537537
) -> Result<CertificateSigningRequest, Error> {
538538
// No .. pattern, we use this to ensure every field is used
@@ -616,9 +616,9 @@ impl CertificateParams {
616616
pub(crate) fn serialize_der_with_signer<K: PublicKeyData>(
617617
&self,
618618
pub_key: &K,
619-
issuer: Issuer<'_>,
619+
issuer: Issuer<'_, impl SigningKey>,
620620
) -> Result<CertificateDer<'static>, Error> {
621-
let der = sign_der(&issuer.key_pair, |writer| {
621+
let der = sign_der(issuer.key_pair, |writer| {
622622
let pub_key_spki =
623623
yasna::construct_der(|writer| serialize_public_key_der(pub_key, writer));
624624
// Write version
@@ -643,7 +643,7 @@ impl CertificateParams {
643643
}
644644
};
645645
// Write signature algorithm
646-
issuer.key_pair.alg.write_alg_ident(writer.next());
646+
issuer.key_pair.algorithm().write_alg_ident(writer.next());
647647
// Write issuer name
648648
write_distinguished_name(writer.next(), &issuer.distinguished_name);
649649
// Write validity
@@ -1207,6 +1207,7 @@ pub enum BasicConstraints {
12071207
mod tests {
12081208
#[cfg(feature = "pem")]
12091209
use super::*;
1210+
use crate::KeyPair;
12101211

12111212
#[cfg(feature = "crypto")]
12121213
#[test]

rcgen/src/crl.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ use yasna::Tag;
77

88
use crate::key_pair::sign_der;
99
use crate::CertificateParams;
10+
use crate::SigningKey;
1011
#[cfg(feature = "pem")]
1112
use crate::ENCODE_CONFIG;
1213
use crate::{
1314
oid, write_distinguished_name, write_dt_utc_or_generalized,
14-
write_x509_authority_key_identifier, write_x509_extension, Error, Issuer, KeyIdMethod, KeyPair,
15+
write_x509_authority_key_identifier, write_x509_extension, Error, Issuer, KeyIdMethod,
1516
KeyUsagePurpose, SerialNumber,
1617
};
1718

@@ -193,7 +194,7 @@ impl CertificateRevocationListParams {
193194
pub fn signed_by(
194195
self,
195196
issuer: &CertificateParams,
196-
issuer_key: &KeyPair,
197+
issuer_key: &impl SigningKey,
197198
) -> Result<CertificateRevocationList, Error> {
198199
if self.next_update.le(&self.this_update) {
199200
return Err(Error::InvalidCrlNextUpdate);
@@ -216,8 +217,8 @@ impl CertificateRevocationListParams {
216217
})
217218
}
218219

219-
fn serialize_der(&self, issuer: Issuer) -> Result<Vec<u8>, Error> {
220-
sign_der(&issuer.key_pair, |writer| {
220+
fn serialize_der(&self, issuer: Issuer<'_, impl SigningKey>) -> Result<Vec<u8>, Error> {
221+
sign_der(issuer.key_pair, |writer| {
221222
// Write CRL version.
222223
// RFC 5280 §5.1.2.1:
223224
// This optional field describes the version of the encoded CRL. When
@@ -233,7 +234,7 @@ impl CertificateRevocationListParams {
233234
// RFC 5280 §5.1.2.2:
234235
// This field MUST contain the same algorithm identifier as the
235236
// signatureAlgorithm field in the sequence CertificateList
236-
issuer.key_pair.alg.write_alg_ident(writer.next());
237+
issuer.key_pair.algorithm().write_alg_ident(writer.next());
237238

238239
// Write issuer.
239240
// RFC 5280 §5.1.2.3:

rcgen/src/csr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use pki_types::CertificateSigningRequestDer;
77
#[cfg(feature = "pem")]
88
use crate::ENCODE_CONFIG;
99
use crate::{
10-
Certificate, CertificateParams, Error, Issuer, KeyPair, PublicKeyData, SignatureAlgorithm,
10+
Certificate, CertificateParams, Error, Issuer, PublicKeyData, SignatureAlgorithm, SigningKey,
1111
};
1212
#[cfg(feature = "x509-parser")]
1313
use crate::{DistinguishedName, SanType};
@@ -203,7 +203,7 @@ impl CertificateSigningRequestParams {
203203
pub fn signed_by(
204204
&self,
205205
issuer: &CertificateParams,
206-
issuer_key: &KeyPair,
206+
issuer_key: &impl SigningKey,
207207
) -> Result<Certificate, Error> {
208208
let issuer = Issuer {
209209
distinguished_name: &issuer.distinguished_name,

rcgen/src/key_pair.rs

Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(feature = "crypto")]
12
use std::fmt;
23

34
#[cfg(feature = "pem")]
@@ -29,30 +30,23 @@ use crate::{sign_algo::SignatureAlgorithm, Error};
2930

3031
/// A key pair variant
3132
#[allow(clippy::large_enum_variant)]
33+
#[cfg(feature = "crypto")]
3234
pub(crate) enum KeyPairKind {
3335
/// A Ecdsa key pair
34-
#[cfg(feature = "crypto")]
3536
Ec(EcdsaKeyPair),
3637
/// A Ed25519 key pair
37-
#[cfg(feature = "crypto")]
3838
Ed(Ed25519KeyPair),
3939
/// A RSA key pair
40-
#[cfg(feature = "crypto")]
4140
Rsa(RsaKeyPair, &'static dyn RsaEncoding),
42-
/// A remote key pair
43-
Remote(Box<dyn SigningKey + Send + Sync>),
4441
}
4542

43+
#[cfg(feature = "crypto")]
4644
impl fmt::Debug for KeyPairKind {
4745
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4846
match self {
49-
#[cfg(feature = "crypto")]
5047
Self::Ec(key_pair) => write!(f, "{:?}", key_pair),
51-
#[cfg(feature = "crypto")]
5248
Self::Ed(key_pair) => write!(f, "{:?}", key_pair),
53-
#[cfg(feature = "crypto")]
5449
Self::Rsa(key_pair, _) => write!(f, "{:?}", key_pair),
55-
Self::Remote(_) => write!(f, "Box<dyn RemotePrivateKey>"),
5650
}
5751
}
5852
}
@@ -64,12 +58,14 @@ impl fmt::Debug for KeyPairKind {
6458
/// `openssl genrsa` doesn't work. See ring's [documentation](ring::signature::RsaKeyPair::from_pkcs8)
6559
/// for how to generate RSA keys in the wanted format
6660
/// and conversion between the formats.
61+
#[cfg(feature = "crypto")]
6762
pub struct KeyPair {
6863
pub(crate) kind: KeyPairKind,
6964
pub(crate) alg: &'static SignatureAlgorithm,
7065
pub(crate) serialized_der: Vec<u8>,
7166
}
7267

68+
#[cfg(feature = "crypto")]
7369
impl fmt::Debug for KeyPair {
7470
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7571
f.debug_struct("KeyPair")
@@ -80,6 +76,7 @@ impl fmt::Debug for KeyPair {
8076
}
8177
}
8278

79+
#[cfg(feature = "crypto")]
8380
impl KeyPair {
8481
/// Generate a new random [`PKCS_ECDSA_P256_SHA256`] key pair
8582
#[cfg(feature = "crypto")]
@@ -187,15 +184,6 @@ impl KeyPair {
187184
Self::try_from(private_key.contents())
188185
}
189186

190-
/// Obtains the key pair from a raw public key and a remote private key
191-
pub fn from_remote(key_pair: Box<dyn SigningKey + Send + Sync>) -> Result<Self, Error> {
192-
Ok(Self {
193-
alg: key_pair.algorithm(),
194-
kind: KeyPairKind::Remote(key_pair),
195-
serialized_der: Vec::new(),
196-
})
197-
}
198-
199187
/// Obtains the key pair from a DER formatted key
200188
/// using the specified [`SignatureAlgorithm`]
201189
///
@@ -399,43 +387,12 @@ impl KeyPair {
399387
std::iter::once(self.alg)
400388
}
401389

402-
pub(crate) fn sign(&self, msg: &[u8], writer: DERWriter) -> Result<(), Error> {
403-
match &self.kind {
404-
#[cfg(feature = "crypto")]
405-
KeyPairKind::Ec(kp) => {
406-
let system_random = SystemRandom::new();
407-
let signature = kp.sign(&system_random, msg)._err()?;
408-
let sig = &signature.as_ref();
409-
writer.write_bitvec_bytes(sig, &sig.len() * 8);
410-
},
411-
#[cfg(feature = "crypto")]
412-
KeyPairKind::Ed(kp) => {
413-
let signature = kp.sign(msg);
414-
let sig = &signature.as_ref();
415-
writer.write_bitvec_bytes(sig, &sig.len() * 8);
416-
},
417-
#[cfg(feature = "crypto")]
418-
KeyPairKind::Rsa(kp, padding_alg) => {
419-
let system_random = SystemRandom::new();
420-
let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
421-
kp.sign(*padding_alg, &system_random, msg, &mut signature)
422-
._err()?;
423-
let sig = &signature.as_ref();
424-
writer.write_bitvec_bytes(sig, &sig.len() * 8);
425-
},
426-
KeyPairKind::Remote(kp) => {
427-
let signature = kp.sign(msg)?;
428-
writer.write_bitvec_bytes(&signature, &signature.len() * 8);
429-
},
430-
}
431-
Ok(())
432-
}
433-
434390
/// Return the key pair's public key in DER format
435391
///
436392
/// The key is formatted according to the SubjectPublicKeyInfo struct of
437393
/// X.509.
438394
/// See [RFC 5280 section 4.1](https://tools.ietf.org/html/rfc5280#section-4.1).
395+
#[cfg(feature = "crypto")]
439396
pub fn public_key_der(&self) -> Vec<u8> {
440397
yasna::construct_der(|writer| serialize_public_key_der(self, writer))
441398
}
@@ -454,11 +411,6 @@ impl KeyPair {
454411
///
455412
/// Panics if called on a remote key pair.
456413
pub fn serialize_der(&self) -> Vec<u8> {
457-
#[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
458-
if let KeyPairKind::Remote(_) = self.kind {
459-
panic!("Serializing a remote key pair is not supported")
460-
}
461-
462414
self.serialized_der.clone()
463415
}
464416

@@ -467,24 +419,9 @@ impl KeyPair {
467419
///
468420
/// Panics if called on a remote key pair.
469421
pub fn serialized_der(&self) -> &[u8] {
470-
#[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
471-
if let KeyPairKind::Remote(_) = self.kind {
472-
panic!("Serializing a remote key pair is not supported")
473-
}
474-
475422
&self.serialized_der
476423
}
477424

478-
/// Access the remote key pair if it is a remote one
479-
pub fn as_remote(&self) -> Option<&(dyn SigningKey + Send + Sync)> {
480-
#[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
481-
if let KeyPairKind::Remote(remote) = &self.kind {
482-
Some(remote.as_ref())
483-
} else {
484-
None
485-
}
486-
}
487-
488425
/// Serializes the key pair (including the private key) in PKCS#8 format in PEM
489426
#[cfg(feature = "pem")]
490427
pub fn serialize_pem(&self) -> String {
@@ -494,16 +431,34 @@ impl KeyPair {
494431
}
495432
}
496433

434+
#[cfg(feature = "crypto")]
435+
impl SigningKey for KeyPair {
436+
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
437+
Ok(match &self.kind {
438+
KeyPairKind::Ec(kp) => {
439+
let system_random = SystemRandom::new();
440+
let signature = kp.sign(&system_random, msg)._err()?;
441+
signature.as_ref().to_owned()
442+
},
443+
KeyPairKind::Ed(kp) => kp.sign(msg).as_ref().to_owned(),
444+
KeyPairKind::Rsa(kp, padding_alg) => {
445+
let system_random = SystemRandom::new();
446+
let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
447+
kp.sign(*padding_alg, &system_random, msg, &mut signature)
448+
._err()?;
449+
signature
450+
},
451+
})
452+
}
453+
}
454+
455+
#[cfg(feature = "crypto")]
497456
impl PublicKeyData for KeyPair {
498457
fn public_key_der(&self) -> &[u8] {
499458
match &self.kind {
500-
#[cfg(feature = "crypto")]
501459
KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
502-
#[cfg(feature = "crypto")]
503460
KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
504-
#[cfg(feature = "crypto")]
505461
KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(),
506-
KeyPairKind::Remote(kp) => kp.public_key_der(),
507462
}
508463
}
509464

@@ -635,7 +590,7 @@ pub enum RsaKeySize {
635590
}
636591

637592
pub(crate) fn sign_der(
638-
key: &KeyPair,
593+
key: &impl SigningKey,
639594
f: impl FnOnce(&mut DERWriterSeq<'_>) -> Result<(), Error>,
640595
) -> Result<Vec<u8>, Error> {
641596
yasna::try_construct_der(|writer| {
@@ -644,20 +599,19 @@ pub(crate) fn sign_der(
644599
writer.next().write_der(&data);
645600

646601
// Write signatureAlgorithm
647-
key.alg.write_alg_ident(writer.next());
602+
key.algorithm().write_alg_ident(writer.next());
648603

649604
// Write signature
650-
key.sign(&data, writer.next())?;
605+
let sig = key.sign(&data)?;
606+
let writer = writer.next();
607+
writer.write_bitvec_bytes(&sig, sig.len() * 8);
651608

652609
Ok(())
653610
})
654611
})
655612
}
656613

657614
/// A private key that is not directly accessible, but can be used to sign messages
658-
///
659-
/// Trait objects based on this trait can be passed to the [`KeyPair::from_remote`] function for generating certificates
660-
/// from a remote and raw private key, for example an HSM.
661615
pub trait SigningKey: PublicKeyData {
662616
/// Signs `msg` using the selected algorithm
663617
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error>;

0 commit comments

Comments
 (0)