Crate asn1

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)?;
        Ok(())
    }))
});

§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});

Fields may be marked as EXPLICIT or IMPLICIT either by struct members having the types Explicit and Implicit or via the use of #[explicit] and #[implicit] annotations:

#[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),
    X509GeneralizedTime(asn1::X509GeneralizedTime)
}

All variants must have a single un-named field.

§DEFINED BY

rust-asn1 also provides utilities for more easily handling the case of ANY DEFINED BY in an ASN.1 structure. For example, given the following ASN.1;

MySequence ::= SEQUENCE {
    contentType OBJECT IDENTIFIER,
    content ANY DEFINED BY contentType
}

This can be represented by:

#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct MySequence {
    content_type: asn1::DefinedByMarker<asn1::ObjectIdentifier>,
    #[defined_by(content_type)]
    content: Content,
}

#[derive(asn1::Asn1DefinedByRead, asn1::Asn1DefinedByWrite)]
enum Content {
    #[defined_by(SOME_OID_CONSTANT)]
    SomeVariant(i32),
}

§Design philosophy

As we have designed the asn1 crate, we value the following things, in this order:

  • Security
  • Correctness
  • Performance
  • Generality
  • Ergonomics

Macros§

oid

Structs§

BMPString
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.
BigInt
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)
BigUint
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)
BitString
Represents an ASN.1 BIT STRING whose contents is borrowed.
DateTime
A structure representing a (UTC timezone) date and time. Wrapped by UtcTime and X509GeneralizedTime and used in GeneralizedTime.
DefinedByMarker
Enumerated
An ASN.1 ENUMERATED value.
Explicit
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.
GeneralizedTime
Used for parsing and writing ASN.1 GENERALIZED TIME values, including values with fractional seconds of up to nanosecond precision.
IA5String
Type for use with Parser.read_element and Writer.write_element for handling ASN.1 IA5String. An IA5String contains an &str with only valid characters.
Implicit
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.
ObjectIdentifier
Represents an ASN.1 OBJECT IDENTIFIER.
OctetStringEncoded
Represents values that are encoded as an OCTET STRING containing an encoded TLV, of type T.
OwnedBigInt
Arbitrary sized signed integer which owns its contents. 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)
OwnedBigUint
Arbitrary sized unsigned integer which owns its data. 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)
OwnedBitString
Represents an ASN.1 BIT STRING whose contents owned. When used to parse data this will allocate.
ParseError
ParseError are returned when there is an error parsing the ASN.1 data.
Parser
Encapsulates an ongoing parse. For almost all use-cases the correct entry-point is parse or parse_single.
PrintableString
Type for use with Parser.read_element and Writer.write_element for handling ASN.1 PrintableString. A PrintableString contains an &str with only valid characters.
Sequence
Represents an ASN.1 SEQUENCE.
SequenceOf
Represents an ASN.1 SEQUENCE OF. This is an Iterator over values that are decoded.
SequenceOfWriter
Writes a SEQUENCE OF ASN.1 structure from a slice of T.
SequenceWriter
Writes an ASN.1 SEQUENCE using a callback that writes the inner elements.
SetOf
Represents an ASN.1 SET OF. This is an Iterator over values that are decoded.
SetOfWriter
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.
Tag
Tlv
A TLV (type, length, value) represented as the tag and bytes content. Generally used for parsing ASN.1 ANY values.
UniversalString
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.
UtcTime
Used for parsing and writing ASN.1 UTC TIME values. Wraps a DateTime.
Utf8String
Type for use with Parser.read_element and Writer.write_element for handling ASN.1 UTF8String.
VisibleString
Type for use with Parser.read_element and Writer.write_element for handling ASN.1 VisibleString. A VisibleString contains an &str with only valid characters.
WriteBuf
Writer
Encapsulates an ongoing write. For almost all use-cases the correct entrypoint is write() or write_single().
X509GeneralizedTime
Used for parsing and writing ASN.1 GENERALIZED TIME values used in X.509. Wraps a DateTime.

Enums§

Choice1
Represents an ASN.1 CHOICE with the provided number of potential types.
Choice2
Represents an ASN.1 CHOICE with the provided number of potential types.
Choice3
Represents an ASN.1 CHOICE with the provided number of potential types.
ParseErrorKind
WriteError
WriteError are returned when there is an error writing the ASN.1 data.

Traits§

Asn1DefinedByReadable
A trait for types that can be parsed based on a DEFINED BY value.
Asn1DefinedByWritable
A trait for types that can be written based on a DEFINED BY value.
Asn1Readable
Any type that can be parsed as DER ASN.1.
Asn1Writable
Any type that can be written as DER ASN.1.
SimpleAsn1Readable
Types with a fixed-tag that can be parsed as DER ASN.1
SimpleAsn1Writable
Types with a fixed-tag that can be written as DER ASN.1.

Functions§

from_optional_default
Decodes an OPTIONAL ASN.1 value which has a DEFAULT. Generaly called immediately after Parser::read_element.
parse
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.
parse_single
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)].
strip_tlv
Attempts to parse the Tlv at the start of data (allows trailing data). If successful, the Tlv and the trailing data after it are returned, if unsuccessful a ParseError is returned.
to_optional_default
Prepares an OPTIONAL ASN.1 value which has a DEFAULT for writing. Generally called immediately before Writer::write_element.
write
Constructs a writer and invokes a callback which writes ASN.1 elements into the writer, then returns the generated DER bytes.
write_single
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 Aliases§

Null
The ASN.1 NULL type, for use with Parser.read_element and Writer.write_element.
ParseResult
The result of a parse. Either a successful value or a ParseError.
WriteResult

Derive Macros§

Asn1DefinedByRead
Asn1DefinedByWrite
Asn1Read
Asn1Write