rasn

A safe, #[no_std] ASN.1 codec framework for Rust that encodes and decodes BER, CER, DER, PER, OER, JER, and XER from one abstract data model.

Library
Cargo
v0.28.14
382stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
76/100Good
Development Activity68
Maintenance72
Community76
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture88
Code Quality85
Innovation82
Learning Curve65

rasn is a Rust crate that lets you model ASN.1 data types once and encode or decode them under any of ASN.1’s standard encoding rules — BER, CER, DER, aligned and unaligned PER, OER, COER, JER, and XER — without rewriting the type for each format. It ships as #[no_std] with alloc, so it targets embedded and constrained environments as well as ordinary application code, and its codecs are written entirely in safe Rust and fuzz-tested to handle untrusted input without crashing.

Beyond the core crate, the librasn organization maintains a family of #[no_std] companion crates that implement ASN.1 data types for specific IETF and industry standards on top of rasn’s traits — CMS, Kerberos, LDAP, OCSP, PKIX, SNMP, S/MIME, and connected-vehicle standards like IEEE 1609.2 and ETSI TS 103 097. Combined with derive macros for AsnType, Encode, and Decode that check tag uniqueness at compile time, rasn is aimed at teams working with ASN.1-based protocols in telecom, PKI, and cryptography who want a memory-safe alternative to the format’s traditional C implementations.

What You Get

  • A shared AsnType/Encode/Decode trait model that decouples your Rust types from any single ASN.1 encoding rule
  • Codec modules for BER, CER, DER, APER, UPER, OER, COER, JER, and XER, all implemented in safe Rust
  • Derive macros that generate Encode/Decode implementations and enforce distinct ASN.1 tags at compile time
  • Rich built-in ASN.1 types (INTEGER, OCTET STRING, SEQUENCE, CHOICE, and more) backed by bitvec, bytes, and chrono
  • A family of rasn-* standards crates (CMS, Kerberos, LDAP, OCSP, PKIX, SNMP, SMIME, IEEE 1609.2, ETSI TS 103 097) with ready-made typed models
  • #[no_std] support with only alloc required, so it runs on embedded and other constrained targets

Common Use Cases

  • Implementing PKI and X.509 certificate handling (via rasn-pkix, rasn-cms, rasn-ocsp) in Rust services
  • Parsing and generating LDAP, SNMP, or Kerberos protocol messages that are specified in ASN.1
  • Building connected-vehicle (C-ITS) stacks that use IEEE 1609.2 or ETSI TS 103 097 security envelopes
  • Encoding compact telecom or IoT payloads with PER/OER on embedded, #[no_std] targets
  • Cross-checking or migrating legacy ASN.1-based systems to a memory-safe Rust implementation

Under The Hood

Architecture rasn separates the ASN.1 data model from its encodings: src/types defines the abstract types (AsnType, tags, constraints, SEQUENCE/CHOICE field metadata via Fields), the de/enc modules define the generic Decode/Encoder/Decoder traits, and each of ber.rs, der.rs, cer.rs, per.rs, oer.rs, jer.rs, xer.rs, aper.rs, and uper.rs implements a concrete codec against those traits — der.rs, for example, is a thin wrapper that re-exports ber and configures DecoderOptions::der(). A Codec enum in codec.rs lets callers pick an encoding at runtime and dispatch to the right module. Because a type only ever implements AsnType/Encode/Decode once, adding a new codec (or a new standard’s data model in a standards/* crate) doesn’t require touching existing types. Rust’s borrow checker is used deliberately as a correctness net: encode_sequence/decode_sequence take closures over a scoped encoder/decoder so a field literally cannot be encoded through the wrong scope, a pattern the README documents as failing to compile rather than failing at runtime.

Tech Stack rasn is a #![no_std] (plus alloc) Rust crate built as a Cargo workspace (Cargo.toml workspace members include macros, macros/macros_impl, and standards/*). Core dependencies are bitvec and nom/nom-bitvec for bit-level parsing, num-bigint/num-traits/num-integer for arbitrary-precision INTEGER handling, chrono for ASN.1 time types, snafu for structured error types (with an optional backtraces feature), serde_json and xml-no-std for the JER/XER codecs, and rasn-derive (a separate proc-macro crate under macros/) for the derive macros. An optional compiler feature pulls in rasn-compiler to generate rasn bindings directly from ASN.1 module notation. Dev-dependencies include criterion and iai-callgrind for benchmarking and third-party crates like x509-cert/rustls-webpki for interop testing against other ASN.1/X.509 implementations.

Code Quality The crate has extensive automated tests: a tests/ directory with dozens of files, many named after specific GitHub issues (issue222.rs, issue508.rs, issue523.rs, etc.), indicating regression tests are added per bug report, plus round-trip tests inline in lib.rs that encode and decode every codec and assert equality via pretty_assertions. Error handling is explicit and typed throughout via snafu-derived DecodeError/EncodeError enums with codec-specific error kinds (BerDecodeErrorKind, DerDecodeErrorKind, etc.) rather than stringly-typed or swallowed errors. CI (.github/workflows/rust.yml) runs the test suite, just fmt, and just lint (clippy) across Windows and cross-compiled targets, and the crate carries #![warn(missing_docs)] at the crate root, enforcing rustdoc coverage on public items. The codec implementations are also fuzzed with AFL++, per the README, specifically to make the decoder robust against malformed/adversarial input.

What Makes It Unique Most Rust ASN.1 crates are tied to a single encoding rule or a single standard; rasn’s abstract-model design lets one type definition be shared across nine different encoding rules and across a whole family of standards crates (CMS, PKIX, SNMP, LDAP, Kerberos, connected-vehicle standards) maintained under the same librasn organization. Its derive macros push tag-uniqueness checking — a common source of invalid ASN.1 models — to compile time via static_assertions-style const checks, and the encoder API uses Rust’s ownership system so that a sequence’s contents structurally cannot be encoded into the wrong scope. Combined with #[no_std] support and an all-safe-Rust, fuzzed codec implementation, it targets a niche — embedded and security-critical ASN.1 handling — that’s traditionally dominated by unsafe C libraries.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search