use base64::Engine; use der_parser::ber::{BerObject, BerObjectContent}; use der_parser::Oid; use oid_registry::{OidEntry, OidRegistry}; use oid_registry::asn1_rs::oid; fn main() { let b = "MIIB3DCCAWKgAwIBAgIUBmlMvQ8s4PNWa2dFxhZH6gpVEpUwCgYIKoZIzj0EAwIw HDEaMBgGA1UEAwwRSGF0dGVyIEVDIFJvb3QgQ0EwIBcNMjMxMDI5MDAwMDAwWhgP MjA2MzEwMjkwMDAwMDBaMBwxGjAYBgNVBAMMEUhhdHRlciBFQyBSb290IENBMHYw EAYHKoZIzj0CAQYFK4EEACIDYgAE3hLba+pjLyUPUiXO6DcSM0326f4yuziZiKNU rBKfgJ7GZ6Yydlh2Ke33vyhoBcvTQlHP4ocWGwm0RdJ0Wz+99tkxegv8VskEqIEo CU/U78w6DbcWvzQAAKfXUfGjjNpBo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUeYIe16r9vuTceUDXG0CAbI9Pp+owHwYDVR0j BBgwFoAUeYIe16r9vuTceUDXG0CAbI9Pp+owCgYIKoZIzj0EAwIDaAAwZQIxANym CiIqwtBXwcvn887Z9dnrdWXDEpJanID2nvwqa57ACIhTTu3d/UzFdOM6GWDR8AIw bC9qIy+izBeFPfbggsz6U9nF5++LbtRHBFQ2InWoI4GZd074SGPcYRalMV3AUZ5m"; let dd = base64::engine::general_purpose::STANDARD.decode(b.replace("\n", "")).unwrap(); let ber_obj = der_parser::parse_ber(&dd).unwrap().1; // println!("{:#?}", ber_obj); let oid_reg = build_oid_register(); print(&oid_reg, 0, &ber_obj); } fn print(oid_reg: &OidRegistry, depth: usize, ber_obj: &BerObject) { let prefix = " ".repeat(depth); match &ber_obj.content { BerObjectContent::EndOfContent => { println!("{}END OF CONTENT", prefix); } BerObjectContent::Boolean(b) => { println!("{}BOOLEAN: {}", prefix, b); } BerObjectContent::Integer(i) => { println!("{}INTEGER: {}", prefix, hex::encode(i)); } BerObjectContent::BitString(u, b) => { if let Ok(ber_obj) = der_parser::parse_ber(&b.data) { println!("{}BIT STRING[{}]", prefix, u); print(&oid_reg, depth + 1, &ber_obj.1); } else { println!("{}BIT STRING[{}] - {}", prefix, u, hex::encode(b.data)); } } BerObjectContent::OctetString(s) => { if let Ok(ber_obj) = der_parser::parse_ber(s) { println!("{}OCTET STRING", prefix); print(&oid_reg, depth + 1, &ber_obj.1); } else { println!("{}OCTET STRING: {}", prefix, hex::encode(s)); } } BerObjectContent::Null => { println!("{}NULL", prefix); } BerObjectContent::Enum(e) => { println!("{}ENUM: {}", prefix, e); } BerObjectContent::OID(oid) => { println!("{}OID: {}{}", prefix, oid, format_oid(oid_reg, oid)); } BerObjectContent::RelativeOID(oid) => { println!("{}RELATIVE OID: {}{}", prefix, oid, format_oid(oid_reg, oid)); } BerObjectContent::NumericString(s) => { println!("{}NUMERIC STRING: {}", prefix, s); } BerObjectContent::VisibleString(s) => { println!("{}VISIBLE STRING: {}", prefix, s); } BerObjectContent::PrintableString(s) => { println!("{}PRINTABLE STRING: {}", prefix, s); } BerObjectContent::IA5String(s) => { println!("{}IA5 STRING: {}", prefix, s); } BerObjectContent::UTF8String(s) => { println!("{}UTF8 STRING: {}", prefix, s); } BerObjectContent::T61String(s) => { println!("{}T61 STRING: {}", prefix, s); } BerObjectContent::VideotexString(s) => { println!("{}VIDEOTEX STRING: {}", prefix, s); } BerObjectContent::BmpString(s) => { println!("{}BMP STRING: {}", prefix, s); } BerObjectContent::UniversalString(s) => { println!("{}UNIVERSAL STRING: {}", prefix, hex::encode(s)); } BerObjectContent::GraphicString(s) => { println!("{}GRAPHIC STRING: {}", prefix, s); } BerObjectContent::GeneralString(s) => { println!("{}GENERAL STRING: {}", prefix, s); } BerObjectContent::ObjectDescriptor(d) => { println!("{}OBJECT DESCRIPTOR: {}", prefix, d); } BerObjectContent::Sequence(ber_objects) => { println!("{}SEQUENCE {{", prefix); for b in ber_objects { print(oid_reg, depth + 1, b); } println!("{}}}", prefix); } BerObjectContent::Set(ber_objects) => { println!("{}SET {{", prefix); for b in ber_objects { print(oid_reg, depth + 1, b); } println!("{}}}", prefix); } BerObjectContent::UTCTime(t) => { println!("{}UTC TIME: {}", prefix, t); } BerObjectContent::GeneralizedTime(t) => { println!("{}GENERALIZED TIME: {}", prefix, t); } BerObjectContent::Optional(o) => { println!("{}OPTIONAL {{", prefix); match o { None => { println!("{} NONE", prefix) } Some(o) => { print(oid_reg, depth + 1, o); } } println!("{}}}", prefix); } BerObjectContent::Tagged(c, t, o) => { println!("{}TAGGED class={} tag={} {{", prefix, c, t); print(oid_reg, depth + 1, o); println!("{}}}", prefix); } BerObjectContent::Unknown(u) => { let tag = u.header.tag().0; if let Ok(ber_obj) = der_parser::parse_ber(&u.data) { println!("{}[{}]", prefix, tag); print(&oid_reg, depth + 1, &ber_obj.1); } else { println!("{}[{}] {}", prefix, tag, hex::encode(&u.data)); } } } } fn format_oid(oid_reg: &OidRegistry, oid: &Oid) -> String { match oid_reg.get(oid) { None => "".to_string(), Some(e) => format!(" // {} ({})", e.sn(), e.description()) } } fn build_oid_register() -> OidRegistry<'static> { let mut oid_reg = OidRegistry::default() .with_pkcs1() .with_pkcs7() .with_pkcs9() .with_pkcs12() .with_x509() .with_x962() .with_kdf() .with_ms_spc() .with_nist_algs(); // more OIDs, https://site.hatter.ink/asn1js/oids.js oid_reg.insert(oid!(1.2.156.10197.1.301), OidEntry::new("sm2ECC", "China GM Standards Committee")); oid_reg }