|  | use chrono::offset::{TimeZone, Utc}; | 
|  | use chrono::Datelike; | 
|  | use der_parser::oid; | 
|  | use nom::Parser; | 
|  | use oid_registry::*; | 
|  | use std::collections::HashMap; | 
|  | use x509_parser::prelude::*; | 
|  |  | 
|  | static IGCA_DER: &[u8] = include_bytes!("../assets/IGC_A.der"); | 
|  | static NO_EXTENSIONS_DER: &[u8] = include_bytes!("../assets/no_extensions.der"); | 
|  | static V1: &[u8] = include_bytes!("../assets/v1.der"); | 
|  | static CRL_DER: &[u8] = include_bytes!("../assets/example.crl"); | 
|  | static EMPTY_CRL_DER: &[u8] = include_bytes!("../assets/empty.crl"); | 
|  | static MINIMAL_CRL_DER: &[u8] = include_bytes!("../assets/minimal.crl"); | 
|  | static DUPLICATE_VALUE_IN_AIA: &[u8] = | 
|  | include_bytes!("../assets/duplicate_value_in_authority_info_access.der"); | 
|  |  | 
|  | #[test] | 
|  | fn test_x509_parser() { | 
|  | let empty = &b""[..]; | 
|  | //assert_eq!(x509_parser(IGCA_DER), IResult::Done(empty, (1))); | 
|  | let res = parse_x509_certificate(IGCA_DER); | 
|  | // println!("res: {:?}", res); | 
|  | match res { | 
|  | Ok((e, cert)) => { | 
|  | assert_eq!(e, empty); | 
|  | // | 
|  | let tbs_cert = &cert.tbs_certificate; | 
|  | assert_eq!(tbs_cert.version, X509Version::V3); | 
|  | // | 
|  | let s = tbs_cert.raw_serial_as_string(); | 
|  | assert_eq!(&s, "39:11:45:10:94"); | 
|  | // | 
|  | let expected_subject = "C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, CN=IGC/A, Email=igca@sgdn.pm.gouv.fr"; | 
|  | assert_eq!(format!("{}", tbs_cert.subject), expected_subject); | 
|  | // | 
|  | let cn_list: Result<Vec<_>, X509Error> = cert | 
|  | .subject() | 
|  | .iter_common_name() | 
|  | .map(|attr| attr.as_str()) | 
|  | .collect(); | 
|  | assert_eq!(cn_list, Ok(vec!["IGC/A"])); | 
|  | // | 
|  | let sig = &tbs_cert.signature; | 
|  | assert_eq!(sig.algorithm, oid!(1.2.840 .113549 .1 .1 .5)); | 
|  | // | 
|  | let expected_issuer = "C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, CN=IGC/A, Email=igca@sgdn.pm.gouv.fr"; | 
|  | assert_eq!(format!("{}", tbs_cert.issuer), expected_issuer); | 
|  | let expected_issuer_der = &IGCA_DER[35..171]; | 
|  | assert_eq!(tbs_cert.issuer.as_raw(), expected_issuer_der); | 
|  | // | 
|  | let sig_alg = &cert.signature_algorithm; | 
|  | assert_eq!(sig_alg.algorithm, OID_PKCS1_SHA1WITHRSA); | 
|  | // | 
|  | let not_before = tbs_cert.validity.not_before; | 
|  | let not_after = tbs_cert.validity.not_after; | 
|  | let nb = Utc.timestamp(not_before.timestamp(), 0); | 
|  | let na = Utc.timestamp(not_after.timestamp(), 0); | 
|  | assert_eq!(nb.year(), 2002); | 
|  | assert_eq!(nb.month(), 12); | 
|  | assert_eq!(nb.day(), 13); | 
|  | assert_eq!(na.year(), 2020); | 
|  | assert_eq!(na.month(), 10); | 
|  | assert_eq!(na.day(), 17); | 
|  | let policies = vec![PolicyInformation { | 
|  | policy_id: oid!(1.2.250 .1 .121 .1 .1 .1), | 
|  | policy_qualifiers: None, | 
|  | }]; | 
|  | let expected_extensions = vec![ | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .19), | 
|  | true, | 
|  | &[48, 3, 1, 1, 255], | 
|  | ParsedExtension::BasicConstraints(BasicConstraints { | 
|  | ca: true, | 
|  | path_len_constraint: None, | 
|  | }), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .15), | 
|  | false, | 
|  | &[3, 2, 1, 70], | 
|  | ParsedExtension::KeyUsage(KeyUsage { flags: 98 }), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .32), | 
|  | false, | 
|  | &[48, 12, 48, 10, 6, 8, 42, 129, 122, 1, 121, 1, 1, 1], | 
|  | ParsedExtension::CertificatePolicies(policies), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .14), | 
|  | false, | 
|  | &[ | 
|  | 4, 20, 163, 5, 47, 24, 96, 80, 194, 137, 10, 221, 43, 33, 79, 255, 142, 78, | 
|  | 168, 48, 49, 54, | 
|  | ], | 
|  | ParsedExtension::SubjectKeyIdentifier(KeyIdentifier(&[ | 
|  | 163, 5, 47, 24, 96, 80, 194, 137, 10, 221, 43, 33, 79, 255, 142, 78, 168, | 
|  | 48, 49, 54, | 
|  | ])), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .35), | 
|  | false, | 
|  | &[ | 
|  | 48, 22, 128, 20, 163, 5, 47, 24, 96, 80, 194, 137, 10, 221, 43, 33, 79, | 
|  | 255, 142, 78, 168, 48, 49, 54, | 
|  | ], | 
|  | ParsedExtension::AuthorityKeyIdentifier(AuthorityKeyIdentifier { | 
|  | key_identifier: Some(KeyIdentifier(&[ | 
|  | 163, 5, 47, 24, 96, 80, 194, 137, 10, 221, 43, 33, 79, 255, 142, 78, | 
|  | 168, 48, 49, 54, | 
|  | ])), | 
|  | authority_cert_issuer: None, | 
|  | authority_cert_serial: None, | 
|  | }), | 
|  | ), | 
|  | ]; | 
|  | assert_eq!(tbs_cert.extensions(), &expected_extensions as &[_]); | 
|  | // | 
|  | assert!(tbs_cert.is_ca()); | 
|  | // | 
|  | assert_eq!(tbs_cert.as_ref(), &IGCA_DER[4..(8 + 746)]); | 
|  | } | 
|  | _ => panic!("x509 parsing failed: {:?}", res), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_x509_no_extensions() { | 
|  | let empty = &b""[..]; | 
|  | let res = parse_x509_certificate(NO_EXTENSIONS_DER); | 
|  | match res { | 
|  | Ok((e, cert)) => { | 
|  | assert_eq!(e, empty); | 
|  |  | 
|  | let tbs_cert = cert.tbs_certificate; | 
|  | assert_eq!(tbs_cert.version, X509Version::V3); | 
|  | assert_eq!(tbs_cert.extensions().len(), 0); | 
|  | } | 
|  | _ => panic!("x509 parsing failed: {:?}", res), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_parse_subject_public_key_info() { | 
|  | let res = SubjectPublicKeyInfo::from_der(&IGCA_DER[339..]) | 
|  | .expect("Parse public key info") | 
|  | .1; | 
|  | assert_eq!(res.algorithm.algorithm, OID_PKCS1_RSAENCRYPTION); | 
|  | let params = res.algorithm.parameters.expect("algorithm parameters"); | 
|  | assert_eq!(params.header.tag.0, 5); | 
|  | let spk = res.subject_public_key; | 
|  | println!("spk.data.len {}", spk.data.len()); | 
|  | assert_eq!(spk.data.len(), 270); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_version_v1() { | 
|  | let (rem, cert) = parse_x509_certificate(V1).expect("Could not parse v1 certificate"); | 
|  | assert!(rem.is_empty()); | 
|  | assert_eq!(cert.version(), X509Version::V1); | 
|  | let tbs_cert = cert.tbs_certificate; | 
|  | assert_eq!(format!("{}", tbs_cert.subject), "CN=marquee"); | 
|  | assert_eq!(format!("{}", tbs_cert.issuer), "CN=marquee"); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_crl_parse() { | 
|  | match parse_x509_crl(CRL_DER) { | 
|  | Ok((e, cert)) => { | 
|  | assert!(e.is_empty()); | 
|  |  | 
|  | let tbs_cert_list = cert.tbs_cert_list; | 
|  | assert_eq!(tbs_cert_list.version, Some(X509Version::V2)); | 
|  |  | 
|  | let sig = &tbs_cert_list.signature; | 
|  | assert_eq!(sig.algorithm, OID_PKCS1_SHA1WITHRSA); | 
|  |  | 
|  | let expected_issuer = | 
|  | "O=Sample Signer Organization, OU=Sample Signer Unit, CN=Sample Signer Cert"; | 
|  | assert_eq!(format!("{}", tbs_cert_list.issuer), expected_issuer); | 
|  |  | 
|  | let sig_alg = &cert.signature_algorithm; | 
|  | assert_eq!(sig_alg.algorithm, OID_PKCS1_SHA1WITHRSA); | 
|  |  | 
|  | let this_update = tbs_cert_list.this_update; | 
|  | let next_update = tbs_cert_list.next_update.unwrap(); | 
|  | let tu = Utc.timestamp(this_update.timestamp(), 0); | 
|  | let nu = Utc.timestamp(next_update.timestamp(), 0); | 
|  | assert_eq!(tu.year(), 2013); | 
|  | assert_eq!(tu.month(), 2); | 
|  | assert_eq!(tu.day(), 18); | 
|  | assert_eq!(nu.year(), 2013); | 
|  | assert_eq!(nu.month(), 2); | 
|  | assert_eq!(nu.day(), 18); | 
|  |  | 
|  | let revocation_date = | 
|  | ASN1Time::from_timestamp(Utc.ymd(2013, 2, 18).and_hms(10, 22, 12).timestamp()); | 
|  | let invalidity_date = | 
|  | ASN1Time::from_timestamp(Utc.ymd(2013, 2, 18).and_hms(10, 22, 00).timestamp()); | 
|  |  | 
|  | let revoked_certs = &tbs_cert_list.revoked_certificates; | 
|  | let revoked_cert_0 = &revoked_certs[0]; | 
|  | assert_eq!(*revoked_cert_0.serial(), 0x147947u32.into()); | 
|  | assert_eq!(revoked_cert_0.revocation_date, revocation_date); | 
|  | let expected_extensions = vec![ | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .21), | 
|  | false, | 
|  | &[10, 1, 3], | 
|  | ParsedExtension::ReasonCode(ReasonCode::AffiliationChanged), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .24), | 
|  | false, | 
|  | &[ | 
|  | 24, 15, 50, 48, 49, 51, 48, 50, 49, 56, 49, 48, 50, 50, 48, 48, 90, | 
|  | ], | 
|  | ParsedExtension::InvalidityDate(invalidity_date), | 
|  | ), | 
|  | ]; | 
|  | assert_eq!(revoked_cert_0.extensions(), &expected_extensions as &[_]); | 
|  |  | 
|  | assert_eq!(revoked_certs.len(), 5); | 
|  | assert_eq!(revoked_certs[4].user_certificate, 1_341_771_u32.into()); | 
|  |  | 
|  | let expected_extensions = vec![ | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .35), | 
|  | false, | 
|  | &[ | 
|  | 48, 22, 128, 20, 190, 18, 1, 204, 170, 234, 17, 128, 218, 46, 173, 178, | 
|  | 234, 199, 181, 251, 159, 249, 173, 52, | 
|  | ], | 
|  | ParsedExtension::AuthorityKeyIdentifier(AuthorityKeyIdentifier { | 
|  | key_identifier: Some(KeyIdentifier(&[ | 
|  | 190, 18, 1, 204, 170, 234, 17, 128, 218, 46, 173, 178, 234, 199, 181, | 
|  | 251, 159, 249, 173, 52, | 
|  | ])), | 
|  | authority_cert_issuer: None, | 
|  | authority_cert_serial: None, | 
|  | }), | 
|  | ), | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .20), | 
|  | false, | 
|  | &[2, 1, 3], | 
|  | ParsedExtension::CRLNumber(3u32.into()), | 
|  | ), | 
|  | ]; | 
|  | assert_eq!(tbs_cert_list.extensions(), &expected_extensions as &[_]); | 
|  |  | 
|  | assert_eq!(tbs_cert_list.as_ref(), &CRL_DER[4..(4 + 4 + 508)]); | 
|  | } | 
|  | err => panic!("x509 parsing failed: {:?}", err), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_crl_parse_empty() { | 
|  | match parse_x509_crl(EMPTY_CRL_DER) { | 
|  | Ok((e, cert)) => { | 
|  | assert!(e.is_empty()); | 
|  | assert!(cert.tbs_cert_list.revoked_certificates.is_empty()); | 
|  |  | 
|  | let expected_extensions = vec![ | 
|  | X509Extension::new( | 
|  | oid!(2.5.29 .20), | 
|  | false, | 
|  | &[2, 1, 2], | 
|  | ParsedExtension::CRLNumber(2u32.into()), | 
|  | ), | 
|  | X509Extension::new( | 
|  | OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, | 
|  | false, | 
|  | &[ | 
|  | 48, 22, 128, 20, 34, 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, | 
|  | 82, 191, 80, 27, 57, 39, 6, 172, | 
|  | ], | 
|  | ParsedExtension::AuthorityKeyIdentifier(AuthorityKeyIdentifier { | 
|  | key_identifier: Some(KeyIdentifier(&[ | 
|  | 34, 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, 82, 191, 80, | 
|  | 27, 57, 39, 6, 172, | 
|  | ])), | 
|  | authority_cert_issuer: None, | 
|  | authority_cert_serial: None, | 
|  | }), | 
|  | ), | 
|  | ]; | 
|  | assert_eq!(cert.extensions(), &expected_extensions as &[_]); | 
|  | assert_eq!( | 
|  | cert.tbs_cert_list.as_ref(), | 
|  | &EMPTY_CRL_DER[4..(4 + 3 + 200)] | 
|  | ); | 
|  | } | 
|  | err => panic!("x509 parsing failed: {:?}", err), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_crl_parse_minimal() { | 
|  | match parse_x509_crl(MINIMAL_CRL_DER) { | 
|  | Ok((e, crl)) => { | 
|  | assert!(e.is_empty()); | 
|  | let revocation_date = | 
|  | ASN1Time::from_timestamp(Utc.ymd(1970, 1, 1).and_hms(0, 0, 0).timestamp()); | 
|  | let revoked_certificates = &crl.tbs_cert_list.revoked_certificates; | 
|  | assert_eq!(revoked_certificates.len(), 1); | 
|  | let revoked_cert_0 = &revoked_certificates[0]; | 
|  | assert_eq!(*revoked_cert_0.serial(), 42u32.into()); | 
|  | assert_eq!(revoked_cert_0.revocation_date, revocation_date); | 
|  | assert!(revoked_cert_0.extensions().is_empty()); | 
|  | assert!(crl.tbs_cert_list.extensions().is_empty()); | 
|  | assert_eq!(crl.tbs_cert_list.as_ref(), &MINIMAL_CRL_DER[4..(4 + 79)]); | 
|  | } | 
|  | err => panic!("x509 parsing failed: {:?}", err), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_duplicate_authority_info_access() { | 
|  | match parse_x509_certificate(DUPLICATE_VALUE_IN_AIA) { | 
|  | Ok((_, cert)) => { | 
|  | let extension = cert | 
|  | .tbs_certificate | 
|  | .find_extension(&OID_PKIX_AUTHORITY_INFO_ACCESS) | 
|  | .unwrap(); | 
|  | let mut accessdescs = HashMap::new(); | 
|  | let ca_issuers = vec![ | 
|  | &GeneralName::URI("http://cdp1.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"), | 
|  | &GeneralName::URI("http://cdp2.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"), | 
|  | ]; | 
|  | let ocsp = vec![&GeneralName::URI("http://ocsp.pca.dfn.de/OCSP-Server/OCSP")]; | 
|  | accessdescs.insert(OID_PKIX_ACCESS_DESCRIPTOR_CA_ISSUERS, ca_issuers); | 
|  | accessdescs.insert(OID_PKIX_ACCESS_DESCRIPTOR_OCSP, ocsp); | 
|  | if let ParsedExtension::AuthorityInfoAccess(aia) = extension.parsed_extension() { | 
|  | let h = aia.as_hashmap(); | 
|  | assert_eq!(h, accessdescs); | 
|  | } else { | 
|  | panic!("Wrong extension type parsed"); | 
|  | } | 
|  | } | 
|  | err => panic!("x509 parsing failed: {:?}", err), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_x509_parser_no_ext() { | 
|  | let mut parser = X509CertificateParser::new().with_deep_parse_extensions(false); | 
|  | let (_, x509) = parser.parse(IGCA_DER).expect("parsing failed"); | 
|  | for ext in x509.extensions() { | 
|  | assert_eq!(ext.parsed_extension(), &ParsedExtension::Unparsed); | 
|  | } | 
|  | } |