1#![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#[derive(Debug, Clone, Deserialize)]
115pub struct Certificate {
116 tbs_certificate: TBSCertificate,
117 signature_algorithm: AlgorithmIdentifier,
118 signature_value: BitString, }
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 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 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 pub fn tbs_certificate(&self) -> &TBSCertificate {
166 &self.tbs_certificate
167 }
168
169 pub fn signature_algorithm(&self) -> &AlgorithmIdentifier {
171 &self.signature_algorithm
172 }
173
174 pub fn signature_value(&self) -> &BitString {
176 &self.signature_value
177 }
178
179 pub fn is_self_signed(&self) -> bool {
183 self.tbs_certificate.subject == self.tbs_certificate.issuer
184 }
185
186 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 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 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 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 writeln!(f, " Issuer: {}", self.tbs_certificate.issuer)?;
251
252 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 writeln!(f, " Subject: {}", self.tbs_certificate.subject)?;
273
274 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 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 if let Some(ref _exts) = self.tbs_certificate.extensions {
309 writeln!(f, " X509v3 extensions:")?;
310
311 if let Ok(Some(ski)) = self.extension::<extensions::SubjectKeyIdentifier>() {
313 write!(f, "{}", ski)?;
314 }
315
316 if let Ok(Some(aki)) = self.extension::<extensions::AuthorityKeyIdentifier>() {
318 write!(f, "{}", aki)?;
319 }
320
321 if let Ok(Some(bc)) = self.extension::<extensions::BasicConstraints>() {
323 write!(f, "{}", bc)?;
324 }
325
326 if let Ok(Some(ku)) = self.extension::<extensions::KeyUsage>() {
328 write!(f, "{}", ku)?;
329 }
330
331 if let Ok(Some(eku)) = self.extension::<extensions::ExtendedKeyUsage>() {
333 write!(f, "{}", eku)?;
334 }
335
336 if let Ok(Some(san)) = self.extension::<extensions::SubjectAltName>() {
338 write!(f, "{}", san)?;
339 }
340
341 if let Ok(Some(ian)) = self.extension::<extensions::IssuerAltName>() {
343 write!(f, "{}", ian)?;
344 }
345
346 if let Ok(Some(nc)) = self.extension::<extensions::NameConstraints>() {
348 write!(f, "{}", nc)?;
349 }
350
351 if let Ok(Some(cdp)) = self.extension::<extensions::CRLDistributionPoints>() {
353 write!(f, "{}", cdp)?;
354 }
355
356 if let Ok(Some(cp)) = self.extension::<extensions::CertificatePolicies>() {
358 write!(f, "{}", cp)?;
359 }
360
361 if let Ok(Some(pm)) = self.extension::<extensions::PolicyMappings>() {
363 write!(f, "{}", pm)?;
364 }
365
366 if let Ok(Some(pc)) = self.extension::<extensions::PolicyConstraints>() {
368 write!(f, "{}", pc)?;
369 }
370
371 if let Ok(Some(fcrl)) = self.extension::<extensions::FreshestCRL>() {
373 write!(f, "{}", fcrl)?;
374 }
375
376 if let Ok(Some(iap)) = self.extension::<extensions::InhibitAnyPolicy>() {
378 write!(f, "{}", iap)?;
379 }
380
381 if let Ok(Some(aia)) = self.extension::<extensions::AuthorityInfoAccess>() {
383 write!(f, "{}", aia)?;
384 }
385
386 let handled_oids = vec![
388 "2.5.29.14", "2.5.29.35", "2.5.29.19", "2.5.29.15", "2.5.29.37", "2.5.29.17", "2.5.29.18", "2.5.29.30", "2.5.29.31", "2.5.29.32", "2.5.29.33", "2.5.29.36", "2.5.29.46", "2.5.29.54", "1.3.6.1.5.5.7.1.1", ];
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 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 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 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 let tbs_certificate: TBSCertificate = tbs_elem.decode()?;
493
494 let signature_algorithm: AlgorithmIdentifier = sig_alg_elem.decode()?;
496
497 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
539impl 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 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 let der_bytes: Vec<u8> = pem.decode()?;
568 let der: tsumiki_der::Der = der_bytes.decode()?;
569
570 let asn1_obj = der
572 .decode()
573 .map_err(|_| Error::CertificateDerDecodeFailed)?;
574
575 let element = asn1_obj.elements().first().ok_or(Error::EmptyCertificate)?;
577
578 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#[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 pub fn extensions(&self) -> Option<&Extensions> {
637 self.extensions.as_ref()
638 }
639
640 pub fn version(&self) -> &Version {
642 &self.version
643 }
644
645 pub fn serial_number(&self) -> &CertificateSerialNumber {
647 &self.serial_number
648 }
649
650 pub fn signature(&self) -> &AlgorithmIdentifier {
652 &self.signature
653 }
654
655 pub fn issuer(&self) -> &Name {
657 &self.issuer
658 }
659
660 pub fn validity(&self) -> &Validity {
662 &self.validity
663 }
664
665 pub fn subject(&self) -> &Name {
667 &self.subject
668 }
669
670 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 if self.version != Version::V1 {
687 elements.push(self.version.encode()?);
688 }
689
690 elements.push(self.serial_number.encode()?);
692
693 elements.push(self.signature.encode()?);
695
696 elements.push(self.issuer.encode()?);
698
699 elements.push(self.validity.encode()?);
701
702 elements.push(self.subject.encode()?);
704
705 elements.push(self.subject_public_key_info.encode()?);
707
708 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 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 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 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 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 };
770
771 let serial_number = if let Some(elem) = iter.next() {
773 elem.decode()?
774 } else {
775 return Err(Error::MissingField(CertificateField::SerialNumber));
776 };
777
778 let signature = if let Some(elem) = iter.next() {
780 elem.decode()?
781 } else {
782 return Err(Error::MissingField(CertificateField::Signature));
783 };
784
785 let issuer = if let Some(elem) = iter.next() {
787 elem.decode()?
788 } else {
789 return Err(Error::MissingField(CertificateField::Issuer));
790 };
791
792 let validity = if let Some(elem) = iter.next() {
794 elem.decode()?
795 } else {
796 return Err(Error::MissingField(CertificateField::Validity));
797 };
798
799 let subject = if let Some(elem) = iter.next() {
801 elem.decode()?
802 } else {
803 return Err(Error::MissingField(CertificateField::Subject));
804 };
805
806 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 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#[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 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 match self {
920 Element::ContextSpecific { slot, element, .. } => {
921 if *slot != 1 && *slot != 2 {
922 return Err(Error::UniqueIdentifierInvalidTag(*slot));
923 }
924 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())), _ => Err(Error::UniqueIdentifierInvalidElement),
932 }
933 }
934}
935
936#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
963pub enum Version {
964 V1 = 0,
966 V2 = 1,
968 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 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 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#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1060pub struct Validity {
1061 not_before: NaiveDateTime,
1062 not_after: NaiveDateTime,
1063}
1064
1065impl Validity {
1066 pub fn not_before(&self) -> &NaiveDateTime {
1068 &self.not_before
1069 }
1070
1071 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 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#[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#[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 #[rstest(
1191 input,
1192 expected,
1193 case(
1195 Element::Sequence(vec![
1196 Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap()), ]),
1198 AlgorithmIdentifier {
1199 algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_SHA256_WITH_RSA_ENCRYPTION).unwrap(),
1200 parameters: None,
1201 }
1202 ),
1203 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 case(
1216 Element::Sequence(vec![
1217 Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_ECDSA_WITH_SHA256).unwrap()), 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 case(
1229 Element::Sequence(vec![
1230 Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap()), Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()), ]),
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 case(
1251 Element::Integer(Integer::from(vec![0x01])),
1252 "ExpectedSequence"
1253 ),
1254 case(
1256 Element::Sequence(vec![]),
1257 "EmptyAlgorithmIdentifier"
1258 ),
1259 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 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 #[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 #[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 #[rstest(
1417 not_before_element,
1418 not_after_element,
1419 expected_not_before,
1420 expected_not_after,
1421 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 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 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 case(
1461 Element::Sequence(vec![]),
1462 "expected 2 elements in SEQUENCE"
1463 ),
1464 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 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 case(
1482 Element::Integer(Integer::from(vec![0x01])),
1483 "expected SEQUENCE"
1484 ),
1485 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 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 #[rstest(
1532 input,
1533 expected,
1534 case(
1536 Element::Sequence(vec![
1537 Element::Sequence(vec![
1538 Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_RSA_ENCRYPTION).unwrap()), Element::Null,
1540 ]),
1541 Element::BitString(BitString::new(0, vec![
1542 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0x6c, 0x8f, ])),
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 case(
1561 Element::Sequence(vec![
1562 Element::Sequence(vec![
1563 Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap()), Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap()), ]),
1566 Element::BitString(BitString::new(0, vec![
1567 0x04, 0x8d, 0x61, 0x7e, 0x65, 0x3b, 0x6b, 0x80, 0x69, ])),
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 case(
1588 Element::Sequence(vec![
1589 Element::Sequence(vec![
1590 Element::ObjectIdentifier(ObjectIdentifier::from_str("1.3.101.112").unwrap()), ]),
1592 Element::BitString(BitString::new(0, vec![
1593 0x8d, 0x61, 0x7e, 0x65, 0x3b, 0x6b, 0x80, 0x69, 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 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])), ]),
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 case(
1641 Element::Integer(Integer::from(vec![0x01])),
1642 "expected SEQUENCE"
1643 ),
1644 case(
1646 Element::Sequence(vec![]),
1647 "expected 2 elements, got 0"
1648 ),
1649 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 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 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 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 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 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 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 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 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 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 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); 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 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); assert_eq!(cert.tbs_certificate.issuer.rdn_sequence().len(), 6); }
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 println!("\n=== V3 End Entity Certificate (Display) ===");
1885 println!("{}", cert);
1886
1887 let json_output = serde_json::to_string_pretty(&cert).unwrap();
1889 println!("\n=== V3 End Entity Certificate (JSON) ===");
1890 println!("{}", json_output);
1891
1892 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); assert_eq!(cert.tbs_certificate.issuer.rdn_sequence().len(), 4); }
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 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); 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 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 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); 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 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 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 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 let json_output = serde_json::to_string_pretty(&cert).unwrap();
1985 println!("{}", json_output);
1986
1987 assert_eq!(cert.tbs_certificate.version, Version::V1);
1990 assert!(cert.tbs_certificate.extensions.is_none());
1992 assert_eq!(
1994 cert.tbs_certificate.issuer.rdn_sequence().len(),
1995 3 );
1997 assert_eq!(
1998 cert.tbs_certificate.subject.rdn_sequence().len(),
1999 3 );
2001 }
2002
2003 #[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 assert!(alg_id.parameters.is_some());
2041 }
2042 }
2043 _ => panic!("Expected Sequence"),
2044 }
2045
2046 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 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]) )]
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 }
2096 _ => panic!("Expected Integer"),
2097 }
2098
2099 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 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 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(), parameters: None,
2168 },
2169 vec![0x30, 0x0d, 0x06, 0x09] ),
2171 case(
2172 AlgorithmIdentifier {
2173 algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(), parameters: Some(AlgorithmParameters::Other(
2175 RawAlgorithmParameter::new(Element::ObjectIdentifier(ObjectIdentifier::from_str(tsumiki_pkix_types::algorithm::parameters::ec::NamedCurve::Secp256r1.oid_str()).unwrap())) )),
2177 },
2178 vec![0x04, 0x41] ),
2180 case(
2181 AlgorithmIdentifier {
2182 algorithm: ObjectIdentifier::from_str(tsumiki_pkix_types::AlgorithmIdentifier::OID_EC_PUBLIC_KEY).unwrap(), parameters: Some(AlgorithmParameters::Null),
2184 },
2185 vec![0xff, 0xee, 0xdd] )
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 let decoded_algorithm: AlgorithmIdentifier = elements[0].decode().unwrap();
2205 assert_eq!(decoded_algorithm, algorithm);
2206
2207 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 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 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 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 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 match &fields[0] {
2417 Element::ObjectIdentifier(oid) => {
2418 assert_eq!(oid, exts.extensions[i].oid());
2419 }
2420 _ => panic!("Expected ObjectIdentifier"),
2421 }
2422
2423 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 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 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 match &encoded {
2587 Element::Sequence(elements) => {
2588 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 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 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 let cert: Certificate = asn1_obj.decode().unwrap();
2622
2623 let encoded_element: Element = cert.encode().unwrap();
2625
2626 let decoded_cert: Certificate = encoded_element.decode().unwrap();
2628
2629 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 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 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 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 let cert: Certificate = original_asn1_obj.decode().unwrap();
2679
2680 let encoded_asn1_obj: ASN1Object = cert.encode().unwrap();
2682
2683 let decoded_cert: Certificate = encoded_asn1_obj.decode().unwrap();
2685
2686 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 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 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 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 let unique_id = UniqueIdentifier(BitString::new(0, vec![0x01, 0x02, 0x03]));
2740
2741 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 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}