Skip to main content

tsumiki_x509/
lib.rs

1//! # tsumiki-x509
2//!
3//! X.509 certificate parsing and handling.
4//!
5//! This crate implements [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280)
6//! with full support for X.509 v3 extensions.
7//!
8//! ## Features
9//!
10//! - Parse X.509 certificates (v1, v2, v3)
11//! - Type-safe extension access
12//! - Certificate chain handling
13//! - JSON/YAML serialization with serde
14//! - rustls integration (with `rustls` feature)
15//!
16//! ## Example
17//!
18//! ```no_run
19//! use std::str::FromStr;
20//! use tsumiki_x509::Certificate;
21//!
22//! let pem_data = "-----BEGIN CERTIFICATE-----
23//! ...
24//! -----END CERTIFICATE-----";
25//!
26//! let cert = Certificate::from_str(pem_data).unwrap();
27//!
28//! let tbs = cert.tbs_certificate();
29//! println!("Subject: {}", tbs.subject());
30//! println!("Issuer: {}", tbs.issuer());
31//! ```
32//!
33//! ## Type-Safe Extension Access
34//!
35//! ```no_run
36//! use tsumiki_x509::Certificate;
37//! use tsumiki_x509::extensions::BasicConstraints;
38//! use std::str::FromStr;
39//!
40//! let pem_data = "-----BEGIN CERTIFICATE-----
41//! ...
42//! -----END CERTIFICATE-----";
43//!
44//! let cert = Certificate::from_str(pem_data).unwrap();
45//!
46//! // Get extension with type safety
47//! if let Some(bc) = cert.extension::<BasicConstraints>().unwrap() {
48//!     println!("Is CA: {}", bc.ca);
49//!     if let Some(path_len) = bc.path_len_constraint {
50//!         println!("Path length: {}", path_len);
51//!     }
52//! }
53//! ```
54
55#![forbid(unsafe_code)]
56
57use std::fmt;
58use std::str::FromStr;
59
60use chrono::{Datelike, NaiveDateTime};
61use serde::{Deserialize, Serialize, ser::SerializeStruct};
62use tsumiki::decoder::{DecodableFrom, Decoder};
63use tsumiki::encoder::{EncodableTo, Encoder};
64use tsumiki_asn1::{ASN1Object, BitString, Element, Integer, ObjectIdentifier};
65use tsumiki_pem::{FromPem, Pem};
66use tsumiki_pkix_types::{
67    AlgorithmIdentifier, CertificateSerialNumber, Name, OidName, SubjectPublicKeyInfo,
68};
69
70use crate::error::{CertificateField, Error};
71use crate::extensions::{Extensions, ParsedExtensions};
72
73mod chain;
74pub mod error;
75pub mod extensions;
76#[cfg(feature = "rustls")]
77mod rustls;
78mod types;
79
80pub use chain::CertificateChain;
81
82/*
83https://datatracker.ietf.org/doc/html/rfc5280#section-4.1
84
85Certificate  ::=  SEQUENCE  {
86    tbsCertificate       TBSCertificate,
87    signatureAlgorithm   AlgorithmIdentifier,
88    signatureValue       BIT STRING
89}
90 */
91
92/// X.509 Certificate structure.
93///
94/// An X.509 certificate binds a public key to an identity (subject).
95/// It contains the certificate data (TBSCertificate), signature algorithm,
96/// and digital signature from the issuer.
97///
98/// Supports X.509 v1, v2, and v3 certificates with full extension support.
99///
100/// Defined in [RFC 5280 Section 4.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1).
101///
102/// # Example
103/// ```no_run
104/// use std::str::FromStr;
105/// use tsumiki_x509::Certificate;
106///
107/// let pem_data = "-----BEGIN CERTIFICATE-----
108/// ...
109/// -----END CERTIFICATE-----";
110///
111/// let cert = Certificate::from_str(pem_data).unwrap();
112/// println!("Subject: {}", cert.tbs_certificate().subject());
113/// ```
114#[derive(Debug, Clone, Deserialize)]
115pub struct Certificate {
116    tbs_certificate: TBSCertificate,
117    signature_algorithm: AlgorithmIdentifier,
118    signature_value: BitString, // BIT STRING
119}
120
121impl Serialize for Certificate {
122    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123    where
124        S: serde::Serializer,
125    {
126        let mut state = serializer.serialize_struct("Certificate", 3)?;
127
128        // Serialize TBSCertificate with RawExtensions
129        let tbs = SerializableTBSCertificate::try_from(&self.tbs_certificate)
130            .map_err(serde::ser::Error::custom)?;
131        state.serialize_field("tbs_certificate", &tbs)?;
132
133        state.serialize_field("signature_algorithm", &self.signature_algorithm)?;
134        state.serialize_field("signature_value", &self.signature_value)?;
135        state.end()
136    }
137}
138
139impl Certificate {
140    /// Get a specific extension by type.
141    ///
142    /// Returns `None` if the certificate has no extensions or the requested
143    /// extension is not present. Returns an error if parsing the extension fails.
144    ///
145    /// # Example
146    /// ```no_run
147    /// use std::str::FromStr;
148    /// use tsumiki_x509::Certificate;
149    /// use tsumiki_x509::extensions::BasicConstraints;
150    ///
151    /// let cert = Certificate::from_str("-----BEGIN CERTIFICATE-----...").unwrap();
152    /// if let Some(bc) = cert.extension::<BasicConstraints>().unwrap() {
153    ///     println!("Is CA: {}", bc.ca);
154    /// }
155    /// ```
156    pub fn extension<T: extensions::Extension>(&self) -> Result<Option<T>, Error> {
157        if let Some(ref exts) = self.tbs_certificate.extensions {
158            exts.extension::<T>()
159        } else {
160            Ok(None)
161        }
162    }
163
164    /// Get the TBS (To Be Signed) certificate
165    pub fn tbs_certificate(&self) -> &TBSCertificate {
166        &self.tbs_certificate
167    }
168
169    /// Get the signature algorithm
170    pub fn signature_algorithm(&self) -> &AlgorithmIdentifier {
171        &self.signature_algorithm
172    }
173
174    /// Get the signature value
175    pub fn signature_value(&self) -> &BitString {
176        &self.signature_value
177    }
178
179    /// Returns true if the certificate is self-signed.
180    ///
181    /// A certificate is considered self-signed if its Subject and Issuer are equal.
182    pub fn is_self_signed(&self) -> bool {
183        self.tbs_certificate.subject == self.tbs_certificate.issuer
184    }
185
186    /// Get a list of OIDs for all extensions present in the certificate
187    ///
188    /// Returns None if the certificate has no extensions (e.g., V1 certificates).
189    /// This is useful to check which extensions are present without parsing them.
190    ///
191    /// # Example
192    /// ```no_run
193    /// use std::str::FromStr;
194    /// use tsumiki_x509::Certificate;
195    ///
196    /// let cert = Certificate::from_str("-----BEGIN CERTIFICATE-----...").unwrap();
197    /// if let Some(oids) = cert.extension_oids() {
198    ///     for oid in oids {
199    ///         println!("Extension present: {}", oid);
200    ///     }
201    /// }
202    /// ```
203    pub fn extension_oids(&self) -> Option<Vec<ObjectIdentifier>> {
204        self.tbs_certificate.extensions.as_ref().map(|exts| {
205            exts.extensions()
206                .iter()
207                .map(|ext| ext.oid().clone())
208                .collect()
209        })
210    }
211}
212
213impl fmt::Display for Certificate {
214    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215        writeln!(f, "Certificate:")?;
216        writeln!(f, "    Data:")?;
217
218        // Version
219        let version_num = match self.tbs_certificate.version {
220            Version::V1 => 1,
221            Version::V2 => 2,
222            Version::V3 => 3,
223        };
224        writeln!(
225            f,
226            "        Version: {} (0x{})",
227            version_num,
228            version_num - 1
229        )?;
230
231        // Serial Number
232        let serial_bytes = self
233            .tbs_certificate
234            .serial_number
235            .as_ref()
236            .to_signed_bytes_be();
237        let serial_hex: Vec<String> = serial_bytes.iter().map(|b| format!("{:02x}", b)).collect();
238        writeln!(f, "        Serial Number: {}", serial_hex.join(":"))?;
239
240        // Signature Algorithm
241        let sig_alg = self
242            .tbs_certificate
243            .signature
244            .oid_name()
245            .map(|s| s.to_string())
246            .unwrap_or_else(|| self.tbs_certificate.signature.algorithm.to_string());
247        writeln!(f, "        Signature Algorithm: {}", sig_alg)?;
248
249        // Issuer
250        writeln!(f, "        Issuer: {}", self.tbs_certificate.issuer)?;
251
252        // Validity
253        writeln!(f, "        Validity")?;
254        writeln!(
255            f,
256            "            Not Before: {}",
257            self.tbs_certificate
258                .validity
259                .not_before
260                .format("%b %d %H:%M:%S %Y GMT")
261        )?;
262        writeln!(
263            f,
264            "            Not After : {}",
265            self.tbs_certificate
266                .validity
267                .not_after
268                .format("%b %d %H:%M:%S %Y GMT")
269        )?;
270
271        // Subject
272        writeln!(f, "        Subject: {}", self.tbs_certificate.subject)?;
273
274        // Subject Public Key Info
275        writeln!(f, "        Subject Public Key Info:")?;
276        let pubkey_alg = self
277            .tbs_certificate
278            .subject_public_key_info
279            .algorithm()
280            .oid_name()
281            .map(|s| s.to_string())
282            .unwrap_or_else(|| {
283                self.tbs_certificate
284                    .subject_public_key_info
285                    .algorithm()
286                    .algorithm
287                    .to_string()
288            });
289        writeln!(f, "            Public Key Algorithm: {}", pubkey_alg)?;
290
291        // Public Key (hex dump)
292        let pubkey_bytes = self
293            .tbs_certificate
294            .subject_public_key_info
295            .subject_public_key()
296            .as_bytes();
297        writeln!(
298            f,
299            "                Public-Key: ({} bit)",
300            pubkey_bytes.len() * 8
301        )?;
302        for chunk in pubkey_bytes.chunks(15) {
303            let hex_str: Vec<String> = chunk.iter().map(|b| format!("{:02x}", b)).collect();
304            writeln!(f, "                {}", hex_str.join(":"))?;
305        }
306
307        // Extensions
308        if let Some(ref _exts) = self.tbs_certificate.extensions {
309            writeln!(f, "        X509v3 extensions:")?;
310
311            // Subject Key Identifier
312            if let Ok(Some(ski)) = self.extension::<extensions::SubjectKeyIdentifier>() {
313                write!(f, "{}", ski)?;
314            }
315
316            // Authority Key Identifier
317            if let Ok(Some(aki)) = self.extension::<extensions::AuthorityKeyIdentifier>() {
318                write!(f, "{}", aki)?;
319            }
320
321            // Basic Constraints
322            if let Ok(Some(bc)) = self.extension::<extensions::BasicConstraints>() {
323                write!(f, "{}", bc)?;
324            }
325
326            // Key Usage
327            if let Ok(Some(ku)) = self.extension::<extensions::KeyUsage>() {
328                write!(f, "{}", ku)?;
329            }
330
331            // Extended Key Usage
332            if let Ok(Some(eku)) = self.extension::<extensions::ExtendedKeyUsage>() {
333                write!(f, "{}", eku)?;
334            }
335
336            // Subject Alternative Name
337            if let Ok(Some(san)) = self.extension::<extensions::SubjectAltName>() {
338                write!(f, "{}", san)?;
339            }
340
341            // Issuer Alternative Name
342            if let Ok(Some(ian)) = self.extension::<extensions::IssuerAltName>() {
343                write!(f, "{}", ian)?;
344            }
345
346            // Name Constraints
347            if let Ok(Some(nc)) = self.extension::<extensions::NameConstraints>() {
348                write!(f, "{}", nc)?;
349            }
350
351            // CRL Distribution Points
352            if let Ok(Some(cdp)) = self.extension::<extensions::CRLDistributionPoints>() {
353                write!(f, "{}", cdp)?;
354            }
355
356            // Certificate Policies
357            if let Ok(Some(cp)) = self.extension::<extensions::CertificatePolicies>() {
358                write!(f, "{}", cp)?;
359            }
360
361            // Policy Mappings
362            if let Ok(Some(pm)) = self.extension::<extensions::PolicyMappings>() {
363                write!(f, "{}", pm)?;
364            }
365
366            // Policy Constraints
367            if let Ok(Some(pc)) = self.extension::<extensions::PolicyConstraints>() {
368                write!(f, "{}", pc)?;
369            }
370
371            // Freshest CRL
372            if let Ok(Some(fcrl)) = self.extension::<extensions::FreshestCRL>() {
373                write!(f, "{}", fcrl)?;
374            }
375
376            // Inhibit Any Policy
377            if let Ok(Some(iap)) = self.extension::<extensions::InhibitAnyPolicy>() {
378                write!(f, "{}", iap)?;
379            }
380
381            // Authority Info Access
382            if let Ok(Some(aia)) = self.extension::<extensions::AuthorityInfoAccess>() {
383                write!(f, "{}", aia)?;
384            }
385
386            // Display any other extensions not explicitly handled above
387            let handled_oids = vec![
388                "2.5.29.14",         // SubjectKeyIdentifier
389                "2.5.29.35",         // AuthorityKeyIdentifier
390                "2.5.29.19",         // BasicConstraints
391                "2.5.29.15",         // KeyUsage
392                "2.5.29.37",         // ExtendedKeyUsage
393                "2.5.29.17",         // SubjectAltName
394                "2.5.29.18",         // IssuerAltName
395                "2.5.29.30",         // NameConstraints
396                "2.5.29.31",         // CRLDistributionPoints
397                "2.5.29.32",         // CertificatePolicies
398                "2.5.29.33",         // PolicyMappings
399                "2.5.29.36",         // PolicyConstraints
400                "2.5.29.46",         // FreshestCRL
401                "2.5.29.54",         // InhibitAnyPolicy
402                "1.3.6.1.5.5.7.1.1", // AuthorityInfoAccess
403            ];
404
405            if let Some(ref exts) = self.tbs_certificate.extensions {
406                for raw_ext in exts.extensions() {
407                    let oid_str = raw_ext.oid().to_string();
408                    if !handled_oids.contains(&oid_str.as_str()) {
409                        let ext_name = raw_ext.oid_name().unwrap_or(&oid_str);
410                        let critical = if raw_ext.critical() { " critical" } else { "" };
411                        writeln!(f, "            X509v3 {}:{}", ext_name, critical)?;
412                        // Display raw value as hex
413                        let value_bytes = raw_ext.value().as_bytes();
414                        if value_bytes.len() <= 32 {
415                            let hex_str: Vec<String> =
416                                value_bytes.iter().map(|b| format!("{:02x}", b)).collect();
417                            writeln!(f, "                {}", hex_str.join(":"))?;
418                        } else {
419                            writeln!(f, "                <{} bytes>", value_bytes.len())?;
420                        }
421                    }
422                }
423            }
424        }
425
426        // Signature Algorithm (outer)
427        let sig_alg_outer = self
428            .signature_algorithm
429            .oid_name()
430            .map(|s| s.to_string())
431            .unwrap_or_else(|| self.signature_algorithm.algorithm.to_string());
432        writeln!(f, "    Signature Algorithm: {}", sig_alg_outer)?;
433
434        // Signature Value
435        let sig_bytes = self.signature_value.as_bytes();
436        for chunk in sig_bytes.chunks(18) {
437            let hex_str: Vec<String> = chunk.iter().map(|b| format!("{:02x}", b)).collect();
438            writeln!(f, "         {}", hex_str.join(":"))?;
439        }
440
441        Ok(())
442    }
443}
444
445impl DecodableFrom<ASN1Object> for Certificate {}
446
447impl Decoder<ASN1Object, Certificate> for ASN1Object {
448    type Error = Error;
449
450    fn decode(&self) -> Result<Certificate, Self::Error> {
451        let elements = self.elements();
452        if elements.len() != 1 {
453            return Err(Error::InvalidElementCount {
454                context: CertificateField::Certificate,
455                expected: "1",
456                actual: elements.len(),
457            });
458        }
459
460        elements.first().ok_or(Error::EmptyCertificate)?.decode()
461    }
462}
463
464impl DecodableFrom<Element> for Certificate {}
465
466impl Decoder<Element, Certificate> for Element {
467    type Error = Error;
468
469    fn decode(&self) -> Result<Certificate, Self::Error> {
470        match self {
471            Element::Sequence(elements) => {
472                if elements.len() != 3 {
473                    return Err(Error::InvalidElementCount {
474                        context: CertificateField::Certificate,
475                        expected: "3",
476                        actual: elements.len(),
477                    });
478                }
479
480                let (tbs_elem, sig_alg_elem, sig_val_elem) = match elements.as_slice() {
481                    [tbs, sig_alg, sig_val] => (tbs, sig_alg, sig_val),
482                    _ => {
483                        return Err(Error::InvalidElementCount {
484                            context: CertificateField::Certificate,
485                            expected: "3",
486                            actual: elements.len(),
487                        });
488                    }
489                };
490
491                // TBSCertificate
492                let tbs_certificate: TBSCertificate = tbs_elem.decode()?;
493
494                // signatureAlgorithm
495                let signature_algorithm: AlgorithmIdentifier = sig_alg_elem.decode()?;
496
497                // signatureValue (BIT STRING)
498                let signature_value = if let Element::BitString(bs) = sig_val_elem {
499                    bs.clone()
500                } else {
501                    return Err(Error::ExpectedBitString(CertificateField::SignatureValue));
502                };
503
504                Ok(Certificate {
505                    tbs_certificate,
506                    signature_algorithm,
507                    signature_value,
508                })
509            }
510            _ => Err(Error::ExpectedSequence(CertificateField::Certificate)),
511        }
512    }
513}
514
515impl EncodableTo<Certificate> for Element {}
516
517impl Encoder<Certificate, Element> for Certificate {
518    type Error = Error;
519
520    fn encode(&self) -> Result<Element, Self::Error> {
521        Ok(Element::Sequence(vec![
522            self.tbs_certificate.encode()?,
523            self.signature_algorithm.encode()?,
524            Element::BitString(self.signature_value.clone()),
525        ]))
526    }
527}
528
529impl EncodableTo<Certificate> for ASN1Object {}
530
531impl Encoder<Certificate, ASN1Object> for Certificate {
532    type Error = Error;
533
534    fn encode(&self) -> Result<ASN1Object, Self::Error> {
535        Ok(ASN1Object::new(vec![self.encode()?]))
536    }
537}
538
539// Pem -> Certificate decoder
540impl DecodableFrom<tsumiki_pem::Pem> for Certificate {}
541
542impl Decoder<tsumiki_pem::Pem, Certificate> for tsumiki_pem::Pem {
543    type Error = Error;
544
545    fn decode(&self) -> Result<Certificate, Self::Error> {
546        Certificate::from_pem(self)
547    }
548}
549
550impl tsumiki_pem::FromPem for Certificate {
551    type Error = Error;
552
553    fn expected_label() -> tsumiki_pem::Label {
554        tsumiki_pem::Label::Certificate
555    }
556
557    fn from_pem(pem: &tsumiki_pem::Pem) -> Result<Self, Self::Error> {
558        // Check label
559        if pem.label() != Self::expected_label() {
560            return Err(Error::UnexpectedPemLabel {
561                expected: Self::expected_label().to_string(),
562                got: pem.label().to_string(),
563            });
564        }
565
566        // Decode PEM to DER bytes
567        let der_bytes: Vec<u8> = pem.decode()?;
568        let der: tsumiki_der::Der = der_bytes.decode()?;
569
570        // Decode DER to ASN1Object
571        let asn1_obj = der
572            .decode()
573            .map_err(|_| Error::CertificateDerDecodeFailed)?;
574
575        // Get first element
576        let element = asn1_obj.elements().first().ok_or(Error::EmptyCertificate)?;
577
578        // Decode to Certificate
579        element.decode()
580    }
581}
582
583impl FromStr for Certificate {
584    type Err = Error;
585
586    fn from_str(s: &str) -> Result<Self, Self::Err> {
587        let pem = Pem::from_str(s)?;
588        Self::from_pem(&pem)
589    }
590}
591
592/*
593TBSCertificate  ::=  SEQUENCE  {
594     version         [0]  EXPLICIT Version DEFAULT v1,
595     serialNumber         CertificateSerialNumber,
596     signature            AlgorithmIdentifier,
597     issuer               Name,
598     validity             Validity,
599     subject              Name,
600     subjectPublicKeyInfo SubjectPublicKeyInfo,
601     issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
602                          -- If present, version MUST be v2 or v3
603     subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
604                              -- If present, version MUST be v2 or v3
605     extensions      [3]  EXPLICIT Extensions OPTIONAL
606                              -- If present, version MUST be v3
607}
608 */
609
610/// TBS (To Be Signed) Certificate structure.
611///
612/// Contains the actual certificate data that is signed by the issuer.
613/// This includes the subject, issuer, public key, validity period,
614/// and optional extensions.
615///
616/// The signature in the outer Certificate structure is computed over
617/// the DER encoding of this TBSCertificate.
618///
619/// Defined in [RFC 5280 Section 4.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1).
620#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
621pub struct TBSCertificate {
622    version: Version,
623    serial_number: CertificateSerialNumber,
624    signature: AlgorithmIdentifier,
625    issuer: Name,
626    validity: Validity,
627    subject: Name,
628    subject_public_key_info: SubjectPublicKeyInfo,
629    issuer_unique_id: Option<UniqueIdentifier>,
630    subject_unique_id: Option<UniqueIdentifier>,
631    extensions: Option<Extensions>,
632}
633
634impl TBSCertificate {
635    /// Get the extensions
636    pub fn extensions(&self) -> Option<&Extensions> {
637        self.extensions.as_ref()
638    }
639
640    /// Get the certificate version
641    pub fn version(&self) -> &Version {
642        &self.version
643    }
644
645    /// Get the serial number
646    pub fn serial_number(&self) -> &CertificateSerialNumber {
647        &self.serial_number
648    }
649
650    /// Get the signature algorithm
651    pub fn signature(&self) -> &AlgorithmIdentifier {
652        &self.signature
653    }
654
655    /// Get the issuer name
656    pub fn issuer(&self) -> &Name {
657        &self.issuer
658    }
659
660    /// Get the validity period
661    pub fn validity(&self) -> &Validity {
662        &self.validity
663    }
664
665    /// Get the subject name
666    pub fn subject(&self) -> &Name {
667        &self.subject
668    }
669
670    /// Get the subject public key info
671    pub fn subject_public_key_info(&self) -> &SubjectPublicKeyInfo {
672        &self.subject_public_key_info
673    }
674}
675
676impl EncodableTo<TBSCertificate> for Element {}
677
678impl Encoder<TBSCertificate, Element> for TBSCertificate {
679    type Error = Error;
680
681    fn encode(&self) -> Result<Element, Self::Error> {
682        let mut elements = Vec::new();
683
684        // version [0] EXPLICIT Version DEFAULT v1
685        // Only include version if not V1
686        if self.version != Version::V1 {
687            elements.push(self.version.encode()?);
688        }
689
690        // serialNumber
691        elements.push(self.serial_number.encode()?);
692
693        // signature
694        elements.push(self.signature.encode()?);
695
696        // issuer
697        elements.push(self.issuer.encode()?);
698
699        // validity
700        elements.push(self.validity.encode()?);
701
702        // subject
703        elements.push(self.subject.encode()?);
704
705        // subjectPublicKeyInfo
706        elements.push(self.subject_public_key_info.encode()?);
707
708        // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL
709        if let Some(ref issuer_uid) = self.issuer_unique_id {
710            let bit_string = issuer_uid.encode()?;
711            elements.push(Element::ContextSpecific {
712                slot: 1,
713                constructed: false,
714                element: Box::new(bit_string),
715            });
716        }
717
718        // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL
719        if let Some(ref subject_uid) = self.subject_unique_id {
720            let bit_string = subject_uid.encode()?;
721            elements.push(Element::ContextSpecific {
722                slot: 2,
723                constructed: false,
724                element: Box::new(bit_string),
725            });
726        }
727
728        // extensions [3] EXPLICIT Extensions OPTIONAL
729        if let Some(ref exts) = self.extensions {
730            elements.push(exts.encode()?);
731        }
732
733        Ok(Element::Sequence(elements))
734    }
735}
736
737impl DecodableFrom<Element> for TBSCertificate {}
738
739impl Decoder<Element, TBSCertificate> for Element {
740    type Error = Error;
741
742    fn decode(&self) -> Result<TBSCertificate, Self::Error> {
743        let Element::Sequence(elements) = self else {
744            return Err(Error::ExpectedSequence(CertificateField::TBSCertificate));
745        };
746
747        // V1 certificates have 6 required fields (no version field)
748        // V2/V3 certificates can have up to 10 fields (version + 6 required + 3 optional)
749        if elements.len() < 6 || elements.len() > 10 {
750            return Err(Error::InvalidElementCount {
751                context: CertificateField::TBSCertificate,
752                expected: "6-10",
753                actual: elements.len(),
754            });
755        }
756
757        let mut iter = elements.iter();
758
759        // version [0] EXPLICIT Version DEFAULT v1
760        let version =
761            if let Some(Element::ContextSpecific { slot: 0, .. }) = iter.as_slice().first() {
762                if let Some(elem) = iter.next() {
763                    elem.decode()?
764                } else {
765                    return Err(Error::MissingField(CertificateField::Version));
766                }
767            } else {
768                Version::V1 // DEFAULT v1
769            };
770
771        // serialNumber
772        let serial_number = if let Some(elem) = iter.next() {
773            elem.decode()?
774        } else {
775            return Err(Error::MissingField(CertificateField::SerialNumber));
776        };
777
778        // signature
779        let signature = if let Some(elem) = iter.next() {
780            elem.decode()?
781        } else {
782            return Err(Error::MissingField(CertificateField::Signature));
783        };
784
785        // issuer
786        let issuer = if let Some(elem) = iter.next() {
787            elem.decode()?
788        } else {
789            return Err(Error::MissingField(CertificateField::Issuer));
790        };
791
792        // validity
793        let validity = if let Some(elem) = iter.next() {
794            elem.decode()?
795        } else {
796            return Err(Error::MissingField(CertificateField::Validity));
797        };
798
799        // subject
800        let subject = if let Some(elem) = iter.next() {
801            elem.decode()?
802        } else {
803            return Err(Error::MissingField(CertificateField::Subject));
804        };
805
806        // subjectPublicKeyInfo
807        let subject_public_key_info = if let Some(elem) = iter.next() {
808            elem.decode()?
809        } else {
810            return Err(Error::MissingField(CertificateField::SubjectPublicKeyInfo));
811        };
812
813        // Optional fields: issuerUniqueID [1], subjectUniqueID [2], extensions [3]
814        let (issuer_unique_id, subject_unique_id, extensions) = iter.try_fold(
815            (None, None, None),
816            |(issuer_uid, subject_uid, exts), elem| match elem {
817                Element::ContextSpecific { slot: 1, .. } if issuer_uid.is_none() => {
818                    Ok((Some(elem.decode()?), subject_uid, exts))
819                }
820                Element::ContextSpecific { slot: 2, .. } if subject_uid.is_none() => {
821                    Ok((issuer_uid, Some(elem.decode()?), exts))
822                }
823                Element::ContextSpecific { slot: 3, .. } if exts.is_none() => {
824                    Ok((issuer_uid, subject_uid, Some(elem.decode()?)))
825                }
826                _ => Err(Error::UnexpectedElement(CertificateField::TBSCertificate)),
827            },
828        )?;
829
830        Ok(TBSCertificate {
831            version,
832            serial_number,
833            signature,
834            issuer,
835            validity,
836            subject,
837            subject_public_key_info,
838            issuer_unique_id,
839            subject_unique_id,
840            extensions,
841        })
842    }
843}
844
845/*
846Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
847
848CertificateSerialNumber  ::=  INTEGER
849
850
851Time ::= CHOICE {
852    utcTime        UTCTime,
853    generalTime    GeneralizedTime
854}
855
856UniqueIdentifier  ::=  BIT STRING
857
858SubjectPublicKeyInfo is now provided by pkix-types
859
860Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
861*/
862
863/// Unique identifier for issuer or subject.
864///
865/// UniqueIdentifier is a BIT STRING used in X.509 v2 certificates to provide
866/// unique identifiers for certificate issuers and subjects when names are reused.
867///
868/// Defined in [RFC 5280 Section 4.1.2.8](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.8).
869///
870/// **Note**: RFC 5280 specifies that CAs conforming to this profile MUST NOT
871/// generate certificates with unique identifiers. This field is deprecated and
872/// should not be used in new certificates.
873///
874/// In TBSCertificate, these appear as context-specific tagged fields:
875/// - issuerUniqueID \[1\] IMPLICIT UniqueIdentifier OPTIONAL
876/// - subjectUniqueID \[2\] IMPLICIT UniqueIdentifier OPTIONAL
877#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
878pub struct UniqueIdentifier(BitString);
879
880impl UniqueIdentifier {
881    pub fn new(bit_string: BitString) -> Self {
882        UniqueIdentifier(bit_string)
883    }
884}
885
886impl AsRef<BitString> for UniqueIdentifier {
887    fn as_ref(&self) -> &BitString {
888        &self.0
889    }
890}
891
892impl From<UniqueIdentifier> for BitString {
893    fn from(uid: UniqueIdentifier) -> Self {
894        uid.0
895    }
896}
897
898impl EncodableTo<UniqueIdentifier> for Element {}
899
900impl Encoder<UniqueIdentifier, Element> for UniqueIdentifier {
901    type Error = Error;
902
903    fn encode(&self) -> Result<Element, Self::Error> {
904        // UniqueIdentifier needs context-specific tagging [1] or [2] IMPLICIT
905        // This is handled by the caller (TBSCertificate encoder)
906        // Here we just return the BitString element
907        Ok(Element::BitString(self.0.clone()))
908    }
909}
910
911impl DecodableFrom<Element> for UniqueIdentifier {}
912
913impl Decoder<Element, UniqueIdentifier> for Element {
914    type Error = Error;
915
916    fn decode(&self) -> Result<UniqueIdentifier, Self::Error> {
917        // UniqueIdentifier appears as [1] IMPLICIT or [2] IMPLICIT UniqueIdentifier
918        // IMPLICIT tagging means the element directly contains the BitString data
919        match self {
920            Element::ContextSpecific { slot, element, .. } => {
921                if *slot != 1 && *slot != 2 {
922                    return Err(Error::UniqueIdentifierInvalidTag(*slot));
923                }
924                // IMPLICIT tagging: element is directly the BitString
925                match element.as_ref() {
926                    Element::BitString(bit_string) => Ok(UniqueIdentifier(bit_string.clone())),
927                    _ => Err(Error::UniqueIdentifierExpectedBitString),
928                }
929            }
930            Element::BitString(bit_string) => Ok(UniqueIdentifier(bit_string.clone())), // Allow direct BitString for testing
931            _ => Err(Error::UniqueIdentifierInvalidElement),
932        }
933    }
934}
935
936/*
937Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
938
939Extension  ::=  SEQUENCE  {
940    extnID      OBJECT IDENTIFIER,
941    critical    BOOLEAN DEFAULT FALSE,
942    extnValue   OCTET STRING
943                -- contains the DER encoding of an ASN.1 value
944                -- corresponding to the extension type identified
945                -- by extnID
946}
947*/
948
949/// X.509 certificate version.
950///
951/// Indicates the version of the encoded certificate:
952/// - V1: Basic certificate (no extensions, no unique identifiers)
953/// - V2: Added issuerUniqueID and subjectUniqueID fields (rarely used)
954/// - V3: Added extensions support (most common modern format)
955///
956/// Defined in [RFC 5280 Section 4.1.2.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.1).
957///
958/// In TBSCertificate, this appears as:
959/// - \[0\] EXPLICIT Version with DEFAULT v1
960/// - If the \[0\] tag is absent, the version defaults to V1
961/// - V2 and V3 certificates must include the version field
962#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
963pub enum Version {
964    /// Version 1: Basic certificate format
965    V1 = 0,
966    /// Version 2: Adds unique identifiers (deprecated)
967    V2 = 1,
968    /// Version 3: Adds extensions support (modern standard)
969    V3 = 2,
970}
971
972impl DecodableFrom<Element> for Version {}
973
974impl Decoder<Element, Version> for Element {
975    type Error = Error;
976
977    fn decode(&self) -> Result<Version, Self::Error> {
978        // Version appears as [0] EXPLICIT Version in TBSCertificate
979        // This means Element::ContextSpecific { slot: 0, element: Box<Element::Integer> }
980        let integer = match self {
981            Element::ContextSpecific { slot, element, .. } => {
982                if *slot != 0 {
983                    return Err(Error::InvalidVersion(format!(
984                        "expected context-specific tag [0], got [{}]",
985                        slot
986                    )));
987                }
988                // EXPLICIT tagging: element contains the full INTEGER
989                match element.as_ref() {
990                    Element::Integer(i) => i,
991                    _ => {
992                        return Err(Error::InvalidVersion(
993                            "expected Integer inside context-specific tag [0]".to_string(),
994                        ));
995                    }
996                }
997            }
998            _ => {
999                return Err(Error::InvalidVersion(
1000                    "expected context-specific tag [0] for Version".to_string(),
1001                ));
1002            }
1003        };
1004
1005        match u64::try_from(integer).map_err(Error::InvalidASN1)? {
1006            0 => Ok(Version::V1),
1007            1 => Ok(Version::V2),
1008            2 => Ok(Version::V3),
1009            v => Err(Error::InvalidVersion(format!(
1010                "unknown version value: {}",
1011                v
1012            ))),
1013        }
1014    }
1015}
1016
1017impl EncodableTo<Version> for Element {}
1018
1019impl Encoder<Version, Element> for Version {
1020    type Error = Error;
1021
1022    fn encode(&self) -> Result<Element, Self::Error> {
1023        let version_value = *self as i64;
1024        let version_int = Integer::from(version_value.to_be_bytes().to_vec());
1025        Ok(Element::ContextSpecific {
1026            slot: 0,
1027            constructed: true,
1028            element: Box::new(Element::Integer(version_int)),
1029        })
1030    }
1031}
1032
1033// CertificateSerialNumber is now in pkix-types crate
1034// No need for adapter implementations - pkix-types provides the Encoder/Decoder traits
1035
1036// https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5
1037/*
1038Validity ::= SEQUENCE {
1039    notBefore      Time,
1040    notAfter       Time
1041}
1042*/
1043
1044/// Certificate validity period.
1045///
1046/// Specifies the time interval during which the CA warrants that it will
1047/// maintain information about the status of the certificate.
1048///
1049/// The validity period is defined by two dates:
1050/// - `not_before`: Certificate is not valid before this date
1051/// - `not_after`: Certificate is not valid after this date
1052///
1053/// Defined in [RFC 5280 Section 4.1.2.5](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5).
1054///
1055/// # Time Encoding
1056/// RFC 5280 specifies:
1057/// - UTCTime for dates from 1950 to 2049
1058/// - GeneralizedTime for dates outside this range
1059#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1060pub struct Validity {
1061    not_before: NaiveDateTime,
1062    not_after: NaiveDateTime,
1063}
1064
1065impl Validity {
1066    /// Get the not before date
1067    pub fn not_before(&self) -> &NaiveDateTime {
1068        &self.not_before
1069    }
1070
1071    /// Get the not after date
1072    pub fn not_after(&self) -> &NaiveDateTime {
1073        &self.not_after
1074    }
1075}
1076
1077impl DecodableFrom<Element> for Validity {}
1078
1079impl Decoder<Element, Validity> for Element {
1080    type Error = Error;
1081
1082    fn decode(&self) -> Result<Validity, Self::Error> {
1083        if let Element::Sequence(elements) = self {
1084            if elements.len() != 2 {
1085                return Err(Error::ValidityInvalidElementCount);
1086            }
1087            let not_before = match &elements[0] {
1088                Element::UTCTime(dt) => *dt,
1089                Element::GeneralizedTime(dt) => *dt,
1090                _ => return Err(Error::ValidityInvalidNotBefore),
1091            };
1092            let not_after = match &elements[1] {
1093                Element::UTCTime(dt) => *dt,
1094                Element::GeneralizedTime(dt) => *dt,
1095                _ => return Err(Error::ValidityInvalidNotAfter),
1096            };
1097            Ok(Validity {
1098                not_before,
1099                not_after,
1100            })
1101        } else {
1102            Err(Error::ValidityExpectedSequence)
1103        }
1104    }
1105}
1106
1107impl EncodableTo<Validity> for Element {}
1108
1109impl Encoder<Validity, Element> for Validity {
1110    type Error = Error;
1111
1112    fn encode(&self) -> Result<Element, Self::Error> {
1113        // RFC 5280: Use UTCTime for years 1950-2049, GeneralizedTime otherwise
1114        let not_before_elm = if self.not_before.year() >= 1950 && self.not_before.year() < 2050 {
1115            Element::UTCTime(self.not_before)
1116        } else {
1117            Element::GeneralizedTime(self.not_before)
1118        };
1119
1120        let not_after_elm = if self.not_after.year() >= 1950 && self.not_after.year() < 2050 {
1121            Element::UTCTime(self.not_after)
1122        } else {
1123            Element::GeneralizedTime(self.not_after)
1124        };
1125
1126        Ok(Element::Sequence(vec![not_before_elm, not_after_elm]))
1127    }
1128}
1129
1130// Serialization helper for TBSCertificate with parsed extensions
1131
1132#[derive(Debug, Clone, Serialize)]
1133struct SerializableTBSCertificate {
1134    version: Version,
1135    serial_number: CertificateSerialNumber,
1136    signature: AlgorithmIdentifier,
1137    issuer: Name,
1138    validity: Validity,
1139    subject: Name,
1140    subject_public_key_info: SubjectPublicKeyInfo,
1141    #[serde(skip_serializing_if = "Option::is_none")]
1142    issuer_unique_id: Option<UniqueIdentifier>,
1143    #[serde(skip_serializing_if = "Option::is_none")]
1144    subject_unique_id: Option<UniqueIdentifier>,
1145    #[serde(skip_serializing_if = "Option::is_none")]
1146    extensions: Option<ParsedExtensions>,
1147}
1148
1149impl TryFrom<&TBSCertificate> for SerializableTBSCertificate {
1150    type Error = Error;
1151
1152    fn try_from(tbs: &TBSCertificate) -> Result<Self, Self::Error> {
1153        let extensions = if let Some(ref exts) = tbs.extensions {
1154            Some(ParsedExtensions::from_extensions(exts)?)
1155        } else {
1156            None
1157        };
1158
1159        Ok(SerializableTBSCertificate {
1160            version: tbs.version,
1161            serial_number: tbs.serial_number.clone(),
1162            signature: tbs.signature.clone(),
1163            issuer: tbs.issuer.clone(),
1164            validity: tbs.validity.clone(),
1165            subject: tbs.subject.clone(),
1166            subject_public_key_info: tbs.subject_public_key_info.clone(),
1167            issuer_unique_id: tbs.issuer_unique_id.clone(),
1168            subject_unique_id: tbs.subject_unique_id.clone(),
1169            extensions,
1170        })
1171    }
1172}
1173
1174// Helper functions for Display implementation
1175
1176#[cfg(test)]
1177mod tests {
1178    use super::*;
1179    use crate::extensions::{Extension, Extensions, RawExtension};
1180    use chrono::NaiveDate;
1181    use rstest::rstest;
1182    use std::str::FromStr;
1183    use tsumiki_asn1::{BitString, OctetString};
1184    use tsumiki_der::Der;
1185    use tsumiki_pem::Pem;
1186    use tsumiki_pkix_types::{AlgorithmParameters, RawAlgorithmParameter};
1187    use tsumiki_pkix_types::{AttributeTypeAndValue, Name, RelativeDistinguishedName};
1188
1189    // AlgorithmIdentifier tests
1190    #[rstest(
1191        input,
1192        expected,
1193        // Test case: Algorithm without parameters (None = Absent)
1194        case(
1195            Element::Sequence(vec![
1196                Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap()), // sha256WithRSAEncryption
1197            ]),
1198            AlgorithmIdentifier {
1199                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap(),
1200                parameters: None,
1201            }
1202        ),
1203        // Test case: Algorithm with NULL parameters
1204        case(
1205            Element::Sequence(vec![
1206                Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap()),
1207                Element::Null,
1208            ]),
1209            AlgorithmIdentifier {
1210                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap(),
1211                parameters: Some(AlgorithmParameters::Null),
1212            }
1213        ),
1214        // Test case: Algorithm with OctetString parameters
1215        case(
1216            Element::Sequence(vec![
1217                Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_ECDSA_WITH_SHA256).unwrap()), // ecdsa-with-SHA256
1218                Element::OctetString(tsumiki_asn1::OctetString::from(vec![0x01, 0x02, 0x03])),
1219            ]),
1220            AlgorithmIdentifier {
1221                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_ECDSA_WITH_SHA256).unwrap(),
1222                parameters: Some(AlgorithmParameters::Other(
1223                    RawAlgorithmParameter::new(Element::OctetString(tsumiki_asn1::OctetString::from(vec![0x01, 0x02, 0x03])))
1224                )),
1225            }
1226        ),
1227        // Test case: Algorithm with OID parameters - ECDSA curve
1228        case(
1229            Element::Sequence(vec![
1230                Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap()), // ecPublicKey
1231                Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()), // secp256r1 (prime256v1)
1232            ]),
1233            AlgorithmIdentifier {
1234                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(),
1235                parameters: Some(AlgorithmParameters::Other(
1236                    RawAlgorithmParameter::new(Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()))
1237                )),
1238            }
1239        )
1240    )]
1241    fn test_algorithm_identifier_decode_success(input: Element, expected: AlgorithmIdentifier) {
1242        let result: AlgorithmIdentifier = input.decode().unwrap();
1243        assert_eq!(result, expected);
1244    }
1245
1246    #[rstest(
1247        input,
1248        expected_error_variant,
1249        // Test case: Not a Sequence
1250        case(
1251            Element::Integer(Integer::from(vec![0x01])),
1252            "ExpectedSequence"
1253        ),
1254        // Test case: Empty sequence
1255        case(
1256            Element::Sequence(vec![]),
1257            "EmptyAlgorithmIdentifier"
1258        ),
1259        // Test case: Too many elements
1260        case(
1261            Element::Sequence(vec![
1262                Element::ObjectIdentifier(ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap()),
1263                Element::Null,
1264                Element::Integer(Integer::from(vec![0x01])),
1265            ]),
1266            "TooManyElements"
1267        ),
1268        // Test case: First element is not ObjectIdentifier
1269        case(
1270            Element::Sequence(vec![
1271                Element::Integer(Integer::from(vec![0x01])),
1272            ]),
1273            "ExpectedOidForAlgorithm"
1274        )
1275    )]
1276    fn test_algorithm_identifier_decode_failure(input: Element, expected_error_variant: &str) {
1277        let result: Result<AlgorithmIdentifier, _> = input.decode();
1278        assert!(result.is_err());
1279        let err = result.unwrap_err();
1280        let err_str = format!("{:?}", err);
1281        assert!(
1282            err_str.contains(expected_error_variant),
1283            "Expected error '{}', but got '{}'",
1284            expected_error_variant,
1285            err_str
1286        );
1287    }
1288
1289    // Version tests
1290    #[rstest]
1291    #[case::v1(
1292        Element::ContextSpecific {
1293            constructed: true,
1294            slot: 0,
1295            element: Box::new(Element::Integer(Integer::from(vec![0x00])))
1296        },
1297        Version::V1
1298    )]
1299    #[case::v2(
1300        Element::ContextSpecific {
1301            constructed: true,
1302            slot: 0,
1303            element: Box::new(Element::Integer(Integer::from(vec![0x01])))
1304        },
1305        Version::V2
1306    )]
1307    #[case::v3(
1308        Element::ContextSpecific {
1309            constructed: true,
1310            slot: 0,
1311            element: Box::new(Element::Integer(Integer::from(vec![0x02])))
1312        },
1313        Version::V3
1314    )]
1315    fn test_version_decode_success(#[case] input: Element, #[case] expected: Version) {
1316        let result: Result<Version, Error> = input.decode();
1317        assert!(result.is_ok());
1318        assert_eq!(result.unwrap(), expected);
1319    }
1320
1321    #[rstest]
1322    #[case::null(Element::Null, "InvalidVersion")]
1323    #[case::direct_integer(Element::Integer(Integer::from(vec![0x00])), "InvalidVersion")]
1324    #[case::invalid_version_value(
1325        Element::ContextSpecific {
1326            constructed: true,
1327            slot: 0,
1328            element: Box::new(Element::Integer(Integer::from(vec![0x03])))
1329        },
1330        "InvalidVersion"
1331    )]
1332    #[case::wrong_slot(
1333        Element::ContextSpecific {
1334            constructed: true,
1335            slot: 1,
1336            element: Box::new(Element::Integer(Integer::from(vec![0x00])))
1337        },
1338        "InvalidVersion"
1339    )]
1340    #[case::not_integer_inside(
1341        Element::ContextSpecific {
1342            constructed: true,
1343            slot: 0,
1344            element: Box::new(Element::Null)
1345        },
1346        "InvalidVersion"
1347    )]
1348    #[case::octet_string(Element::OctetString(tsumiki_asn1::OctetString::from(vec![0x00])), "InvalidVersion")]
1349    #[case::utf8_string(Element::UTF8String("v1".to_string()), "InvalidVersion")]
1350    fn test_version_decode_failure(#[case] input: Element, #[case] expected_error_variant: &str) {
1351        let result: Result<Version, Error> = input.decode();
1352        assert!(result.is_err());
1353        let err = result.unwrap_err();
1354        let err_str = format!("{:?}", err);
1355        assert!(
1356            err_str.contains(expected_error_variant),
1357            "Expected error '{}', but got '{}'",
1358            expected_error_variant,
1359            err_str
1360        );
1361    }
1362
1363    // CertificateSerialNumber tests
1364    #[rstest]
1365    #[case::simple_serial(
1366        Element::Integer(Integer::from(vec![0x01])),
1367        CertificateSerialNumber::from(Integer::from(vec![0x01]))
1368    )]
1369    #[case::medium_serial(
1370        Element::Integer(Integer::from(vec![0x01, 0x02, 0x03, 0x04])),
1371        CertificateSerialNumber::from(Integer::from(vec![0x01, 0x02, 0x03, 0x04]))
1372    )]
1373    #[case::long_serial(
1374        Element::Integer(Integer::from(vec![
1375            0x48, 0xc3, 0x54, 0x8e, 0x4a, 0x5e, 0xe7, 0x64,
1376            0x74, 0x7b, 0xb0, 0x50, 0xc9, 0x16, 0xea, 0xae,
1377            0x99, 0xd6, 0x8f, 0x82
1378        ])),
1379        CertificateSerialNumber::from(Integer::from(vec![
1380            0x48, 0xc3, 0x54, 0x8e, 0x4a, 0x5e, 0xe7, 0x64,
1381            0x74, 0x7b, 0xb0, 0x50, 0xc9, 0x16, 0xea, 0xae,
1382            0x99, 0xd6, 0x8f, 0x82
1383        ]))
1384    )]
1385    fn test_certificate_serial_number_decode_success(
1386        #[case] input: Element,
1387        #[case] expected: CertificateSerialNumber,
1388    ) {
1389        let result: Result<CertificateSerialNumber, tsumiki_pkix_types::Error> = input.decode();
1390        assert!(result.is_ok());
1391        assert_eq!(result.unwrap(), expected);
1392    }
1393
1394    #[rstest]
1395    #[case::null(Element::Null, "CertificateSerialNumberExpectedInteger")]
1396    #[case::octet_string(Element::OctetString(tsumiki_asn1::OctetString::from(vec![0x01])), "CertificateSerialNumberExpectedInteger")]
1397    #[case::object_identifier(Element::ObjectIdentifier(ObjectIdentifier::from_str("1.2.3.4").unwrap()), "CertificateSerialNumberExpectedInteger")]
1398    #[case::utf8_string(Element::UTF8String("test".to_string()), "CertificateSerialNumberExpectedInteger")]
1399    fn test_certificate_serial_number_decode_failure(
1400        #[case] input: Element,
1401        #[case] expected_error_variant: &str,
1402    ) {
1403        let result: Result<CertificateSerialNumber, tsumiki_pkix_types::Error> = input.decode();
1404        assert!(result.is_err());
1405        let err = result.unwrap_err();
1406        let err_str = format!("{:?}", err);
1407        assert!(
1408            err_str.contains(expected_error_variant),
1409            "Expected error '{}', but got '{}'",
1410            expected_error_variant,
1411            err_str
1412        );
1413    }
1414
1415    // Validity tests
1416    #[rstest(
1417        not_before_element,
1418        not_after_element,
1419        expected_not_before,
1420        expected_not_after,
1421        // Test case: Both UTCTime
1422        case(
1423            Element::UTCTime(NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()),
1424            Element::UTCTime(NaiveDateTime::parse_from_str("2024-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()),
1425            NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap(),
1426            NaiveDateTime::parse_from_str("2024-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()
1427        ),
1428        // Test case: Both GeneralizedTime
1429        case(
1430            Element::GeneralizedTime(NaiveDateTime::parse_from_str("2025-01-01 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap()),
1431            Element::GeneralizedTime(NaiveDateTime::parse_from_str("2026-01-01 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap()),
1432            NaiveDateTime::parse_from_str("2025-01-01 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
1433            NaiveDateTime::parse_from_str("2026-01-01 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap()
1434        ),
1435        // Test case: Mixed UTCTime and GeneralizedTime
1436        case(
1437            Element::UTCTime(NaiveDateTime::parse_from_str("2020-06-15 12:30:45", "%Y-%m-%d %H:%M:%S").unwrap()),
1438            Element::GeneralizedTime(NaiveDateTime::parse_from_str("2030-06-15 12:30:45", "%Y-%m-%d %H:%M:%S").unwrap()),
1439            NaiveDateTime::parse_from_str("2020-06-15 12:30:45", "%Y-%m-%d %H:%M:%S").unwrap(),
1440            NaiveDateTime::parse_from_str("2030-06-15 12:30:45", "%Y-%m-%d %H:%M:%S").unwrap()
1441        )
1442    )]
1443    fn test_validity_decode_success(
1444        not_before_element: Element,
1445        not_after_element: Element,
1446        expected_not_before: NaiveDateTime,
1447        expected_not_after: NaiveDateTime,
1448    ) {
1449        let sequence = Element::Sequence(vec![not_before_element, not_after_element]);
1450        let validity: Validity = sequence.decode().unwrap();
1451
1452        assert_eq!(validity.not_before, expected_not_before);
1453        assert_eq!(validity.not_after, expected_not_after);
1454    }
1455
1456    #[rstest(
1457        input,
1458        expected_error_msg,
1459        // Test case: Empty sequence
1460        case(
1461            Element::Sequence(vec![]),
1462            "expected 2 elements in SEQUENCE"
1463        ),
1464        // Test case: Only one element
1465        case(
1466            Element::Sequence(vec![
1467                Element::UTCTime(NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap())
1468            ]),
1469            "expected 2 elements in SEQUENCE"
1470        ),
1471        // Test case: Too many elements
1472        case(
1473            Element::Sequence(vec![
1474                Element::UTCTime(NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()),
1475                Element::UTCTime(NaiveDateTime::parse_from_str("2024-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()),
1476                Element::UTCTime(NaiveDateTime::parse_from_str("2025-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap())
1477            ]),
1478            "expected 2 elements in SEQUENCE"
1479        ),
1480        // Test case: Not a sequence
1481        case(
1482            Element::Integer(Integer::from(vec![0x01])),
1483            "expected SEQUENCE"
1484        ),
1485        // Test case: Invalid notBefore (not a time element)
1486        case(
1487            Element::Sequence(vec![
1488                Element::Integer(Integer::from(vec![0x01])),
1489                Element::UTCTime(NaiveDateTime::parse_from_str("2024-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap())
1490            ]),
1491            "notBefore must be UTCTime or GeneralizedTime"
1492        ),
1493        // Test case: Invalid notAfter (not a time element)
1494        case(
1495            Element::Sequence(vec![
1496                Element::UTCTime(NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S").unwrap()),
1497                Element::Integer(Integer::from(vec![0x01]))
1498            ]),
1499            "notAfter must be UTCTime or GeneralizedTime"
1500        )
1501    )]
1502    fn test_validity_decode_failure(input: Element, expected_error_msg: &str) {
1503        let result: Result<Validity, Error> = input.decode();
1504        assert!(result.is_err());
1505        let err = result.unwrap_err();
1506        let err_str = format!("{}", err);
1507        assert!(
1508            err_str.contains(expected_error_msg),
1509            "Expected error message to contain '{}', but got '{}'",
1510            expected_error_msg,
1511            err_str
1512        );
1513    }
1514
1515    #[test]
1516    fn test_validity_roundtrip_serialization() {
1517        let validity = Validity {
1518            not_before: NaiveDateTime::parse_from_str("2019-12-16 03:02:10", "%Y-%m-%d %H:%M:%S")
1519                .unwrap(),
1520            not_after: NaiveDateTime::parse_from_str("2024-12-16 03:02:10", "%Y-%m-%d %H:%M:%S")
1521                .unwrap(),
1522        };
1523
1524        let json = serde_json::to_string(&validity).unwrap();
1525        let deserialized: Validity = serde_json::from_str(&json).unwrap();
1526
1527        assert_eq!(validity, deserialized);
1528    }
1529
1530    // SubjectPublicKeyInfo tests
1531    #[rstest(
1532        input,
1533        expected,
1534        // Test case: RSA public key (2048-bit)
1535        case(
1536            Element::Sequence(vec![
1537                Element::Sequence(vec![
1538                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()), // rsaEncryption
1539                    Element::Null,
1540                ]),
1541                Element::BitString(BitString::new(0, vec![
1542                    0x30, 0x82, 0x01, 0x0a, // SEQUENCE header
1543                    0x02, 0x82, 0x01, 0x01, // INTEGER (modulus)
1544                    0x00, 0xb4, 0x6c, 0x8f, // First few bytes of modulus
1545                ])),
1546            ]),
1547            SubjectPublicKeyInfo::new(
1548                AlgorithmIdentifier::new_with_params(
1549                    ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap(),
1550                    AlgorithmParameters::Null,
1551                ),
1552                BitString::new(0, vec![
1553                    0x30, 0x82, 0x01, 0x0a,
1554                    0x02, 0x82, 0x01, 0x01,
1555                    0x00, 0xb4, 0x6c, 0x8f,
1556                ]),
1557            )
1558        ),
1559        // Test case: ECDSA public key (P-256)
1560        case(
1561            Element::Sequence(vec![
1562                Element::Sequence(vec![
1563                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap()), // ecPublicKey
1564                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()), // secp256r1
1565                ]),
1566                Element::BitString(BitString::new(0, vec![
1567                    0x04, // Uncompressed point
1568                    0x8d, 0x61, 0x7e, 0x65, // X coordinate (first 4 bytes)
1569                    0x3b, 0x6b, 0x80, 0x69, // Y coordinate (first 4 bytes)
1570                ])),
1571            ]),
1572            SubjectPublicKeyInfo::new(
1573                AlgorithmIdentifier::new_with_params(
1574                    ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(),
1575                    AlgorithmParameters::Other(
1576                        RawAlgorithmParameter::new(Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()))
1577                    ),
1578                ),
1579                BitString::new(0, vec![
1580                    0x04,
1581                    0x8d, 0x61, 0x7e, 0x65,
1582                    0x3b, 0x6b, 0x80, 0x69,
1583                ]),
1584            )
1585        ),
1586        // Test case: Ed25519 public key
1587        case(
1588            Element::Sequence(vec![
1589                Element::Sequence(vec![
1590                    Element::ObjectIdentifier(ObjectIdentifier::from_str("1.3.101.112").unwrap()), // Ed25519
1591                ]),
1592                Element::BitString(BitString::new(0, vec![
1593                    0x8d, 0x61, 0x7e, 0x65, 0x3b, 0x6b, 0x80, 0x69, // 32 bytes of public key
1594                    0x1b, 0x21, 0x4c, 0x28, 0xf8, 0x3a, 0x8b, 0x27,
1595                    0x3f, 0x49, 0x40, 0xea, 0xc0, 0x8e, 0x73, 0x6d,
1596                    0x9f, 0x3f, 0x31, 0x21, 0x91, 0x3b, 0xa2, 0x16,
1597                ])),
1598            ]),
1599            SubjectPublicKeyInfo::new(
1600                AlgorithmIdentifier::new(
1601                    ObjectIdentifier::from_str("1.3.101.112").unwrap(),
1602                ),
1603                BitString::new(0, vec![
1604                    0x8d, 0x61, 0x7e, 0x65, 0x3b, 0x6b, 0x80, 0x69,
1605                    0x1b, 0x21, 0x4c, 0x28, 0xf8, 0x3a, 0x8b, 0x27,
1606                    0x3f, 0x49, 0x40, 0xea, 0xc0, 0x8e, 0x73, 0x6d,
1607                    0x9f, 0x3f, 0x31, 0x21, 0x91, 0x3b, 0xa2, 0x16,
1608                ]),
1609            )
1610        ),
1611        // Test case: BitString with unused bits
1612        case(
1613            Element::Sequence(vec![
1614                Element::Sequence(vec![
1615                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()),
1616                    Element::Null,
1617                ]),
1618                Element::BitString(BitString::new(3, vec![0xFF, 0xE0])), // 13 bits (3 unused in last byte)
1619            ]),
1620            SubjectPublicKeyInfo::new(
1621                AlgorithmIdentifier::new_with_params(
1622                    ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap(),
1623                    AlgorithmParameters::Null,
1624                ),
1625                BitString::new(3, vec![0xFF, 0xE0]),
1626            )
1627        ),
1628    )]
1629    fn test_subject_public_key_info_decode_success(input: Element, expected: SubjectPublicKeyInfo) {
1630        let result: Result<SubjectPublicKeyInfo, tsumiki_pkix_types::Error> = input.decode();
1631        assert!(result.is_ok());
1632        let spki = result.unwrap();
1633        assert_eq!(spki, expected);
1634    }
1635
1636    #[rstest(
1637        input,
1638        expected_error_msg,
1639        // Test case: Not a Sequence
1640        case(
1641            Element::Integer(Integer::from(vec![0x01])),
1642            "expected SEQUENCE"
1643        ),
1644        // Test case: Empty sequence
1645        case(
1646            Element::Sequence(vec![]),
1647            "expected 2 elements, got 0"
1648        ),
1649        // Test case: Only one element
1650        case(
1651            Element::Sequence(vec![
1652                Element::Sequence(vec![
1653                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()),
1654                ]),
1655            ]),
1656            "expected 2 elements, got 1"
1657        ),
1658        // Test case: Too many elements
1659        case(
1660            Element::Sequence(vec![
1661                Element::Sequence(vec![
1662                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()),
1663                ]),
1664                Element::BitString(BitString::new(0, vec![0x00])),
1665                Element::Null,
1666            ]),
1667            "expected 2 elements, got 3"
1668        ),
1669        // Test case: First element is not AlgorithmIdentifier (not a sequence)
1670        case(
1671            Element::Sequence(vec![
1672                Element::Integer(Integer::from(vec![0x01])),
1673                Element::BitString(BitString::new(0, vec![0x00])),
1674            ]),
1675            "AlgorithmIdentifier must be a SEQUENCE"
1676        ),
1677        // Test case: Second element is not BitString
1678        case(
1679            Element::Sequence(vec![
1680                Element::Sequence(vec![
1681                    Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()),
1682                ]),
1683                Element::OctetString(OctetString::from(vec![0x00])),
1684            ]),
1685            "expected BIT STRING for subject public key"
1686        ),
1687        // Test case: Invalid AlgorithmIdentifier (empty sequence)
1688        case(
1689            Element::Sequence(vec![
1690                Element::Sequence(vec![]),
1691                Element::BitString(BitString::new(0, vec![0x00])),
1692            ]),
1693            "AlgorithmIdentifier must have at least 1 element"
1694        ),
1695    )]
1696    fn test_subject_public_key_info_decode_failure(input: Element, expected_error_msg: &str) {
1697        let result: Result<SubjectPublicKeyInfo, tsumiki_pkix_types::Error> = input.decode();
1698        assert!(result.is_err());
1699        let err = result.unwrap_err();
1700        let err_str = format!("{}", err);
1701        assert!(
1702            err_str.contains(expected_error_msg),
1703            "Expected error message containing '{}', but got '{}'",
1704            expected_error_msg,
1705            err_str
1706        );
1707    }
1708
1709    // Test certificate V1 (RSA 2048-bit, no extensions)
1710    // Generated with: openssl req -x509 -newkey rsa:2048 -nodes \
1711    //   -keyout x509/test_v1_key.pem -out x509/test_v1_cert.pem -days 3650 \
1712    //   -subj "/C=JP/O=Tsumiki/CN=test-v1"
1713    const TEST_CERT_V1: &str = r"-----BEGIN CERTIFICATE-----
1714MIIC3jCCAcYCCQD36esrlVEnfTANBgkqhkiG9w0BAQsFADAxMQswCQYDVQQGEwJK
1715UDEQMA4GA1UECgwHVHN1bWlraTEQMA4GA1UEAwwHdGVzdC12MTAeFw0yNTEyMjgw
1716OTU0MDlaFw0zNTEyMjYwOTU0MDlaMDExCzAJBgNVBAYTAkpQMRAwDgYDVQQKDAdU
1717c3VtaWtpMRAwDgYDVQQDDAd0ZXN0LXYxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
1718MIIBCgKCAQEA4wIzS7OSAX5BGtOggT2npL7j07MK7tp8LdLQtVv4STTTldq5nB21
1719msh7WjrJ/DVzBljyoDOS+rRCe/33SakVCWtsvgXmlbr6/HYiHEFIeMj1U5qFHBPI
1720/yccZdwW0FdaKNoMDyaa6ii/uZ0mdm9Rh2BTmM6jbsKghGOPZNtt7cfPDOQEkbuX
1721tdTS8YNRxULsIVrKi3GEsITZylvpzaS2k8atsQyayE2I/wVCBuwnP8JKE7ZjXBCu
1722D1+RpXdeVIJFwG9oe7X1ejurwb+VRTZzLFr+p9f6D/1PXzjWGxxohG9ACKaMlWqO
1723+Ge0mODKwo7D+Z+2uR1t0W8eZp/Mg7PjHQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
1724AQAWbVDRrPKoZ+kAOKdl5rZ9DOtzTnAkYTIXKiI5kKsZQ05Rz0N3zjtv6WieHu4f
1725STa6A1EjsESx78VhqiWD451lfJTAPvofzY7f32ZrMhGPI5GIGQJXm3ykFNC57z/g
1726hZS04cvj1lqaWdp5DQ9ZrIS9PaBVcY+RtuRmIpbSuZukjGvG/W76fqajZWRwG6yW
1727lbz1C5n4m8n+m8zTLy28nxX7Fm/8h0c3/jjrJnkYQ98JIQuj9vyhH0SHloP/uoTI
1728arWjLcCEZ6DqqXiKc4ojkQvARkufeKpztUlgi7lrTfk6hG0RWp0jmY/OyV3OeTeP
1729ZyI1Mobuf6I2De0X96VkC+JV
1730-----END CERTIFICATE-----";
1731
1732    // Test certificate V3 CA (RSA 4096-bit, with CA extensions)
1733    // Generated with: openssl req -x509 -newkey rsa:4096 -nodes \
1734    //   -keyout x509/test_key.pem -out x509/test_cert.pem -days 3650 \
1735    //   -config x509/cert_config.cnf \
1736    //   -subj "/C=JP/ST=Tokyo/L=Shibuya/O=Tsumiki Project/OU=Test/CN=tsumiki.test"
1737    const TEST_CERT_V3_CA: &str = r"-----BEGIN CERTIFICATE-----
1738MIIFxDCCA6ygAwIBAgIJAJOR1eonIkS9MA0GCSqGSIb3DQEBCwUAMG8xCzAJBgNV
1739BAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEQMA4GA1UEBwwHU2hpYnV5YTEYMBYGA1UE
1740CgwPVHN1bWlraSBQcm9qZWN0MQ0wCwYDVQQLDARUZXN0MRUwEwYDVQQDDAx0c3Vt
1741aWtpLnRlc3QwHhcNMjUxMjI4MDg0OTA3WhcNMzUxMjI2MDg0OTA3WjBvMQswCQYD
1742VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB1NoaWJ1eWExGDAWBgNV
1743BAoMD1RzdW1pa2kgUHJvamVjdDENMAsGA1UECwwEVGVzdDEVMBMGA1UEAwwMdHN1
1744bWlraS50ZXN0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4Ey4xmrV
1745Oju/hD/gGWzIG7PHAIKrCIyZdGNuESZxZCTISFYDLBif9SpIh1Ss1p5L37KCe7P8
17466T2Ab/NPCpCUuHI51XOLBfvyAYPlkbF3bgtrtG4+4cCqpBTsQpE23tLjq3Yiw1Tp
1747uw8ny+83omq7sJJ3fYaDun/JDwK+sDhOxAfF7B0g8n6crg4cONXwBEVXcPNIr+SG
1748enwUAZwcCGG50tGiDGf92Mj/GuwbHrcaRsGbSClK/YismkO/dROCVhp+4tSCmGLM
1749eoKa7z+bkCyVNfCNJYXfJp1Iqpu65ElT0DzHq/KTvkbfFnkqSXb0e61CW/tSfFCK
1750vA0Ih6tlEa275rv86hEH5NZvM5kS66LUzZwgA2Cc527Xnf41zEPQZZhBe9VtReqR
1751sbBd02vScg4rsGy8j01T8mK/1yTD8euXJN7fuiuChhFMw/LWcGfwMsd3vG7ty4hh
1752Yuv7kYAcasZpABbT/2SvdJ8VX9pZLQiFJvUJ/tQGX0Mm3FZaExj/vttsO2/Q9/OP
1753hIAyPUWqgqw14SqjrBa9eUULKENiWpbf5EtXNeDWOGTUz8xLXL4AKYvbkLi0ciPp
1754GiN5U9/P05PgzakwsniCMuG+RtgYX0jJJNwzAsDMqk8C7ATWWj1UOCowADqOsTXS
1755oDnrwNkBv0AKN4oL1wh+Lyqc+8Idin2sA6sCAwEAAaNjMGEwHQYDVR0OBBYEFAHB
1756rLF5p+pxNqZDYFTpIpgzkOkIMB8GA1UdIwQYMBaAFAHBrLF5p+pxNqZDYFTpIpgz
1757kOkIMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
1758CwUAA4ICAQBc9G5hR7REaXkwnUs6gxGAqsrs2FLskDWUmQ7CqZChvmIcYDYaWBkN
1759dORbNnt5IayJaeGRtGVobLzKa5gkd7H8S2nYEf3ZB53Ao7axc6+qkXsyqw53GrkL
1760y9gRNtcmE2S1DAHLvNP2ITr+Q5xeilGrN5LX6cgvPLq7W9oUrejilCUdaxMD9JxU
1761H4UPitrCoenz6kmATYjFccgucpDrII6TKnAMBNa1MsRfyMxrK9eKWDVrCVaU8qG/
1762cc/lW+81HF9a58jLvLVNzkBU1akyuEkIySpjUAB17MqZED/E1vjnuz2uZ1ZdqvXn
1763v5IknYv37rFFa9umzLrPBg+bdAq6kSYO6fuZ1ALLXnXwS/o6aB6er3IhQ+BG3T2l
1764csJ9HHkSzd9+OQBxmvzQzqzPnrRUPPsVWFpY5U/HgiapQY7ap2WvH5PYqTTVJxuX
1765nRY+7m26TseaQUoGtvmGQroWExHXnfMPegXFMLMQNZ6sLd3196b7xXbsDLPWHI+W
1766iVmR86a6BiAiLoWky6r4X7hzOvEKEpP+U0AmzCy/M5QIJrQ8WUAUMYwUvwA/PUwD
1767UbUqI1x5HAbH95tvCou+2CI27rSINgsQjFdx13Xc3+4xjHGvncqWQXCyQvcC4a33
1768dlxmWgRWrD79sttWdIihj33fPv+OezjPjVNXU5tSJsDpKudwXhcPzQ==
1769-----END CERTIFICATE-----";
1770
1771    // Test certificate V3 End Entity (RSA 2048-bit, with SAN extension)
1772    // Generated with: openssl req -x509 -newkey rsa:2048 -nodes \
1773    //   -keyout x509/test_ee_key.pem -out x509/test_ee_cert.pem -days 3650 \
1774    //   -config x509/end_entity_config.cnf \
1775    //   -subj "/C=JP/ST=Tokyo/O=Tsumiki Project/CN=server.tsumiki.test"
1776    const TEST_CERT_V3_EE: &str = r"-----BEGIN CERTIFICATE-----
1777MIIDrDCCApSgAwIBAgIJAJe8Uwe3KSplMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV
1778BAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEYMBYGA1UECgwPVHN1bWlraSBQcm9qZWN0
1779MRwwGgYDVQQDDBNzZXJ2ZXIudHN1bWlraS50ZXN0MB4XDTI1MTIyODA5NTQyNloX
1780DTM1MTIyNjA5NTQyNlowVTELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRgw
1781FgYDVQQKDA9Uc3VtaWtpIFByb2plY3QxHDAaBgNVBAMME3NlcnZlci50c3VtaWtp
1782LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtc3gArhY+2ZPa
1783EEodwZSdV64JfI6LP/VJdCrJkrWw+cAjIoPd5IWYYM4quJjyS0sKJdOcG1ox+Vyk
1784V2Mx3Tu7a9HfkL94UVC6wkuqxn6ss1nF3WDwRpMKdk2osAkfC2DEy+gUTbSUP7nF
1785xLfzWnHsiKf7OQdnvqi1+ky77c2oYCsR4Gmc45/pmma8laHtD15nLrNw6QPNFXgi
1786tqVRsJAd887FP35vsxlKLSt1KtDplXPwVdTKIEoAfC3rbfS2RtHoLz2iScS4m97R
1787H2yd71R04UaBluloV6eVn+SYx6toglm2TigxQG/v0i/b4J5+tTLRFWSbSw6IXfPv
1788IpeO5QybAgMBAAGjfzB9MB0GA1UdDgQWBBQ3BSW6F/y0r7M6za10RFuSkEjWADAO
1789BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMC0G
1790A1UdEQQmMCSCDHRzdW1pa2kudGVzdIIOKi50c3VtaWtpLnRlc3SHBH8AAAEwDQYJ
1791KoZIhvcNAQELBQADggEBAK+YTpe3eg622ATN9mXMUxyD+qHLdsjqaoe1XHyjZyZ7
1792uEERNtSw2FBxzg1YDh2dEZtWc8ybwPwJwpySo/7dq53BWZW6aBW0kMp3GLC/Od6C
1793k+8EFoao7SFr16XsGQJD4DNoKVvHKAE2FworjXdRUFswwtkoD8gdsK2sf2vgnBv8
1794HAVm7HukOAHpl5Cv4uoD57p1kfMH4T7q1yKz5e9kQi3Ta5vJzydMluZzgJQUxif1
17953nAQuaKAyIZfiF4QTlaA8i8nodjhZeM6A0ZomnZeCVjigqkr706tbakcyyrbsjM4
1796I36SjnCvZLfTAZy2PzjD+JS43m/+2ydsdhU7+aUoR+w=
1797-----END CERTIFICATE-----";
1798
1799    // Test certificate V3 ECDSA P-256 CA (with CA extensions)
1800    // Generated with: openssl ecparam -name prime256v1 -genkey -noout | \
1801    //   openssl req -new -x509 -key /dev/stdin -out x509/test_ec_cert.pem -days 3650 \
1802    //   -config x509/cert_config.cnf \
1803    //   -subj "/C=JP/ST=Tokyo/O=Tsumiki Project/CN=ec-ca.tsumiki.test"
1804    const TEST_CERT_V3_ECDSA_P256: &str = r"-----BEGIN CERTIFICATE-----
1805MIICAjCCAaigAwIBAgIJAKtsTdFGb77kMAoGCCqGSM49BAMCMFQxCzAJBgNVBAYT
1806AkpQMQ4wDAYDVQQIDAVUb2t5bzEYMBYGA1UECgwPVHN1bWlraSBQcm9qZWN0MRsw
1807GQYDVQQDDBJlYy1jYS50c3VtaWtpLnRlc3QwHhcNMjUxMjI4MTAyOTI0WhcNMzUx
1808MjI2MTAyOTI0WjBUMQswCQYDVQQGEwJKUDEOMAwGA1UECAwFVG9reW8xGDAWBgNV
1809BAoMD1RzdW1pa2kgUHJvamVjdDEbMBkGA1UEAwwSZWMtY2EudHN1bWlraS50ZXN0
1810MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7sCe86byM+Pj8cbpthxg1eMhQ/MN
1811xgsLmedraZo9OXStkYhMFFqcFccwiIXLiWJgiIsVVpGn02uLpB4SOlu4FKNjMGEw
1812HQYDVR0OBBYEFDWBtOp+1zCPl3dUA52ZjY7C2F1tMB8GA1UdIwQYMBaAFDWBtOp+
18131zCPl3dUA52ZjY7C2F1tMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG
1814MAoGCCqGSM49BAMCA0gAMEUCIEtUSow92vKt7bYbjRszN8Db2UR6BSaz+q7kxo+X
1815Z1s+AiEAsj0FnruwSPLI6M1KzOjeNKTmFeDyYIw3zF1DVdCFOmc=
1816-----END CERTIFICATE-----";
1817
1818    // Test certificate V3 ECDSA P-384 (with SAN extension)
1819    // Generated with: openssl ecparam -name secp384r1 -genkey -noout | \
1820    //   openssl req -new -x509 -key /dev/stdin -out x509/test_ec384_cert.pem -days 3650 \
1821    //   -config x509/end_entity_config.cnf \
1822    //   -subj "/C=JP/O=Tsumiki Project/CN=ec384.tsumiki.test"
1823    const TEST_CERT_V3_ECDSA_P384: &str = r"-----BEGIN CERTIFICATE-----
1824MIICOjCCAcGgAwIBAgIJAPSkPOMqZro8MAoGCCqGSM49BAMCMEQxCzAJBgNVBAYT
1825AkpQMRgwFgYDVQQKDA9Uc3VtaWtpIFByb2plY3QxGzAZBgNVBAMMEmVjMzg0LnRz
1826dW1pa2kudGVzdDAeFw0yNTEyMjgxMDI5NDhaFw0zNTEyMjYxMDI5NDhaMEQxCzAJ
1827BgNVBAYTAkpQMRgwFgYDVQQKDA9Uc3VtaWtpIFByb2plY3QxGzAZBgNVBAMMEmVj
1828Mzg0LnRzdW1pa2kudGVzdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABMZzYCpsCn/q
1829OkGGfxphk+24hS47tW849Z2xjzh2XJqLlKrcPcO+5zpWri7WNuo/DrsPXIgJdTxx
1830/b97Rq25TgtRLem5rux4uN0gMxf5qcRotqSXrN5eL7i8xPGrWBxw9aN/MH0wHQYD
1831VR0OBBYEFGVQxde1MT37ma9vjNCp9WVdUXsCMA4GA1UdDwEB/wQEAwIFoDAdBgNV
1832HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwLQYDVR0RBCYwJIIMdHN1bWlraS50
1833ZXN0gg4qLnRzdW1pa2kudGVzdIcEfwAAATAKBggqhkjOPQQDAgNnADBkAjAVRQuq
183466V6ZQQoCFGNDUbki4yWd4pKp2x2igVxJ+8yAJj0hSERlRP1cpnq5CWhOXgCMExy
1835sDuylxpp9szuj0bvfcO9JcS+V/5gPK0+5QxawidqE/ERQgBD9yj8ouw4F6BmKg==
1836-----END CERTIFICATE-----";
1837
1838    #[test]
1839    fn test_decode_v1_certificate() {
1840        let pem = Pem::from_str(TEST_CERT_V1).unwrap();
1841        let der: Der = pem.decode().unwrap();
1842        let asn1_obj: ASN1Object = der.decode().unwrap();
1843
1844        let cert: Certificate = asn1_obj.decode().unwrap();
1845        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1846        println!("=== V1 Certificate ===");
1847        println!("{}", json_output);
1848
1849        // V1 certificate assertions
1850        assert_eq!(cert.tbs_certificate.version, Version::V1);
1851        assert!(cert.tbs_certificate.extensions.is_none());
1852        assert_eq!(cert.tbs_certificate.issuer.rdn_sequence().len(), 3); // C, O, CN
1853        assert_eq!(cert.tbs_certificate.subject.rdn_sequence().len(), 3);
1854    }
1855
1856    #[test]
1857    fn test_decode_v3_ca_certificate() {
1858        let pem = Pem::from_str(TEST_CERT_V3_CA).unwrap();
1859        let der: Der = pem.decode().unwrap();
1860        let asn1_obj: ASN1Object = der.decode().unwrap();
1861
1862        let cert: Certificate = asn1_obj.decode().unwrap();
1863        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1864        println!("=== V3 CA Certificate ===");
1865        println!("{}", json_output);
1866
1867        // V3 CA certificate assertions
1868        assert_eq!(cert.tbs_certificate.version, Version::V3);
1869        assert!(cert.tbs_certificate.extensions.is_some());
1870        let extensions = cert.tbs_certificate.extensions.as_ref().unwrap();
1871        assert_eq!(extensions.extensions().len(), 4); // SKI, AKI, BasicConstraints, KeyUsage
1872        assert_eq!(cert.tbs_certificate.issuer.rdn_sequence().len(), 6); // C, ST, L, O, OU, CN
1873    }
1874
1875    #[test]
1876    fn test_decode_v3_ee_certificate() {
1877        let pem = Pem::from_str(TEST_CERT_V3_EE).unwrap();
1878        let der: Der = pem.decode().unwrap();
1879        let asn1_obj: ASN1Object = der.decode().unwrap();
1880
1881        let cert: Certificate = asn1_obj.decode().unwrap();
1882
1883        // Print Display output (OpenSSL-like format)
1884        println!("\n=== V3 End Entity Certificate (Display) ===");
1885        println!("{}", cert);
1886
1887        // Print JSON output
1888        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1889        println!("\n=== V3 End Entity Certificate (JSON) ===");
1890        println!("{}", json_output);
1891
1892        // V3 End Entity certificate assertions
1893        assert_eq!(cert.tbs_certificate.version, Version::V3);
1894        assert!(cert.tbs_certificate.extensions.is_some());
1895        let extensions = cert.tbs_certificate.extensions.as_ref().unwrap();
1896        assert_eq!(extensions.extensions().len(), 4); // SKI, KeyUsage, ExtKeyUsage, SAN
1897        assert_eq!(cert.tbs_certificate.issuer.rdn_sequence().len(), 4); // C, ST, O, CN
1898    }
1899
1900    #[test]
1901    fn test_decode_v3_ecdsa_p256_certificate() {
1902        let pem = Pem::from_str(TEST_CERT_V3_ECDSA_P256).unwrap();
1903        let der: Der = pem.decode().unwrap();
1904        let asn1_obj: ASN1Object = der.decode().unwrap();
1905
1906        let cert: Certificate = asn1_obj.decode().unwrap();
1907        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1908        println!("=== V3 ECDSA P-256 CA Certificate ===");
1909        println!("{}", json_output);
1910
1911        // V3 ECDSA P-256 CA certificate assertions
1912        assert_eq!(cert.tbs_certificate.version, Version::V3);
1913        assert!(cert.tbs_certificate.extensions.is_some());
1914        let extensions = cert.tbs_certificate.extensions.as_ref().unwrap();
1915        assert_eq!(extensions.extensions().len(), 4); // SKI, AKI, BasicConstraints, KeyUsage
1916
1917        // Verify it's ECDSA (OID: 1.2.840.10045.2.1)
1918        assert_eq!(
1919            cert.tbs_certificate
1920                .subject_public_key_info
1921                .algorithm()
1922                .algorithm
1923                .to_string(),
1924            "1.2.840.10045.2.1"
1925        );
1926        // Verify signature algorithm is ECDSA-SHA256 (OID: 1.2.840.10045.4.3.2)
1927        assert_eq!(
1928            cert.signature_algorithm.algorithm.to_string(),
1929            "1.2.840.10045.4.3.2"
1930        );
1931    }
1932
1933    #[test]
1934    fn test_decode_v3_ecdsa_p384_certificate() {
1935        let pem = Pem::from_str(TEST_CERT_V3_ECDSA_P384).unwrap();
1936        let der: Der = pem.decode().unwrap();
1937        let asn1_obj: ASN1Object = der.decode().unwrap();
1938
1939        let cert: Certificate = asn1_obj.decode().unwrap();
1940        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1941        println!("=== V3 ECDSA P-384 Certificate ===");
1942        println!("{}", json_output);
1943
1944        // V3 ECDSA P-384 certificate assertions
1945        assert_eq!(cert.tbs_certificate.version, Version::V3);
1946        assert!(cert.tbs_certificate.extensions.is_some());
1947        let extensions = cert.tbs_certificate.extensions.as_ref().unwrap();
1948        assert_eq!(extensions.extensions().len(), 4); // SKI, KeyUsage, ExtKeyUsage, SAN
1949
1950        // Verify it's ECDSA (OID: 1.2.840.10045.2.1)
1951        assert_eq!(
1952            cert.tbs_certificate
1953                .subject_public_key_info
1954                .algorithm()
1955                .algorithm
1956                .to_string(),
1957            "1.2.840.10045.2.1"
1958        );
1959        // Verify signature algorithm is ECDSA-SHA256 (OID: 1.2.840.10045.4.3.2)
1960        assert_eq!(
1961            cert.signature_algorithm.algorithm.to_string(),
1962            "1.2.840.10045.4.3.2"
1963        );
1964    }
1965
1966    #[test]
1967    fn test_decode_full_certificate() {
1968        // Parse PEM -> DER -> ASN1Object -> Certificate
1969        let pem = Pem::from_str(TEST_CERT_V1).unwrap();
1970        let der: Der = pem.decode().unwrap();
1971        let asn1_obj: ASN1Object = der.decode().unwrap();
1972
1973        // Decode to Certificate from ASN1Object directly
1974        let certificate: Result<Certificate, Error> = asn1_obj.decode();
1975        assert!(
1976            certificate.is_ok(),
1977            "Failed to decode certificate: {:?}",
1978            certificate.err()
1979        );
1980
1981        let cert = certificate.unwrap();
1982
1983        // Output as JSON
1984        let json_output = serde_json::to_string_pretty(&cert).unwrap();
1985        println!("{}", json_output);
1986
1987        // Verify basic properties
1988        // This is a v1 certificate (no explicit version field in the encoding)
1989        assert_eq!(cert.tbs_certificate.version, Version::V1);
1990        // v1 certificates don't have extensions
1991        assert!(cert.tbs_certificate.extensions.is_none());
1992        // Verify subject/issuer
1993        assert_eq!(
1994            cert.tbs_certificate.issuer.rdn_sequence().len(),
1995            3 // C, O, CN
1996        );
1997        assert_eq!(
1998            cert.tbs_certificate.subject.rdn_sequence().len(),
1999            3 // C, O, CN
2000        );
2001    }
2002
2003    // Encoder tests
2004    #[rstest(
2005        alg_id,
2006        expected_len,
2007        case(
2008            AlgorithmIdentifier {
2009                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap(),
2010                parameters: None,
2011            },
2012            1
2013        ),
2014        case(
2015            AlgorithmIdentifier {
2016                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap(),
2017                parameters: Some(AlgorithmParameters::Null),
2018            },
2019            2
2020        ),
2021        case(
2022            AlgorithmIdentifier {
2023                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_ECDSA_WITH_SHA256).unwrap(),
2024                parameters: Some(AlgorithmParameters::Other(
2025                    RawAlgorithmParameter::new(Element::OctetString(OctetString::from(vec![0x01, 0x02, 0x03])))
2026                )),
2027            },
2028            2
2029        )
2030    )]
2031    fn test_algorithm_identifier_encode(alg_id: AlgorithmIdentifier, expected_len: usize) {
2032        let encoded = alg_id.encode().unwrap();
2033
2034        match &encoded {
2035            Element::Sequence(elems) => {
2036                assert_eq!(elems.len(), expected_len);
2037                assert!(matches!(elems[0], Element::ObjectIdentifier(_)));
2038                if expected_len == 2 {
2039                    // Parameters exist
2040                    assert!(alg_id.parameters.is_some());
2041                }
2042            }
2043            _ => panic!("Expected Sequence"),
2044        }
2045
2046        // Round-trip test
2047        let decoded: AlgorithmIdentifier = encoded.decode().unwrap();
2048        assert_eq!(decoded, alg_id);
2049    }
2050
2051    #[rstest(
2052        version,
2053        expected_value,
2054        case(Version::V1, 0),
2055        case(Version::V2, 1),
2056        case(Version::V3, 2)
2057    )]
2058    fn test_version_encode(version: Version, expected_value: u64) {
2059        let encoded = version.encode().unwrap();
2060        match encoded {
2061            Element::ContextSpecific {
2062                slot, ref element, ..
2063            } => {
2064                assert_eq!(slot, 0);
2065                match element.as_ref() {
2066                    Element::Integer(i) => {
2067                        let value = u64::try_from(i).unwrap();
2068                        assert_eq!(value, expected_value);
2069                    }
2070                    _ => panic!("Expected Integer inside context-specific tag"),
2071                }
2072            }
2073            _ => panic!("Expected ContextSpecific"),
2074        }
2075
2076        // Round-trip test
2077        let decoded: Version = encoded.decode().unwrap();
2078        assert_eq!(decoded, version);
2079    }
2080
2081    #[rstest(
2082        serial_bytes,
2083        case(vec![0x01]),
2084        case(vec![0x01, 0x23, 0x45, 0x67, 0x89]),
2085        case(vec![0x7f, 0xee, 0xdd, 0xcc, 0xbb, 0xaa]) // Use 0x7f to avoid sign bit issues
2086    )]
2087    fn test_certificate_serial_number_encode(serial_bytes: Vec<u8>) {
2088        let serial = CertificateSerialNumber::from_bytes(serial_bytes.clone());
2089
2090        let encoded = serial.encode().unwrap();
2091
2092        match &encoded {
2093            Element::Integer(_) => {
2094                // Just verify it's an Integer
2095            }
2096            _ => panic!("Expected Integer"),
2097        }
2098
2099        // Round-trip test is the most important
2100        let decoded: CertificateSerialNumber = encoded.decode().unwrap();
2101        assert_eq!(decoded, serial);
2102    }
2103
2104    #[rstest(
2105        not_before,
2106        not_after,
2107        case(
2108            NaiveDate::from_ymd_opt(2024, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap(),
2109            NaiveDate::from_ymd_opt(2025, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap()
2110        ),
2111        case(
2112            NaiveDate::from_ymd_opt(1950, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap(),
2113            NaiveDate::from_ymd_opt(2049, 12, 31).unwrap().and_hms_opt(23, 59, 59).unwrap()
2114        ),
2115        case(
2116            NaiveDate::from_ymd_opt(1949, 12, 31).unwrap().and_hms_opt(23, 59, 59).unwrap(),
2117            NaiveDate::from_ymd_opt(2050, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap()
2118        )
2119    )]
2120    fn test_validity_encode(not_before: NaiveDateTime, not_after: NaiveDateTime) {
2121        let validity = Validity {
2122            not_before,
2123            not_after,
2124        };
2125
2126        let encoded = validity.encode().unwrap();
2127
2128        match &encoded {
2129            Element::Sequence(elements) => {
2130                assert_eq!(elements.len(), 2);
2131
2132                // Check that dates in range 1950-2049 use UTCTime
2133                match &elements[0] {
2134                    Element::UTCTime(_) => {
2135                        assert!(not_before.year() >= 1950 && not_before.year() < 2050);
2136                    }
2137                    Element::GeneralizedTime(_) => {
2138                        assert!(not_before.year() < 1950 || not_before.year() >= 2050);
2139                    }
2140                    _ => panic!("Expected UTCTime or GeneralizedTime for notBefore"),
2141                }
2142
2143                match &elements[1] {
2144                    Element::UTCTime(_) => {
2145                        assert!(not_after.year() >= 1950 && not_after.year() < 2050);
2146                    }
2147                    Element::GeneralizedTime(_) => {
2148                        assert!(not_after.year() < 1950 || not_after.year() >= 2050);
2149                    }
2150                    _ => panic!("Expected UTCTime or GeneralizedTime for notAfter"),
2151                }
2152            }
2153            _ => panic!("Expected Sequence"),
2154        }
2155
2156        // Round-trip test
2157        let decoded: Validity = encoded.decode().unwrap();
2158        assert_eq!(decoded, validity);
2159    }
2160
2161    #[rstest(
2162        algorithm,
2163        public_key_bytes,
2164        case(
2165            AlgorithmIdentifier {
2166                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap(), // RSA
2167                parameters: None,
2168            },
2169            vec![0x30, 0x0d, 0x06, 0x09] // Sample RSA public key bytes
2170        ),
2171        case(
2172            AlgorithmIdentifier {
2173                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(), // EC public key
2174                parameters: Some(AlgorithmParameters::Other(
2175                    RawAlgorithmParameter::new(Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap())) // prime256v1
2176                )),
2177            },
2178            vec![0x04, 0x41] // Sample EC public key bytes
2179        ),
2180        case(
2181            AlgorithmIdentifier {
2182                algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(), // EC public key
2183                parameters: Some(AlgorithmParameters::Null),
2184            },
2185            vec![0xff, 0xee, 0xdd] // Different key bytes
2186        )
2187    )]
2188    fn test_subject_public_key_info_encode(
2189        algorithm: AlgorithmIdentifier,
2190        public_key_bytes: Vec<u8>,
2191    ) {
2192        let subject_public_key_info = SubjectPublicKeyInfo::new(
2193            algorithm.clone(),
2194            BitString::new(0, public_key_bytes.clone()),
2195        );
2196
2197        let encoded = subject_public_key_info.encode().unwrap();
2198
2199        match &encoded {
2200            Element::Sequence(elements) => {
2201                assert_eq!(elements.len(), 2);
2202
2203                // First element should be the algorithm identifier
2204                let decoded_algorithm: AlgorithmIdentifier = elements[0].decode().unwrap();
2205                assert_eq!(decoded_algorithm, algorithm);
2206
2207                // Second element should be a BitString
2208                match &elements[1] {
2209                    Element::BitString(bs) => {
2210                        assert_eq!(bs.as_bytes(), public_key_bytes.as_slice());
2211                    }
2212                    _ => panic!("Expected BitString for subject public key"),
2213                }
2214            }
2215            _ => panic!("Expected Sequence"),
2216        }
2217
2218        // Round-trip test
2219        let decoded: SubjectPublicKeyInfo = encoded.decode().unwrap();
2220        assert_eq!(decoded, subject_public_key_info);
2221    }
2222
2223    #[rstest(
2224        name,
2225        case(Name {
2226            rdn_sequence: vec![
2227                RelativeDistinguishedName {
2228                    attributes: vec![AttributeTypeAndValue {
2229                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME).unwrap(),
2230                        attribute_value: "Example CA".into(),
2231                    }],
2232                },
2233            ],
2234        }),
2235        case(Name {
2236            rdn_sequence: vec![
2237                RelativeDistinguishedName {
2238                    attributes: vec![AttributeTypeAndValue {
2239                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_COUNTRY_NAME).unwrap(),
2240                        attribute_value: "US".into(),
2241                    }],
2242                },
2243                RelativeDistinguishedName {
2244                    attributes: vec![AttributeTypeAndValue {
2245                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_STATE_OR_PROVINCE_NAME).unwrap(),
2246                        attribute_value: "California".into(),
2247                    }],
2248                },
2249                RelativeDistinguishedName {
2250                    attributes: vec![AttributeTypeAndValue {
2251                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_ORGANIZATION_NAME).unwrap(),
2252                        attribute_value: "Example Corp".into(),
2253                    }],
2254                },
2255            ],
2256        }),
2257        case(Name {
2258            rdn_sequence: vec![
2259                RelativeDistinguishedName {
2260                    attributes: vec![AttributeTypeAndValue {
2261                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_COUNTRY_NAME).unwrap(),
2262                        attribute_value: "JP".into(),
2263                    }],
2264                },
2265                RelativeDistinguishedName {
2266                    attributes: vec![AttributeTypeAndValue {
2267                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_STATE_OR_PROVINCE_NAME).unwrap(),
2268                        attribute_value: "Tokyo".into(),
2269                    }],
2270                },
2271                RelativeDistinguishedName {
2272                    attributes: vec![
2273                        AttributeTypeAndValue {
2274                            attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_ORGANIZATION_NAME).unwrap(),
2275                            attribute_value: "ACME Inc".into(),
2276                        },
2277                        AttributeTypeAndValue {
2278                            attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_ORGANIZATIONAL_UNIT_NAME).unwrap(),
2279                            attribute_value: "Engineering".into(),
2280                        },
2281                    ],
2282                },
2283                RelativeDistinguishedName {
2284                    attributes: vec![AttributeTypeAndValue {
2285                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME).unwrap(),
2286                        attribute_value: "www.example.com".into(),
2287                    }],
2288                },
2289            ],
2290        }),
2291        case(Name {
2292            rdn_sequence: vec![
2293                RelativeDistinguishedName {
2294                    attributes: vec![AttributeTypeAndValue {
2295                        attribute_type: ObjectIdentifier::from_str(tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME).unwrap(),
2296                        attribute_value: "日本語ドメイン.jp".into(),
2297                    }],
2298                },
2299            ],
2300        })
2301    )]
2302    fn test_name_encode(name: Name) {
2303        let encoded = name.encode().unwrap();
2304
2305        match &encoded {
2306            Element::Sequence(rdn_elements) => {
2307                assert_eq!(rdn_elements.len(), name.rdn_sequence().len());
2308                for (i, rdn_elm) in rdn_elements.iter().enumerate() {
2309                    match rdn_elm {
2310                        Element::Set(attr_elements) => {
2311                            assert_eq!(
2312                                attr_elements.len(),
2313                                name.rdn_sequence()[i].attributes.len()
2314                            );
2315                            for (j, attr_elm) in attr_elements.iter().enumerate() {
2316                                match attr_elm {
2317                                    Element::Sequence(seq) => {
2318                                        assert_eq!(seq.len(), 2);
2319                                        match &seq[0] {
2320                                            Element::ObjectIdentifier(oid) => {
2321                                                assert_eq!(
2322                                                    oid,
2323                                                    &name.rdn_sequence()[i].attributes[j]
2324                                                        .attribute_type
2325                                                );
2326                                            }
2327                                            _ => panic!("Expected ObjectIdentifier"),
2328                                        }
2329                                        // Check that appropriate string type is used
2330                                        match &seq[1] {
2331                                            Element::PrintableString(s) => {
2332                                                assert_eq!(
2333                                                    s,
2334                                                    name.rdn_sequence()[i].attributes[j]
2335                                                        .attribute_value
2336                                                        .as_str()
2337                                                );
2338                                            }
2339                                            Element::UTF8String(s) => {
2340                                                assert_eq!(
2341                                                    s,
2342                                                    name.rdn_sequence()[i].attributes[j]
2343                                                        .attribute_value
2344                                                        .as_str()
2345                                                );
2346                                            }
2347                                            _ => panic!("Expected PrintableString or UTF8String"),
2348                                        }
2349                                    }
2350                                    _ => panic!("Expected Sequence for AttributeTypeAndValue"),
2351                                }
2352                            }
2353                        }
2354                        _ => panic!("Expected Set for RDN"),
2355                    }
2356                }
2357            }
2358            _ => panic!("Expected Sequence"),
2359        }
2360
2361        // Round-trip test
2362        let decoded: Name = encoded.decode().unwrap();
2363        assert_eq!(decoded, name);
2364    }
2365
2366    #[rstest(
2367        exts,
2368        case(Extensions {
2369            extensions: vec![
2370                RawExtension::new(
2371                    ObjectIdentifier::from_str(crate::extensions::BasicConstraints::OID).unwrap(),
2372                    false,
2373                    OctetString::from(vec![0x30, 0x00]),
2374                ),
2375            ],
2376        }),
2377        case(Extensions {
2378            extensions: vec![
2379                RawExtension::new(
2380                    ObjectIdentifier::from_str(crate::extensions::KeyUsage::OID).unwrap(),
2381                    true,
2382                    OctetString::from(vec![0x03, 0x02, 0x05, 0xa0]),
2383                ),
2384            ],
2385        }),
2386        case(Extensions {
2387            extensions: vec![
2388                RawExtension::new(
2389                    ObjectIdentifier::from_str(crate::extensions::BasicConstraints::OID).unwrap(),
2390                    true,
2391                    OctetString::from(vec![0x30, 0x03, 0x01, 0x01, 0xff]),
2392                ),
2393                RawExtension::new(
2394                    ObjectIdentifier::from_str(crate::extensions::SubjectKeyIdentifier::OID).unwrap(),
2395                    false,
2396                    OctetString::from(vec![0x04, 0x14, 0x01, 0x02, 0x03]),
2397                ),
2398            ],
2399        })
2400    )]
2401    fn test_extensions_encode(exts: Extensions) {
2402        let encoded = exts.encode().unwrap();
2403
2404        // Should be wrapped in [3] EXPLICIT
2405        match &encoded {
2406            Element::ContextSpecific { slot, element, .. } => {
2407                assert_eq!(slot, &3);
2408                match element.as_ref() {
2409                    Element::Sequence(ext_elements) => {
2410                        assert_eq!(ext_elements.len(), exts.extensions.len());
2411
2412                        for (i, ext_elm) in ext_elements.iter().enumerate() {
2413                            match ext_elm {
2414                                Element::Sequence(fields) => {
2415                                    // Check OID
2416                                    match &fields[0] {
2417                                        Element::ObjectIdentifier(oid) => {
2418                                            assert_eq!(oid, exts.extensions[i].oid());
2419                                        }
2420                                        _ => panic!("Expected ObjectIdentifier"),
2421                                    }
2422
2423                                    // Check critical field (only present if true)
2424                                    let value_index = if exts.extensions[i].is_critical() {
2425                                        assert_eq!(fields.len(), 3);
2426                                        match &fields[1] {
2427                                            Element::Boolean(b) => assert!(b),
2428                                            _ => panic!("Expected Boolean"),
2429                                        }
2430                                        2
2431                                    } else {
2432                                        assert_eq!(fields.len(), 2);
2433                                        1
2434                                    };
2435
2436                                    // Check value
2437                                    match &fields[value_index] {
2438                                        Element::OctetString(octets) => {
2439                                            assert_eq!(
2440                                                octets.as_bytes(),
2441                                                exts.extensions[i].value().as_bytes()
2442                                            );
2443                                        }
2444                                        _ => panic!("Expected OctetString"),
2445                                    }
2446                                }
2447                                _ => panic!("Expected Sequence for Extension"),
2448                            }
2449                        }
2450                    }
2451                    _ => panic!("Expected Sequence inside [3]"),
2452                }
2453            }
2454            _ => panic!("Expected ContextSpecific [3]"),
2455        }
2456
2457        // Round-trip test
2458        let decoded: Extensions = encoded.decode().unwrap();
2459        assert_eq!(decoded, exts);
2460    }
2461
2462    fn create_tbs_v3_with_extensions() -> TBSCertificate {
2463        TBSCertificate {
2464            version: Version::V3,
2465            serial_number: CertificateSerialNumber::from_bytes(vec![0x01, 0x02, 0x03]),
2466            signature: AlgorithmIdentifier {
2467                algorithm: ObjectIdentifier::from_str(
2468                    tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION,
2469                )
2470                .unwrap(),
2471                parameters: Some(AlgorithmParameters::Null),
2472            },
2473            issuer: Name {
2474                rdn_sequence: vec![RelativeDistinguishedName {
2475                    attributes: vec![AttributeTypeAndValue {
2476                        attribute_type: ObjectIdentifier::from_str(
2477                            tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME,
2478                        )
2479                        .unwrap(),
2480                        attribute_value: "Test CA".into(),
2481                    }],
2482                }],
2483            },
2484            validity: Validity {
2485                not_before: NaiveDate::from_ymd_opt(2024, 1, 1)
2486                    .unwrap()
2487                    .and_hms_opt(0, 0, 0)
2488                    .unwrap(),
2489                not_after: NaiveDate::from_ymd_opt(2025, 1, 1)
2490                    .unwrap()
2491                    .and_hms_opt(0, 0, 0)
2492                    .unwrap(),
2493            },
2494            subject: Name {
2495                rdn_sequence: vec![RelativeDistinguishedName {
2496                    attributes: vec![AttributeTypeAndValue {
2497                        attribute_type: ObjectIdentifier::from_str(
2498                            tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME,
2499                        )
2500                        .unwrap(),
2501                        attribute_value: "Test Subject".into(),
2502                    }],
2503                }],
2504            },
2505            subject_public_key_info: SubjectPublicKeyInfo::new(
2506                AlgorithmIdentifier::new_with_params(
2507                    ObjectIdentifier::from_str("1.2.840.113549.1.1.1").unwrap(),
2508                    AlgorithmParameters::Null,
2509                ),
2510                BitString::new(0, vec![0x30, 0x0d]),
2511            ),
2512            issuer_unique_id: None,
2513            subject_unique_id: None,
2514            extensions: Some(Extensions {
2515                extensions: vec![RawExtension::new(
2516                    ObjectIdentifier::from_str(crate::extensions::BasicConstraints::OID).unwrap(),
2517                    true,
2518                    OctetString::from(vec![0x30, 0x03, 0x01, 0x01, 0xff]),
2519                )],
2520            }),
2521        }
2522    }
2523
2524    fn create_tbs_v1_minimal() -> TBSCertificate {
2525        TBSCertificate {
2526            version: Version::V1,
2527            serial_number: CertificateSerialNumber::from_bytes(vec![0x01]),
2528            signature: AlgorithmIdentifier {
2529                algorithm: ObjectIdentifier::from_str("1.2.840.113549.1.1.5").unwrap(),
2530                parameters: Some(AlgorithmParameters::Null),
2531            },
2532            issuer: Name {
2533                rdn_sequence: vec![RelativeDistinguishedName {
2534                    attributes: vec![AttributeTypeAndValue {
2535                        attribute_type: ObjectIdentifier::from_str(
2536                            tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME,
2537                        )
2538                        .unwrap(),
2539                        attribute_value: "CA".into(),
2540                    }],
2541                }],
2542            },
2543            validity: Validity {
2544                not_before: NaiveDate::from_ymd_opt(2000, 1, 1)
2545                    .unwrap()
2546                    .and_hms_opt(0, 0, 0)
2547                    .unwrap(),
2548                not_after: NaiveDate::from_ymd_opt(2001, 1, 1)
2549                    .unwrap()
2550                    .and_hms_opt(0, 0, 0)
2551                    .unwrap(),
2552            },
2553            subject: Name {
2554                rdn_sequence: vec![RelativeDistinguishedName {
2555                    attributes: vec![AttributeTypeAndValue {
2556                        attribute_type: ObjectIdentifier::from_str(
2557                            tsumiki_pkix_types::AttributeTypeAndValue::OID_COMMON_NAME,
2558                        )
2559                        .unwrap(),
2560                        attribute_value: "Subject".into(),
2561                    }],
2562                }],
2563            },
2564            subject_public_key_info: SubjectPublicKeyInfo::new(
2565                AlgorithmIdentifier::new_with_params(
2566                    ObjectIdentifier::from_str("1.2.840.113549.1.1.1").unwrap(),
2567                    AlgorithmParameters::Null,
2568                ),
2569                BitString::new(0, vec![0x30, 0x0d]),
2570            ),
2571            issuer_unique_id: None,
2572            subject_unique_id: None,
2573            extensions: None,
2574        }
2575    }
2576
2577    #[rstest(
2578        tbs,
2579        case(create_tbs_v3_with_extensions()),
2580        case(create_tbs_v1_minimal())
2581    )]
2582    fn test_tbs_certificate_encode(tbs: TBSCertificate) {
2583        let encoded = tbs.encode().unwrap();
2584
2585        // Should be a Sequence
2586        match &encoded {
2587            Element::Sequence(elements) => {
2588                // V1 certificates have 6 fields (no version field)
2589                // V3 certificates with extensions have 8 fields (version + 6 required + extensions)
2590                if tbs.version == Version::V1 {
2591                    assert_eq!(elements.len(), 6);
2592                } else {
2593                    assert!(elements.len() >= 7);
2594                }
2595            }
2596            _ => panic!("Expected Sequence for TBSCertificate"),
2597        }
2598
2599        // Round-trip test
2600        let decoded: TBSCertificate = encoded.decode().unwrap();
2601        assert_eq!(decoded.version, tbs.version);
2602        assert_eq!(decoded.serial_number, tbs.serial_number);
2603        assert_eq!(decoded.signature, tbs.signature);
2604        assert_eq!(decoded.issuer, tbs.issuer);
2605        assert_eq!(decoded.validity, tbs.validity);
2606        assert_eq!(decoded.subject, tbs.subject);
2607        assert_eq!(decoded.subject_public_key_info, tbs.subject_public_key_info);
2608        assert_eq!(decoded.issuer_unique_id, tbs.issuer_unique_id);
2609        assert_eq!(decoded.subject_unique_id, tbs.subject_unique_id);
2610        assert_eq!(decoded.extensions, tbs.extensions);
2611    }
2612
2613    #[test]
2614    fn test_certificate_encode_decode_roundtrip() {
2615        // Test with a real V3 certificate
2616        let pem = Pem::from_str(TEST_CERT_V3_EE).unwrap();
2617        let der: Der = pem.decode().unwrap();
2618        let asn1_obj: ASN1Object = der.decode().unwrap();
2619
2620        // Decode certificate
2621        let cert: Certificate = asn1_obj.decode().unwrap();
2622
2623        // Encode certificate
2624        let encoded_element: Element = cert.encode().unwrap();
2625
2626        // Decode back
2627        let decoded_cert: Certificate = encoded_element.decode().unwrap();
2628
2629        // Verify all fields match
2630        assert_eq!(decoded_cert.tbs_certificate, cert.tbs_certificate);
2631        assert_eq!(decoded_cert.signature_algorithm, cert.signature_algorithm);
2632        assert_eq!(decoded_cert.signature_value, cert.signature_value);
2633    }
2634
2635    #[test]
2636    fn test_certificate_encode_decode_v1() {
2637        // Test with V1 certificate (no extensions)
2638        let pem = Pem::from_str(TEST_CERT_V1).unwrap();
2639        let der: Der = pem.decode().unwrap();
2640        let asn1_obj: ASN1Object = der.decode().unwrap();
2641
2642        let cert: Certificate = asn1_obj.decode().unwrap();
2643        let encoded_element: Element = cert.encode().unwrap();
2644        let decoded_cert: Certificate = encoded_element.decode().unwrap();
2645
2646        assert_eq!(decoded_cert.tbs_certificate.version, Version::V1);
2647        assert_eq!(decoded_cert.tbs_certificate, cert.tbs_certificate);
2648        assert_eq!(decoded_cert.signature_algorithm, cert.signature_algorithm);
2649        assert_eq!(decoded_cert.signature_value, cert.signature_value);
2650    }
2651
2652    #[test]
2653    fn test_certificate_encode_decode_v3_ca() {
2654        // Test with V3 CA certificate
2655        let pem = Pem::from_str(TEST_CERT_V3_CA).unwrap();
2656        let der: Der = pem.decode().unwrap();
2657        let asn1_obj: ASN1Object = der.decode().unwrap();
2658
2659        let cert: Certificate = asn1_obj.decode().unwrap();
2660        let encoded_element: Element = cert.encode().unwrap();
2661        let decoded_cert: Certificate = encoded_element.decode().unwrap();
2662
2663        assert_eq!(decoded_cert.tbs_certificate.version, Version::V3);
2664        assert!(decoded_cert.tbs_certificate.extensions.is_some());
2665        assert_eq!(decoded_cert.tbs_certificate, cert.tbs_certificate);
2666        assert_eq!(decoded_cert.signature_algorithm, cert.signature_algorithm);
2667        assert_eq!(decoded_cert.signature_value, cert.signature_value);
2668    }
2669
2670    #[test]
2671    fn test_certificate_encode_to_asn1object() {
2672        // Test with V3 EE certificate
2673        let pem = Pem::from_str(TEST_CERT_V3_EE).unwrap();
2674        let der: Der = pem.decode().unwrap();
2675        let original_asn1_obj: ASN1Object = der.decode().unwrap();
2676
2677        // Decode certificate
2678        let cert: Certificate = original_asn1_obj.decode().unwrap();
2679
2680        // Encode to ASN1Object
2681        let encoded_asn1_obj: ASN1Object = cert.encode().unwrap();
2682
2683        // Decode back from ASN1Object
2684        let decoded_cert: Certificate = encoded_asn1_obj.decode().unwrap();
2685
2686        // Verify all fields match
2687        assert_eq!(decoded_cert.tbs_certificate, cert.tbs_certificate);
2688        assert_eq!(decoded_cert.signature_algorithm, cert.signature_algorithm);
2689        assert_eq!(decoded_cert.signature_value, cert.signature_value);
2690
2691        // Verify ASN1Object structure
2692        assert_eq!(encoded_asn1_obj.elements().len(), 1);
2693        assert!(matches!(
2694            encoded_asn1_obj.elements()[0],
2695            Element::Sequence(_)
2696        ));
2697    }
2698
2699    #[test]
2700    fn test_certificate_encode_to_asn1object_v1() {
2701        // Test with V1 certificate
2702        let pem = Pem::from_str(TEST_CERT_V1).unwrap();
2703        let der: Der = pem.decode().unwrap();
2704        let original_asn1_obj: ASN1Object = der.decode().unwrap();
2705
2706        let cert: Certificate = original_asn1_obj.decode().unwrap();
2707        let encoded_asn1_obj: ASN1Object = cert.encode().unwrap();
2708        let decoded_cert: Certificate = encoded_asn1_obj.decode().unwrap();
2709
2710        assert_eq!(decoded_cert.tbs_certificate.version, Version::V1);
2711        assert_eq!(decoded_cert.tbs_certificate, cert.tbs_certificate);
2712        assert_eq!(decoded_cert.signature_algorithm, cert.signature_algorithm);
2713        assert_eq!(decoded_cert.signature_value, cert.signature_value);
2714    }
2715
2716    #[test]
2717    fn test_version_constructed_flag() {
2718        // Version is [0] EXPLICIT, so constructed should be true
2719        let version = Version::V3;
2720        let encoded = version.encode().unwrap();
2721
2722        match encoded {
2723            Element::ContextSpecific {
2724                slot, constructed, ..
2725            } => {
2726                assert_eq!(slot, 0);
2727                assert!(
2728                    constructed,
2729                    "Version [0] EXPLICIT should have constructed=true"
2730                );
2731            }
2732            _ => panic!("Version should encode to ContextSpecific"),
2733        }
2734    }
2735
2736    #[test]
2737    fn test_unique_identifier_constructed_flag() {
2738        // UniqueIdentifier is [1]/[2] IMPLICIT BitString, so constructed should be false
2739        let unique_id = UniqueIdentifier(BitString::new(0, vec![0x01, 0x02, 0x03]));
2740
2741        // Create TBSCertificate with issuerUniqueID to test encoding
2742        let tbs = TBSCertificate {
2743            version: Version::V3,
2744            serial_number: CertificateSerialNumber::from_bytes(vec![0x01]),
2745            signature: AlgorithmIdentifier {
2746                algorithm: ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(),
2747                parameters: None,
2748            },
2749            issuer: Name {
2750                rdn_sequence: vec![],
2751            },
2752            validity: Validity {
2753                not_before: NaiveDate::from_ymd_opt(1970, 1, 1)
2754                    .unwrap()
2755                    .and_hms_opt(0, 0, 0)
2756                    .unwrap(),
2757                not_after: NaiveDate::from_ymd_opt(1970, 1, 1)
2758                    .unwrap()
2759                    .and_hms_opt(0, 0, 1)
2760                    .unwrap(),
2761            },
2762            subject: Name {
2763                rdn_sequence: vec![],
2764            },
2765            subject_public_key_info: SubjectPublicKeyInfo::new(
2766                AlgorithmIdentifier::new(
2767                    ObjectIdentifier::from_str("1.2.840.113549.1.1.1").unwrap(),
2768                ),
2769                BitString::new(0, vec![0x00]),
2770            ),
2771            issuer_unique_id: Some(unique_id),
2772            subject_unique_id: None,
2773            extensions: None,
2774        };
2775
2776        let encoded = tbs.encode().unwrap();
2777
2778        if let Element::Sequence(elements) = encoded {
2779            // Find the issuerUniqueID element (slot 1)
2780            let issuer_uid = elements
2781                .iter()
2782                .find(|e| matches!(e, Element::ContextSpecific { slot: 1, .. }))
2783                .expect("issuerUniqueID should be present");
2784
2785            if let Element::ContextSpecific {
2786                slot, constructed, ..
2787            } = issuer_uid
2788            {
2789                assert_eq!(*slot, 1);
2790                assert!(
2791                    !(*constructed),
2792                    "issuerUniqueID [1] IMPLICIT should have constructed=false"
2793                );
2794            }
2795        } else {
2796            panic!("TBSCertificate should encode to Sequence");
2797        }
2798    }
2799}