feat: add derparse-rs

This commit is contained in:
2023-11-26 00:02:25 +08:00
parent 8666bf8a51
commit 558c309c91
3 changed files with 434 additions and 0 deletions

194
derparse-rs/src/main.rs Executable file
View File

@@ -0,0 +1,194 @@
#!/usr/bin/env runrs
//! ```cargo
//! [dependencies]
//! base64 = "0.21.5"
//! der-parser = "8.2.0"
//! hex = "0.4.3"
//! oid-registry = { version = "0.6.1", features = ["x962", "x509", "crypto", "pkcs1", "pkcs12", "pkcs7", "pkcs9", "kdf", "ms_spc", "nist_algs"] }
//! ```
use std::fs;
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 args = std::env::args().skip(1).collect::<Vec<_>>();
if args.is_empty() {
println!("Require Args.");
return;
}
let arg1 = &args[0];
let content = try_parse(arg1);
let ber_obj = match der_parser::parse_ber(&content) {
Ok(ber_obj) => ber_obj.1,
Err(e) => panic!("Parse DER failed: {}", e),
};
let oid_reg = build_oid_register();
print(&oid_reg, 0, &ber_obj);
}
fn try_parse(arg1: &str) -> Vec<u8> {
let arg1 = arg1.replace("\n", "").replace("\r", "");
if let Ok(h) = hex::decode(&arg1) {
return h;
}
if let Ok(h) = base64::engine::general_purpose::STANDARD.decode(&arg1) {
return h;
}
if let Ok(content) = fs::read(&arg1) {
return content;
}
panic!("Parse arg failed: {}", arg1);
}
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
}