Skip to content

Commit be6d26f

Browse files
committed
x509-cert: adds a Builder trait for Certificate and CertReq
1 parent 9f19495 commit be6d26f

2 files changed

Lines changed: 109 additions & 93 deletions

File tree

x509-cert/src/builder.rs

Lines changed: 108 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ impl Profile {
258258
pub struct CertificateBuilder<'s, S> {
259259
tbs: TbsCertificate,
260260
extensions: Extensions,
261-
signer: &'s S,
261+
cert_signer: &'s S,
262262
}
263263

264264
impl<'s, S> CertificateBuilder<'s, S>
@@ -273,14 +273,14 @@ where
273273
mut validity: Validity,
274274
subject: Name,
275275
subject_public_key_info: SubjectPublicKeyInfoOwned,
276-
signer: &'s S,
276+
cert_signer: &'s S,
277277
) -> Result<Self> {
278-
let verifying_key = signer.verifying_key();
278+
let verifying_key = cert_signer.verifying_key();
279279
let signer_pub = verifying_key
280280
.to_public_key_der()?
281281
.decode_msg::<SubjectPublicKeyInfoOwned>()?;
282282

283-
let signature_alg = signer.signature_algorithm_identifier()?;
283+
let signature_alg = cert_signer.signature_algorithm_identifier()?;
284284
let issuer = profile.get_issuer(&subject);
285285

286286
validity.not_before.rfc5280_adjust_utc_time()?;
@@ -313,7 +313,7 @@ where
313313
Ok(Self {
314314
tbs,
315315
extensions,
316-
signer,
316+
cert_signer,
317317
})
318318
}
319319

@@ -324,66 +324,13 @@ where
324324

325325
Ok(())
326326
}
327-
328-
fn finalize(&mut self) {
329-
if !self.extensions.is_empty() {
330-
self.tbs.extensions = Some(self.extensions.clone());
331-
}
332-
333-
if self.tbs.extensions.is_none() {
334-
if self.tbs.issuer_unique_id.is_some() || self.tbs.subject_unique_id.is_some() {
335-
self.tbs.version = Version::V2;
336-
} else {
337-
self.tbs.version = Version::V1;
338-
}
339-
}
340-
}
341-
342-
/// Run the certificate through the signer and build the end certificate.
343-
pub fn build<Signature>(mut self) -> Result<Certificate>
344-
where
345-
S: Signer<Signature>,
346-
Signature: SignatureEncoding,
347-
{
348-
self.finalize();
349-
350-
let signature = self.signer.try_sign(&self.tbs.to_der()?)?;
351-
let signature = BitString::from_bytes(signature.to_bytes().as_ref())?;
352-
353-
let cert = Certificate {
354-
tbs_certificate: self.tbs.clone(),
355-
signature_algorithm: self.tbs.signature,
356-
signature,
357-
};
358-
359-
Ok(cert)
360-
}
361-
362-
/// Run the certificate through the signer and build the end certificate.
363-
pub fn build_with_rng<Signature>(mut self, rng: &mut impl CryptoRngCore) -> Result<Certificate>
364-
where
365-
S: RandomizedSigner<Signature>,
366-
Signature: SignatureEncoding,
367-
{
368-
self.finalize();
369-
370-
let signature = self.signer.try_sign_with_rng(rng, &self.tbs.to_der()?)?;
371-
let signature = BitString::from_bytes(signature.to_bytes().as_ref())?;
372-
373-
let cert = Certificate {
374-
tbs_certificate: self.tbs.clone(),
375-
signature_algorithm: self.tbs.signature,
376-
signature,
377-
};
378-
379-
Ok(cert)
380-
}
381327
}
382328

329+
/// Builder for X509 Certificate Requests
383330
pub struct RequestBuilder<'s, S> {
384331
info: CertReqInfo,
385332
extension_req: ExtensionReq,
386-
signer: &'s S,
333+
req_signer: &'s S,
387334
}
388335

389336
impl<'s, S> RequestBuilder<'s, S>
@@ -392,9 +339,9 @@ where
392339
S::VerifyingKey: EncodePublicKey,
393340
{
394341
/// Creates a new certificate request builder
395-
pub fn new(subject: Name, signer: &'s S) -> Result<Self> {
342+
pub fn new(subject: Name, req_signer: &'s S) -> Result<Self> {
396343
let version = Default::default();
397-
let verifying_key = signer.verifying_key();
344+
let verifying_key = req_signer.verifying_key();
398345
let public_key = verifying_key
399346
.to_public_key_der()?
400347
.decode_msg::<SubjectPublicKeyInfoOwned>()?;
@@ -409,7 +356,7 @@ where
409356
attributes,
410357
},
411358
extension_req,
412-
signer,
359+
req_signer,
413360
})
414361
}
415362

@@ -421,53 +368,122 @@ where
421368

422369
Ok(())
423370
}
371+
}
424372

425-
fn finalize(&mut self) -> Result<()> {
426-
self.info
427-
.attributes
428-
.add(self.extension_req.clone().try_into()?);
429-
Ok(())
430-
}
373+
/// Trait for X509 builders
374+
///
375+
/// This trait defines the interface between builder and the signers.
376+
pub trait Builder: Sized {
377+
/// The builder's object signer
378+
type Signer;
379+
380+
/// Type built by this builder
381+
type Output: Sized;
431382

432-
/// Run the certificate through the signer and build the end certificate.
433-
pub fn build<Signature>(mut self) -> Result<CertReq>
383+
/// Return a reference to the signer.
384+
fn signer(&self) -> &Self::Signer;
385+
386+
/// Assemble the final object from signature.
387+
fn assemble(self, signature: BitString) -> Result<Self::Output>;
388+
389+
/// Finalize and return a serialization of the object for signature.
390+
fn finalize(&mut self) -> der::Result<vec::Vec<u8>>;
391+
392+
/// Run the object through the signer and build it.
393+
fn build<Signature>(mut self) -> Result<Self::Output>
434394
where
435-
S: Signer<Signature>,
395+
Self::Signer: Signer<Signature>,
436396
Signature: SignatureEncoding,
437397
{
438-
self.finalize()?;
398+
let blob = self.finalize()?;
439399

440-
let algorithm = self.signer.signature_algorithm_identifier()?;
441-
let signature = self.signer.try_sign(&self.info.to_der()?)?;
400+
let signature = self.signer().try_sign(&blob)?;
442401
let signature = BitString::from_bytes(signature.to_bytes().as_ref())?;
443402

444-
let req = CertReq {
445-
info: self.info,
446-
algorithm,
447-
signature,
448-
};
449-
450-
Ok(req)
403+
self.assemble(signature)
451404
}
452405

453-
/// Run the certificate through the signer and build the end certificate.
454-
pub fn build_with_rng<Signature>(mut self, rng: &mut impl CryptoRngCore) -> Result<CertReq>
406+
/// Run the object through the signer and build it.
407+
fn build_with_rng<Signature>(mut self, rng: &mut impl CryptoRngCore) -> Result<Self::Output>
455408
where
456-
S: RandomizedSigner<Signature>,
409+
Self::Signer: RandomizedSigner<Signature>,
457410
Signature: SignatureEncoding,
458411
{
459-
self.finalize()?;
412+
let blob = self.finalize()?;
460413

461-
let algorithm = self.signer.signature_algorithm_identifier()?;
462-
let signature = self.signer.try_sign_with_rng(rng, &self.info.to_der()?)?;
414+
let signature = self.signer().try_sign_with_rng(rng, &blob)?;
463415
let signature = BitString::from_bytes(signature.to_bytes().as_ref())?;
464416

465-
let req = CertReq {
417+
self.assemble(signature)
418+
}
419+
}
420+
421+
impl<'s, S> Builder for CertificateBuilder<'s, S>
422+
where
423+
S: Keypair + DynSignatureAlgorithmIdentifier,
424+
S::VerifyingKey: EncodePublicKey,
425+
{
426+
type Signer = S;
427+
type Output = Certificate;
428+
429+
fn signer(&self) -> &Self::Signer {
430+
self.cert_signer
431+
}
432+
433+
fn finalize(&mut self) -> der::Result<vec::Vec<u8>> {
434+
if !self.extensions.is_empty() {
435+
self.tbs.extensions = Some(self.extensions.clone());
436+
}
437+
438+
if self.tbs.extensions.is_none() {
439+
if self.tbs.issuer_unique_id.is_some() || self.tbs.subject_unique_id.is_some() {
440+
self.tbs.version = Version::V2;
441+
} else {
442+
self.tbs.version = Version::V1;
443+
}
444+
}
445+
446+
self.tbs.to_der()
447+
}
448+
449+
fn assemble(self, signature: BitString) -> Result<Self::Output> {
450+
let signature_algorithm = self.tbs.signature.clone();
451+
452+
Ok(Certificate {
453+
tbs_certificate: self.tbs,
454+
signature_algorithm,
455+
signature,
456+
})
457+
}
458+
}
459+
460+
impl<'s, S> Builder for RequestBuilder<'s, S>
461+
where
462+
S: Keypair + DynSignatureAlgorithmIdentifier,
463+
S::VerifyingKey: EncodePublicKey,
464+
{
465+
type Signer = S;
466+
type Output = CertReq;
467+
468+
fn signer(&self) -> &Self::Signer {
469+
self.req_signer
470+
}
471+
472+
fn finalize(&mut self) -> der::Result<vec::Vec<u8>> {
473+
self.info
474+
.attributes
475+
.add(self.extension_req.clone().try_into()?)?;
476+
477+
self.info.to_der()
478+
}
479+
480+
fn assemble(self, signature: BitString) -> Result<Self::Output> {
481+
let algorithm = self.req_signer.signature_algorithm_identifier()?;
482+
483+
Ok(CertReq {
466484
info: self.info,
467485
algorithm,
468486
signature,
469-
};
470-
471-
Ok(req)
487+
})
472488
}
473489
}

x509-cert/tests/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use sha2::Sha256;
88
use spki::SubjectPublicKeyInfoOwned;
99
use std::{str::FromStr, time::Duration};
1010
use x509_cert::{
11-
builder::{CertificateBuilder, Profile, RequestBuilder},
11+
builder::{Builder, CertificateBuilder, Profile, RequestBuilder},
1212
ext::pkix::{name::GeneralName, SubjectAltName},
1313
name::Name,
1414
serial_number::SerialNumber,

0 commit comments

Comments
 (0)