Crate asn1

source · []
Expand description

This crate provides you with the ability to generate and parse ASN.1 encoded data. More precisely, it provides you with the ability to generate and parse data encoded with ASN.1’s DER (Distinguished Encoding Rules) encoding. It does not support BER (Basic Encoding Rules), CER (Canonical Encoding Rules), XER (XML Encoding Rules), CXER (Canonical XML Encoding Rules), or any other alphabet soup encodings – and it never will.

If you wanted to parse an ASN.1 structure like this:

Signature ::= SEQUENCE {
    r INTEGER,
    s INTEGER
}

Then you’d write the following code:

let result: asn1::ParseResult<_> = asn1::parse(data, |d| {
    return d.read_element::<asn1::Sequence>()?.parse(|d| {
        let r = d.read_element::<u64>()?;
        let s = d.read_element::<u64>()?;
        return Ok((r, s));
    })
});

In general everything about parsing is driven by providing different type parameters to Parser.read_element. Some types implement the Asn1Readable trait directly on a basic type, as seen with u64 or &[u8] (OCTET STRING), while others use wrapper types which simply provide ASN.1 encoding and decoding for some other type (PrintableString or UtcTime). There are also types such as Implicit and Explicit for handling tagged values, Choice1, Choice2, and Choice3 available for choices, and Option<T> for handling OPTIONAL values.

To serialize DER for the Sequence structure, you’d write the following:

let result = asn1::write(|w| {
    w.write_element(&asn1::SequenceWriter::new(&|w| {
        w.write_element(&r);
        w.write_element(&s);
    }));
});

Derive

When built with the derive feature (enabled by default), these can also be expressed as Rust structs:

#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct Signature {
    r: u64,
    s: u64,
}

let sig = asn1::parse_single::<Signature>(data);
let result = asn1::write_single(&Signature{r, s});

On Rust >= 1.51.0, Explicit and Implicit tagging may be specified with struct members of those types. However on Rust < 1.51.0, this is not possible, since they require const generics. Instead, the #[implicit] and #[explicit] attributes may be used:

#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct SomeSequence<'a> {
    #[implicit(0)]
    a: Option<&'a [u8]>,
    #[explicit(1)]
    b: Option<u64>,
}

Fields can also be annotated with #[default(VALUE)] to indicate ASN.1 OPTIONAL DEFAULT values. In this case, the field’s type should be T, and not Option<T>.

These derives may also be used with enums to generate CHOICE implementations.

#[derive(asn1::Asn1Read, asn1::Asn1Write)]
enum Time {
    UTCTime(asn1::UtcTime),
    GeneralizedTime(asn1::GeneralizedTime)
}

All variants must have a single un-named field.

Macros

Structs

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 BMPString. A BMPString contains encoded (UTF-16-BE) bytes which are known to be valid.

Arbitrary sized signed integer. Contents may be accessed as &[u8] of big-endian data. Its contents always match the DER encoding of a value (i.e. they are minimal)

Arbitrary sized unsigned integer. Contents may be accessed as &[u8] of big-endian data. Its contents always match the DER encoding of a value (i.e. they are minimal)

Represents an ASN.1 BIT STRING whose contents is borrowed.

An ASN.1 ENUMERATED value.

Explicit is a type which wraps another ASN.1 type, indicating that the tag is an ASN.1 EXPLICIT. This will generally be used with Option or Choice.

Used for parsing and writing ASN.1 GENERALIZED TIME values. Wraps a chrono::DateTime<Utc>.

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 IA5String. An IA5String contains an &str with only valid characers.

Implicit is a type which wraps another ASN.1 type, indicating that the tag is an ASN.1 IMPLICIT. This will generally be used with Option or Choice.

Represents an ASN.1 OBJECT IDENTIFIER. ObjectIdentifiers are opaque, the only thing may be done with them is test if they are equal to another ObjectIdentifier. The generally recommended practice for handling them is to create some ObjectIdentifier constants with asn1::oid!() and then compare ObjectIdentifiers you get from parsing to those.

Represents an ASN.1 BIT STRING whose contents owned.

Encapsulates an ongoing parse. For almost all use-cases the correct entry-point is parse or parse_single.

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 PrintableString. A PrintableString contains an &str with only valid characers.

Represents an ASN.1 SEQUENCE. By itself, this merely indicates a sequence of bytes that are claimed to form an ASN1 sequence. In almost any circumstance, you’ll want to immediately call Sequence.parse on this value to decode the actual contents therein.

Represents an ASN.1 SEQUENCE OF. This is an Iterator over values that are decoded.

Writes a SEQUENCE OF ASN.1 structure from a slice of T.

Writes an ASN.1 SEQUENCE using a callback that writes the inner elements.

Represents an ASN.1 SET OF. This is an Iterator over values that are decoded.

Writes an ASN.1 SET OF whose contents is a slice of T. This type handles ensuring that the values are properly ordered when written as DER.

A TLV (type, length, value) represented as the tag and bytes content. Generally used for parsing ASN.1 ANY values.

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 UniversalString. A UniversalString contains encoded (UTF-32-BE) bytes which are known to be valid.

Used for parsing and writing ASN.1 UTC TIME values. Wraps a chrono::DateTime<Utc>.

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 UTF8String.

Type for use with Parser.read_element and Writer.write_element for handling ASN.1 VisibleString. An VisibleString contains an &str with only valid characers.

Encapsulates an ongoing write. For almost all use-cases the correct entrypoint is write() or write_single().

Enums

Represents an ASN.1 CHOICE with the provided number of potential types.

Represents an ASN.1 CHOICE with the provided number of potential types.

Represents an ASN.1 CHOICE with the provided number of potential types.

ParseError are returned when there is an error parsing the ASN.1 data.

Traits

Any type that can be parsed as DER ASN.1.

Any type that can be written as DER ASN.1.

Types with a fixed-tag that can be parsed as DER ASN.1

Functions

Decodes an OPTIONAL ASN.1 value which has a DEFAULT. Generaly called immediately after Parser::read_element.

Parse takes a sequence of bytes of DER encoded ASN.1 data, constructs a parser, and invokes a callback to read elements from the ASN.1 parser.

Parses a single top-level ASN.1 element from data (does not allow trailing data). Most often this will be used where T is a type with #[derive(asn1::Asn1Read)].

Prepares an OPTIONAL ASN.1 value which has a DEFAULT for writing. Generally called immediately before Writer::write_element.

Constructs a writer and invokes a callback which writes ASN.1 elements into the writer, then returns the generated DER bytes.

Writes a single top-level ASN.1 element, returning the generated DER bytes. Most often this will be used where T is a type with #[derive(asn1::Asn1Write)].

Type Definitions

The ASN.1 NULL type, for use with Parser.read_element and Writer.write_element.

The result of a parse. Either a successful value or a ParseError.

Derive Macros