Skip to content

Commit d7eaa09

Browse files
committed
x509-cert: adds a Builder trait for Certificate and CertReq
1 parent 6d70d44 commit d7eaa09

2 files changed

Lines changed: 108 additions & 93 deletions

File tree

x509-cert/src/builder.rs

Lines changed: 107 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,67 +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

383329
/// Builder for X509 Certificate Requests
384330
pub struct RequestBuilder<'s, S> {
385331
info: CertReqInfo,
386332
extension_req: ExtensionReq,
387-
signer: &'s S,
333+
req_signer: &'s S,
388334
}
389335

390336
impl<'s, S> RequestBuilder<'s, S>
@@ -393,9 +339,9 @@ where
393339
S::VerifyingKey: EncodePublicKey,
394340
{
395341
/// Creates a new certificate request builder
396-
pub fn new(subject: Name, signer: &'s S) -> Result<Self> {
342+
pub fn new(subject: Name, req_signer: &'s S) -> Result<Self> {
397343
let version = Default::default();
398-
let verifying_key = signer.verifying_key();
344+
let verifying_key = req_signer.verifying_key();
399345
let public_key = verifying_key
400346
.to_public_key_der()?
401347
.decode_msg::<SubjectPublicKeyInfoOwned>()?;
@@ -410,7 +356,7 @@ where
410356
attributes,
411357
},
412358
extension_req,
413-
signer,
359+
req_signer,
414360
})
415361
}
416362

@@ -422,53 +368,122 @@ where
422368

423369
Ok(())
424370
}
371+
}
425372

426-
fn finalize(&mut self) -> Result<()> {
427-
self.info
428-
.attributes
429-
.add(self.extension_req.clone().try_into()?);
430-
Ok(())
431-
}
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;
432382

433-
/// Run the certificate through the signer and build the end certificate.
434-
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>
435394
where
436-
S: Signer<Signature>,
395+
Self::Signer: Signer<Signature>,
437396
Signature: SignatureEncoding,
438397
{
439-
self.finalize()?;
398+
let blob = self.finalize()?;
440399

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

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

454-
/// Run the certificate through the signer and build the end certificate.
455-
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>
456408
where
457-
S: RandomizedSigner<Signature>,
409+
Self::Signer: RandomizedSigner<Signature>,
458410
Signature: SignatureEncoding,
459411
{
460-
self.finalize()?;
412+
let blob = self.finalize()?;
461413

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

466-
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 {
467484
info: self.info,
468485
algorithm,
469486
signature,
470-
};
471-
472-
Ok(req)
487+
})
473488
}
474489
}

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)