Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

x509_cert/
builder.rs

1//! X509 Certificate builder
2
3use alloc::vec;
4use core::fmt;
5use der::{Encode, asn1::BitString, referenced::OwnedToRef};
6use signature::{
7    AsyncRandomizedSigner, AsyncSigner, Keypair, RandomizedSigner, Signer, rand_core::CryptoRng,
8};
9use spki::{
10    DynSignatureAlgorithmIdentifier, EncodePublicKey, ObjectIdentifier, SignatureBitStringEncoding,
11};
12
13use crate::{
14    AlgorithmIdentifier, SubjectPublicKeyInfo,
15    certificate::{self, Certificate, TbsCertificate, Version},
16    crl::{CertificateList, RevokedCert, TbsCertList},
17    ext::{
18        Extensions, ToExtension,
19        pkix::{AuthorityKeyIdentifier, CrlNumber, SubjectKeyIdentifier},
20    },
21    serial_number::SerialNumber,
22    time::{Time, Validity},
23};
24
25pub mod profile;
26
27use self::profile::BuilderProfile;
28
29#[deprecated(
30    since = "0.3.0",
31    note = "please use `x509_cert::builder::profile::BuilderProfile` instead"
32)]
33pub use self::profile::BuilderProfile as Profile;
34
35#[deprecated(
36    since = "0.3.0",
37    note = "please use `x509_cert::request::RequestBuilder` instead"
38)]
39pub use crate::request::RequestBuilder;
40
41pub(crate) const NULL_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("0.0.0");
42
43/// Error type
44#[derive(Debug)]
45#[non_exhaustive]
46pub enum Error {
47    /// ASN.1 DER-related errors.
48    Asn1(der::Error),
49
50    /// Public key errors propagated from the [`spki::Error`] type.
51    PublicKey(spki::Error),
52
53    /// Signing error propagated for the [`signature::Error`] type.
54    Signature(signature::Error),
55
56    /// Each RelativeDistinguishedName MUST contain exactly one AttributeTypeAndValue.
57    NonUniqueRdn,
58
59    /// Each Name MUST NOT contain more than one instance of a given
60    /// AttributeTypeAndValue across all RelativeDistinguishedNames unless explicitly
61    /// allowed in these Requirements
62    NonUniqueATV,
63
64    /// Non-ordered attribute or invalid attribute
65    InvalidAttribute {
66        /// Offending [`ObjectIdentifier`]
67        oid: ObjectIdentifier,
68    },
69
70    /// Not all required elements were specified
71    MissingAttributes,
72}
73
74impl core::error::Error for Error {}
75
76impl fmt::Display for Error {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        match self {
79            Error::Asn1(err) => write!(f, "ASN.1 error: {err}"),
80            Error::PublicKey(err) => write!(f, "public key error: {err}"),
81            Error::Signature(err) => write!(f, "signature error: {err}"),
82            Error::NonUniqueRdn => write!(
83                f,
84                "Each RelativeDistinguishedName MUST contain exactly one AttributeTypeAndValue."
85            ),
86            Error::NonUniqueATV => write!(
87                f,
88                "Each Name MUST NOT contain more than one instance of a given AttributeTypeAndValue"
89            ),
90            Error::InvalidAttribute { oid } => write!(
91                f,
92                "Non-ordered attribute or invalid attribute found (oid={oid})"
93            ),
94            Error::MissingAttributes => write!(f, "Not all required elements were specified"),
95        }
96    }
97}
98
99impl From<der::Error> for Error {
100    fn from(err: der::Error) -> Error {
101        Error::Asn1(err)
102    }
103}
104
105impl From<spki::Error> for Error {
106    fn from(err: spki::Error) -> Error {
107        Error::PublicKey(err)
108    }
109}
110
111impl From<signature::Error> for Error {
112    fn from(err: signature::Error) -> Error {
113        Error::Signature(err)
114    }
115}
116
117/// Result type
118pub type Result<T> = core::result::Result<T, Error>;
119
120/// X509 Certificate builder
121///
122#[cfg_attr(feature = "std", doc = "```")]
123#[cfg_attr(not(feature = "std"), doc = "```ignore")]
124/// use der::Decode;
125/// use x509_cert::spki::SubjectPublicKeyInfo;
126/// use x509_cert::builder::{CertificateBuilder, Builder, profile};
127/// use x509_cert::name::Name;
128/// use x509_cert::serial_number::SerialNumber;
129/// use x509_cert::time::Validity;
130/// use std::str::FromStr;
131///
132/// # const RSA_2048_DER: &[u8] = include_bytes!("../tests/examples/rsa2048-pub.der");
133/// # const RSA_2048_PRIV_DER: &[u8] = include_bytes!("../tests/examples/rsa2048-priv.der");
134/// # use rsa::{pkcs1v15::SigningKey, pkcs1::DecodeRsaPrivateKey};
135/// # use sha2::Sha256;
136/// # use std::time::Duration;
137/// # use der::referenced::RefToOwned;
138/// # fn rsa_signer() -> SigningKey<Sha256> {
139/// #     let private_key = rsa::RsaPrivateKey::from_pkcs1_der(RSA_2048_PRIV_DER).unwrap();
140/// #     let signing_key = SigningKey::<Sha256>::new(private_key);
141/// #     signing_key
142/// # }
143///
144/// let serial_number = SerialNumber::from(42u32);
145/// let validity = Validity::from_now(Duration::new(5, 0)).unwrap();
146/// let subject = Name::from_str("CN=World domination corporation,O=World domination Inc,C=US").unwrap();
147/// let profile = profile::cabf::Root::new(false,subject).expect("Create root profile");
148///
149/// let pub_key = SubjectPublicKeyInfo::try_from(RSA_2048_DER).expect("get rsa pub key");
150///
151/// let mut signer = rsa_signer();
152/// let mut builder = CertificateBuilder::new(
153///     profile,
154///     serial_number,
155///     validity,
156///     pub_key,
157/// )
158/// .expect("Create certificate builder");
159///
160/// let cert = builder.build(&signer).expect("Create certificate");
161/// ```
162pub struct CertificateBuilder<P> {
163    tbs: TbsCertificate,
164    extensions: Extensions,
165    profile: P,
166}
167
168impl<P> CertificateBuilder<P>
169where
170    P: BuilderProfile,
171{
172    /// Creates a new certificate builder
173    pub fn new(
174        profile: P,
175        serial_number: SerialNumber,
176        mut validity: Validity,
177        subject_public_key_info: SubjectPublicKeyInfo,
178    ) -> Result<Self> {
179        let signature_alg = AlgorithmIdentifier {
180            oid: NULL_OID,
181            parameters: None,
182        };
183
184        let subject = profile.get_subject();
185        let issuer = profile.get_issuer(&subject);
186
187        validity.not_before.rfc5280_adjust_utc_time()?;
188        validity.not_after.rfc5280_adjust_utc_time()?;
189
190        let tbs = TbsCertificate {
191            version: Version::V3,
192            serial_number,
193            signature: signature_alg,
194            issuer,
195            validity,
196            subject,
197            subject_public_key_info,
198            extensions: None,
199
200            // We will not generate unique identifier because as per RFC5280 Section 4.1.2.8:
201            //   CAs conforming to this profile MUST NOT generate
202            //   certificates with unique identifiers.
203            //
204            // https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.8
205            issuer_unique_id: None,
206            subject_unique_id: None,
207        };
208
209        let extensions = Extensions::default();
210        Ok(Self {
211            tbs,
212            extensions,
213            profile,
214        })
215    }
216
217    /// Add an extension to this certificate
218    ///
219    /// Extensions need to implement [`ToExtension`], examples may be found in
220    /// in [`ToExtension` documentation](../ext/trait.ToExtension.html#examples) or
221    /// [the implementors](../ext/trait.ToExtension.html#implementors).
222    pub fn add_extension<E: ToExtension>(
223        &mut self,
224        extension: E,
225    ) -> core::result::Result<(), E::Error> {
226        let ext = extension.to_extension(&self.tbs.subject, &self.extensions)?;
227        self.extensions.push(ext);
228        Ok(())
229    }
230}
231
232/// Trait for X509 builders
233///
234/// This trait defines the interface between builder and the signers.
235pub trait Builder: Sized {
236    /// Type built by this builder
237    type Output: Sized;
238
239    /// Assemble the final object from signature.
240    fn assemble<S>(self, signature: BitString, signer: &S) -> Result<Self::Output>
241    where
242        S: Keypair + DynSignatureAlgorithmIdentifier,
243        S::VerifyingKey: EncodePublicKey;
244
245    /// Finalize and return a serialization of the object for signature.
246    fn finalize<S>(&mut self, signer: &S) -> Result<vec::Vec<u8>>
247    where
248        S: Keypair + DynSignatureAlgorithmIdentifier,
249        S::VerifyingKey: EncodePublicKey;
250
251    /// Run the object through the signer and build it.
252    ///
253    /// # Notes
254    ///
255    /// When using ECDSA signers, the `Signature` parameter will need to be explicit
256    /// as multiple implementation of [`signature::Signer`] with various signature
257    /// are available.
258    ///
259    /// This would look like:
260    #[cfg_attr(feature = "std", doc = "```no_run")]
261    #[cfg_attr(not(feature = "std"), doc = "```ignore")]
262    /// # use p256::elliptic_curve::Generate;
263    /// # use rand::rng;
264    /// # use std::{
265    /// #     str::FromStr,
266    /// #     time::Duration
267    /// # };
268    /// # use x509_cert::{
269    /// #     builder::{self, CertificateBuilder, Builder},
270    /// #     name::Name,
271    /// #     serial_number::SerialNumber,
272    /// #     spki::SubjectPublicKeyInfo,
273    /// #     time::Validity
274    /// # };
275    /// #
276    /// # let mut rng = rng();
277    /// # let signer = p256::ecdsa::SigningKey::generate_from_rng(&mut rng);
278    /// # let builder = CertificateBuilder::new(
279    /// #     builder::profile::cabf::Root::new(
280    /// #         false,
281    /// #         Name::from_str("CN=World domination corporation").unwrap()
282    /// #     ).unwrap(),
283    /// #     SerialNumber::from(42u32),
284    /// #     Validity::from_now(Duration::new(5, 0)).unwrap(),
285    /// #     SubjectPublicKeyInfo::from_key(signer.verifying_key()).unwrap()
286    /// # ).unwrap();
287    /// let certificate = builder.build::<_, ecdsa::der::Signature<_>>(&signer).unwrap();
288    /// ```
289    fn build<S, Signature>(mut self, signer: &S) -> Result<Self::Output>
290    where
291        S: Signer<Signature>,
292        S: Keypair + DynSignatureAlgorithmIdentifier,
293        S::VerifyingKey: EncodePublicKey,
294        Signature: SignatureBitStringEncoding,
295    {
296        let blob = self.finalize(signer)?;
297
298        let signature = signer.try_sign(&blob)?.to_bitstring()?;
299
300        self.assemble(signature, signer)
301    }
302
303    /// Run the object through the signer and build it.
304    ///
305    /// # Notes
306    ///
307    /// When using ECDSA signers, the `Signature` parameter will need to be explicit
308    /// as multiple implementation of [`signature::Signer`] with various signature
309    /// are available.
310    ///
311    /// This would look like:
312    #[cfg_attr(feature = "std", doc = "```no_run")]
313    #[cfg_attr(not(feature = "std"), doc = "```ignore")]
314    /// # use p256::elliptic_curve::Generate;
315    /// # use rand::rng;
316    /// # use std::{
317    /// #     str::FromStr,
318    /// #     time::Duration
319    /// # };
320    /// # use x509_cert::{
321    /// #     builder::{self, CertificateBuilder, Builder},
322    /// #     name::Name,
323    /// #     serial_number::SerialNumber,
324    /// #     spki::SubjectPublicKeyInfo,
325    /// #     time::Validity
326    /// # };
327    /// #
328    /// # let mut rng = rng();
329    /// # let signer = p256::ecdsa::SigningKey::generate_from_rng(&mut rng);
330    /// # let builder = CertificateBuilder::new(
331    /// #     builder::profile::cabf::Root::new(
332    /// #         false,
333    /// #         Name::from_str("CN=World domination corporation").unwrap()
334    /// #     ).unwrap(),
335    /// #     SerialNumber::from(42u32),
336    /// #     Validity::from_now(Duration::new(5, 0)).unwrap(),
337    /// #     SubjectPublicKeyInfo::from_key(signer.verifying_key()).unwrap()
338    /// # ).unwrap();
339    /// let certificate = builder.build_with_rng::<_, ecdsa::der::Signature<_>, _>(
340    ///     &signer,
341    ///     &mut rng
342    /// ).unwrap();
343    /// ```
344    fn build_with_rng<S, Signature, R>(mut self, signer: &S, rng: &mut R) -> Result<Self::Output>
345    where
346        S: RandomizedSigner<Signature>,
347        S: Keypair + DynSignatureAlgorithmIdentifier,
348        S::VerifyingKey: EncodePublicKey,
349        Signature: SignatureBitStringEncoding,
350        R: CryptoRng + ?Sized,
351    {
352        let blob = self.finalize(signer)?;
353
354        let signature = signer.try_sign_with_rng(rng, &blob)?.to_bitstring()?;
355
356        self.assemble(signature, signer)
357    }
358}
359
360impl<P> Builder for CertificateBuilder<P>
361where
362    P: BuilderProfile,
363{
364    type Output = Certificate;
365
366    fn finalize<S>(&mut self, cert_signer: &S) -> Result<vec::Vec<u8>>
367    where
368        S: Keypair + DynSignatureAlgorithmIdentifier,
369        S::VerifyingKey: EncodePublicKey,
370    {
371        let verifying_key = cert_signer.verifying_key();
372        let signer_pub = SubjectPublicKeyInfo::from_key(&verifying_key)?;
373
374        self.tbs.signature = cert_signer.signature_algorithm_identifier()?;
375
376        let mut default_extensions = self.profile.build_extensions(
377            self.tbs.subject_public_key_info.owned_to_ref(),
378            signer_pub.owned_to_ref(),
379            &self.tbs,
380        )?;
381
382        self.extensions.append(&mut default_extensions);
383
384        if !self.extensions.is_empty() {
385            self.tbs.extensions = Some(self.extensions.clone());
386        }
387
388        if self.tbs.extensions.is_none() {
389            if self.tbs.issuer_unique_id.is_some() || self.tbs.subject_unique_id.is_some() {
390                self.tbs.version = Version::V2;
391            } else {
392                self.tbs.version = Version::V1;
393            }
394        }
395
396        self.tbs.to_der().map_err(Error::from)
397    }
398
399    fn assemble<S>(self, signature: BitString, _signer: &S) -> Result<Self::Output>
400    where
401        S: Keypair + DynSignatureAlgorithmIdentifier,
402        S::VerifyingKey: EncodePublicKey,
403    {
404        let signature_algorithm = self.tbs.signature.clone();
405
406        Ok(Certificate {
407            tbs_certificate: self.tbs,
408            signature_algorithm,
409            signature,
410        })
411    }
412}
413
414/// Trait for async X509 builders
415///
416/// This trait defines the interface between builder and the signers.
417///
418/// This is the async counterpart of [`Builder`].
419#[allow(async_fn_in_trait)]
420pub trait AsyncBuilder: Sized {
421    /// Type built by this builder
422    type Output: Sized;
423
424    /// Assemble the final object from signature.
425    fn assemble<S>(self, signature: BitString, signer: &S) -> Result<Self::Output>
426    where
427        S: Keypair + DynSignatureAlgorithmIdentifier,
428        S::VerifyingKey: EncodePublicKey;
429
430    /// Finalize and return a serialization of the object for signature.
431    fn finalize<S>(&mut self, signer: &S) -> Result<vec::Vec<u8>>
432    where
433        S: Keypair + DynSignatureAlgorithmIdentifier,
434        S::VerifyingKey: EncodePublicKey;
435
436    /// Run the object through the signer and build it.
437    ///
438    /// # Notes
439    ///
440    /// When using ECDSA signers, the `Signature` parameter will need to be explicit
441    /// as multiple implementation of [`signature::AsyncSigner`] with various signature
442    /// are available.
443    ///
444    /// This would look like:
445    #[cfg_attr(feature = "std", doc = "```no_run")]
446    #[cfg_attr(not(feature = "std"), doc = "```ignore")]
447    /// # use p256::elliptic_curve::Generate;
448    /// # use rand::rng;
449    /// # use std::{
450    /// #     str::FromStr,
451    /// #     time::Duration
452    /// # };
453    /// # use x509_cert::{
454    /// #     builder::{self, CertificateBuilder, AsyncBuilder},
455    /// #     name::Name,
456    /// #     serial_number::SerialNumber,
457    /// #     spki::SubjectPublicKeyInfo,
458    /// #     time::Validity
459    /// # };
460    /// #
461    /// # async fn build() -> builder::Result<()> {
462    /// # let mut rng = rng();
463    /// # let signer = p256::ecdsa::SigningKey::generate_from_rng(&mut rng);
464    /// # let builder = CertificateBuilder::new(
465    /// #     builder::profile::cabf::Root::new(
466    /// #         false,
467    /// #         Name::from_str("CN=World domination corporation").unwrap()
468    /// #     ).unwrap(),
469    /// #     SerialNumber::from(42u32),
470    /// #     Validity::from_now(Duration::new(5, 0)).unwrap(),
471    /// #     SubjectPublicKeyInfo::from_key(signer.verifying_key()).unwrap()
472    /// # ).unwrap();
473    /// let certificate = builder.build_async::<_, ecdsa::der::Signature<_>>(&signer).await?;
474    /// # Ok(())
475    /// # }
476    /// ```
477    async fn build_async<S, Signature>(mut self, signer: &S) -> Result<Self::Output>
478    where
479        S: AsyncSigner<Signature>,
480        S: Keypair + DynSignatureAlgorithmIdentifier,
481        S::VerifyingKey: EncodePublicKey,
482        Signature: SignatureBitStringEncoding,
483    {
484        let blob = self.finalize(signer)?;
485
486        let signature = signer.sign_async(&blob).await?.to_bitstring()?;
487
488        self.assemble(signature, signer)
489    }
490
491    /// Run the object through the signer and build it.
492    ///
493    /// # Notes
494    ///
495    /// When using ECDSA signers, the `Signature` parameter will need to be explicit
496    /// as multiple implementation of [`signature::AsyncSigner`] with various signature
497    /// are available.
498    ///
499    /// This would look like:
500    #[cfg_attr(feature = "std", doc = "```no_run")]
501    #[cfg_attr(not(feature = "std"), doc = "```ignore")]
502    /// # use p256::elliptic_curve::Generate;
503    /// # use rand::rng;
504    /// # use std::{
505    /// #     str::FromStr,
506    /// #     time::Duration
507    /// # };
508    /// # use x509_cert::{
509    /// #     builder::{self, CertificateBuilder, AsyncBuilder},
510    /// #     name::Name,
511    /// #     serial_number::SerialNumber,
512    /// #     spki::SubjectPublicKeyInfo,
513    /// #     time::Validity
514    /// # };
515    /// #
516    /// # async fn build() -> builder::Result<()> {
517    /// # let mut rng = rng();
518    /// # let signer = p256::ecdsa::SigningKey::generate_from_rng(&mut rng);
519    /// # let builder = CertificateBuilder::new(
520    /// #     builder::profile::cabf::Root::new(
521    /// #         false,
522    /// #         Name::from_str("CN=World domination corporation").unwrap()
523    /// #     ).unwrap(),
524    /// #     SerialNumber::from(42u32),
525    /// #     Validity::from_now(Duration::new(5, 0)).unwrap(),
526    /// #     SubjectPublicKeyInfo::from_key(signer.verifying_key()).unwrap()
527    /// # ).unwrap();
528    /// let certificate = builder.build_with_rng_async::<_, ecdsa::der::Signature<_>, _>(&signer, &mut rng).await?;
529    /// # Ok(())
530    /// # }
531    /// ```
532    async fn build_with_rng_async<S, Signature, R>(
533        mut self,
534        signer: &S,
535        rng: &mut R,
536    ) -> Result<Self::Output>
537    where
538        S: AsyncRandomizedSigner<Signature>,
539        S: Keypair + DynSignatureAlgorithmIdentifier,
540        S::VerifyingKey: EncodePublicKey,
541        Signature: SignatureBitStringEncoding,
542        R: CryptoRng + ?Sized,
543    {
544        let blob = self.finalize(signer)?;
545
546        let signature = signer
547            .try_sign_with_rng_async(rng, &blob)
548            .await?
549            .to_bitstring()?;
550
551        self.assemble(signature, signer)
552    }
553}
554
555impl<T> AsyncBuilder for T
556where
557    T: Builder,
558{
559    type Output = <T as Builder>::Output;
560
561    fn assemble<S>(self, signature: BitString, signer: &S) -> Result<Self::Output>
562    where
563        S: Keypair + DynSignatureAlgorithmIdentifier,
564        S::VerifyingKey: EncodePublicKey,
565    {
566        <T as Builder>::assemble(self, signature, signer)
567    }
568
569    fn finalize<S>(&mut self, signer: &S) -> Result<vec::Vec<u8>>
570    where
571        S: Keypair + DynSignatureAlgorithmIdentifier,
572        S::VerifyingKey: EncodePublicKey,
573    {
574        <T as Builder>::finalize(self, signer)
575    }
576}
577
578/// X.509 CRL builder
579pub struct CrlBuilder<P = certificate::Rfc5280>
580where
581    P: certificate::Profile,
582{
583    tbs: TbsCertList<P>,
584}
585
586impl<P> CrlBuilder<P>
587where
588    P: certificate::Profile,
589{
590    /// Create a `CrlBuilder` with the given issuer and the given monotonic [`CrlNumber`]
591    #[cfg(feature = "std")]
592    pub fn new(issuer: &Certificate, crl_number: CrlNumber) -> der::Result<Self> {
593        let this_update = Time::now()?;
594        Self::new_with_this_update(issuer, crl_number, this_update)
595    }
596
597    /// Create a `CrlBuilder` with the given issuer, a given monotonic [`CrlNumber`], and valid
598    /// from the given `this_update` start validity date.
599    pub fn new_with_this_update(
600        issuer: &Certificate,
601        crl_number: CrlNumber,
602        this_update: Time,
603    ) -> der::Result<Self> {
604        // Replaced later when the finalize is called
605        let signature_alg = AlgorithmIdentifier {
606            oid: NULL_OID,
607            parameters: None,
608        };
609
610        let issuer_name = issuer.tbs_certificate.subject().clone();
611
612        let mut crl_extensions = Extensions::new();
613        crl_extensions.push(crl_number.to_extension(&issuer_name, &crl_extensions)?);
614        let aki = match issuer
615            .tbs_certificate
616            .get_extension::<AuthorityKeyIdentifier>()?
617        {
618            Some((_, aki)) => aki,
619            None => {
620                let ski = SubjectKeyIdentifier::try_from(
621                    issuer
622                        .tbs_certificate
623                        .subject_public_key_info()
624                        .owned_to_ref(),
625                )?;
626                AuthorityKeyIdentifier {
627                    // KeyIdentifier must be the same as subjectKeyIdentifier
628                    key_identifier: Some(ski.0.clone()),
629                    // other fields must not be present.
630                    ..Default::default()
631                }
632            }
633        };
634        crl_extensions.push(aki.to_extension(&issuer_name, &crl_extensions)?);
635
636        let tbs = TbsCertList {
637            version: Version::V2,
638            signature: signature_alg,
639            issuer: issuer_name,
640            this_update,
641            next_update: None,
642            revoked_certificates: None,
643            crl_extensions: Some(crl_extensions),
644        };
645
646        Ok(Self { tbs })
647    }
648
649    /// Make the CRL valid until the given `next_update`
650    pub fn with_next_update(mut self, next_update: Option<Time>) -> Self {
651        self.tbs.next_update = next_update;
652        self
653    }
654
655    /// Add certificates to the revocation list
656    pub fn with_certificates<I>(mut self, revoked: I) -> Self
657    where
658        I: Iterator<Item = RevokedCert<P>>,
659    {
660        let certificates = self
661            .tbs
662            .revoked_certificates
663            .get_or_insert_with(vec::Vec::new);
664
665        let mut revoked: vec::Vec<RevokedCert<P>> = revoked.collect();
666        certificates.append(&mut revoked);
667
668        self
669    }
670}
671
672impl<P> Builder for CrlBuilder<P>
673where
674    P: certificate::Profile,
675{
676    type Output = CertificateList<P>;
677
678    fn finalize<S>(&mut self, cert_signer: &S) -> Result<vec::Vec<u8>>
679    where
680        S: Keypair + DynSignatureAlgorithmIdentifier,
681        S::VerifyingKey: EncodePublicKey,
682    {
683        self.tbs.signature = cert_signer.signature_algorithm_identifier()?;
684
685        self.tbs.to_der().map_err(Error::from)
686    }
687
688    fn assemble<S>(self, signature: BitString, _signer: &S) -> Result<Self::Output>
689    where
690        S: Keypair + DynSignatureAlgorithmIdentifier,
691        S::VerifyingKey: EncodePublicKey,
692    {
693        let signature_algorithm = self.tbs.signature.clone();
694
695        Ok(CertificateList {
696            tbs_cert_list: self.tbs,
697            signature_algorithm,
698            signature,
699        })
700    }
701}