| //! [](./LICENSE-MIT) |
| //! [](./LICENSE-APACHE) |
| //! [](https://docs.rs/asn1-rs) |
| //! [](https://crates.io/crates/asn1-rs) |
| //! [](https://crates.io/crates/asn1-rs) |
| //! [](https://github.com/rusticata/asn1-rs/actions) |
| //! [](#rust-version-requirements) |
| //! |
| //! # BER/DER Parsers/Encoders |
| //! |
| //! A set of parsers/encoders for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER |
| //! [[X.690]]) formats, implemented with the [nom] parser combinator framework. |
| //! |
| //! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken |
| //! to ensure security and safety of this crate, including design (recursion limit, defensive |
| //! programming), tests, and fuzzing. It also aims to be panic-free. |
| //! |
| //! This crate is a rewrite of [der-parser](https://crates.io/crates/der-parser) to propose a more data-oriented API, |
| //! and add generalized support for serialization. |
| //! |
| //! Many ideas were borrowed from the [crypto/utils/der](https://github.com/RustCrypto/utils/tree/master/der) crate (like |
| //! the `Any`/`TryFrom`/`FromDer` mechanism), adapted and merged into a generalized BER/DER crate. |
| //! Credits (and many thanks) go to Tony Arcieri for writing the original crate. |
| //! |
| //! # BER/DER parsers |
| //! |
| //! BER stands for Basic Encoding Rules, and is defined in [[X.690]]. It defines a set of rules to |
| //! encode and decode ASN.1 [[X.680]] objects in binary. |
| //! |
| //! [[X.690]] also defines Distinguished Encoding Rules (DER), which is BER with added rules to |
| //! ensure canonical and unequivocal binary representation of objects. |
| //! |
| //! The choice of which one to use is usually guided by the speficication of the data format based |
| //! on BER or DER: for example, X.509 uses DER as encoding representation. |
| //! |
| //! The main traits for parsing are the [`FromBer`] and [`FromDer`] traits. |
| //! These traits provide methods to parse binary input, and return either the remaining (unparsed) bytes |
| //! and the parsed object, or an error. |
| //! |
| //! The parsers follow the interface from [nom], and the [`ParseResult`] object is a specialized version |
| //! of `nom::IResult`. This means that most `nom` combinators (`map`, `many0`, etc.) can be used in |
| //! combination to objects and methods from this crate. Reading the nom documentation may |
| //! help understanding how to write and combine parsers and use the output. |
| //! |
| //! **Minimum Supported Rust Version**: 1.53.0 |
| //! |
| //! Note: if the `bits` feature is enabled, MSRV is 1.56.0 (due to `bitvec` 1.0) |
| //! |
| //! # Recipes |
| //! |
| //! See [doc::recipes] and [doc::derive] for more examples and recipes. |
| //! |
| //! ## Examples |
| //! |
| //! Parse 2 BER integers: |
| //! |
| //! ```rust |
| //! use asn1_rs::{Integer, FromBer}; |
| //! |
| //! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01, |
| //! 0x02, 0x03, 0x01, 0x00, 0x00, |
| //! ]; |
| //! |
| //! let (rem, obj1) = Integer::from_ber(&bytes).expect("parsing failed"); |
| //! let (rem, obj2) = Integer::from_ber(&bytes).expect("parsing failed"); |
| //! |
| //! assert_eq!(obj1, Integer::from_u32(65537)); |
| //! ``` |
| //! |
| //! In the above example, the generic [`Integer`] type is used. This type can contain integers of any |
| //! size, but do not provide a simple API to manipulate the numbers. |
| //! |
| //! In most cases, the integer either has a limit, or is expected to fit into a primitive type. |
| //! To get a simple value, just use the `from_ber`/`from_der` methods on the primitive types: |
| //! |
| //! ```rust |
| //! use asn1_rs::FromBer; |
| //! |
| //! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01, |
| //! 0x02, 0x03, 0x01, 0x00, 0x00, |
| //! ]; |
| //! |
| //! let (rem, obj1) = u32::from_ber(&bytes).expect("parsing failed"); |
| //! let (rem, obj2) = u32::from_ber(&rem).expect("parsing failed"); |
| //! |
| //! assert_eq!(obj1, 65537); |
| //! assert_eq!(obj2, 65536); |
| //! ``` |
| //! |
| //! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return |
| //! an `IntegerTooLarge` error. |
| //! |
| //! # BER/DER encoders |
| //! |
| //! BER/DER encoding is symmetrical to decoding, using the traits `ToBer` and [`ToDer`] traits. |
| //! These traits provide methods to write encoded content to objects with the `io::Write` trait, |
| //! or return an allocated `Vec<u8>` with the encoded data. |
| //! If the serialization fails, an error is returned. |
| //! |
| //! ## Examples |
| //! |
| //! Writing 2 BER integers: |
| //! |
| //! ```rust |
| //! use asn1_rs::{Integer, ToDer}; |
| //! |
| //! let mut writer = Vec::new(); |
| //! |
| //! let obj1 = Integer::from_u32(65537); |
| //! let obj2 = Integer::from_u32(65536); |
| //! |
| //! let _ = obj1.write_der(&mut writer).expect("serialization failed"); |
| //! let _ = obj2.write_der(&mut writer).expect("serialization failed"); |
| //! |
| //! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01, |
| //! 0x02, 0x03, 0x01, 0x00, 0x00, |
| //! ]; |
| //! assert_eq!(&writer, bytes); |
| //! ``` |
| //! |
| //! Similarly to `FromBer`/`FromDer`, serialization methods are also implemented for primitive types: |
| //! |
| //! ```rust |
| //! use asn1_rs::ToDer; |
| //! |
| //! let mut writer = Vec::new(); |
| //! |
| //! let _ = 65537.write_der(&mut writer).expect("serialization failed"); |
| //! let _ = 65536.write_der(&mut writer).expect("serialization failed"); |
| //! |
| //! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01, |
| //! 0x02, 0x03, 0x01, 0x00, 0x00, |
| //! ]; |
| //! assert_eq!(&writer, bytes); |
| //! ``` |
| //! |
| //! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return |
| //! an `IntegerTooLarge` error. |
| //! |
| //! ## Changes |
| //! |
| //! See `CHANGELOG.md`. |
| //! |
| //! # References |
| //! |
| //! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation. |
| //! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical |
| //! Encoding Rules (CER) and Distinguished Encoding Rules (DER). |
| //! |
| //! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1): |
| //! Specification of basic notation." |
| //! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of |
| //! Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules |
| //! (DER)." |
| //! [nom]: https://github.com/Geal/nom "Nom parser combinator framework" |
| #![deny(/*missing_docs,*/ |
| unstable_features, |
| unused_import_braces, |
| unused_qualifications, |
| // unreachable_pub |
| )] |
| #![forbid(unsafe_code)] |
| #![warn( |
| /* missing_docs, |
| rust_2018_idioms,*/ |
| missing_debug_implementations, |
| )] |
| // pragmas for doc |
| #![deny(rustdoc::broken_intra_doc_links)] |
| #![cfg_attr(docsrs, feature(doc_cfg))] |
| #![doc(test( |
| no_crate_inject, |
| attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables)) |
| ))] |
| #![cfg_attr(not(feature = "std"), no_std)] |
| |
| #[cfg(feature = "std")] |
| extern crate core; |
| |
| // #[cfg(feature = "alloc")] |
| extern crate alloc; |
| |
| mod asn1_types; |
| mod ber; |
| mod class; |
| mod datetime; |
| mod derive; |
| mod error; |
| mod header; |
| mod length; |
| mod tag; |
| mod traits; |
| |
| pub use asn1_types::*; |
| pub use class::*; |
| pub use datetime::*; |
| pub use derive::*; |
| pub use error::*; |
| pub use header::*; |
| pub use length::*; |
| pub use tag::*; |
| pub use traits::*; |
| |
| pub use nom; |
| pub use nom::{Err, IResult, Needed}; |
| |
| #[doc(hidden)] |
| pub mod exports { |
| pub use alloc::borrow; |
| pub use asn1_rs_impl; |
| } |
| |
| #[cfg(doc)] |
| pub mod doc; |