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 enum
s 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.
§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
- Ergonomics
Re-exports§
pub use crate::parser::ParseLocation;
Macros§
Structs§
- Type for use with
Parser.read_element
andWriter.write_element
for handling ASN.1BMPString
. ABMPString
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. - A structure representing a (UTC timezone) date and time. Wrapped by
UtcTime
andGeneralizedTime
. - An ASN.1
ENUMERATED
value. Explicit
is a type which wraps another ASN.1 type, indicating that the tag is an ASN.1EXPLICIT
. This will generally be used withOption
orChoice
.- Used for parsing and writing ASN.1
GENERALIZED TIME
values. Wraps aDateTime
. - Type for use with
Parser.read_element
andWriter.write_element
for handling ASN.1IA5String
. AnIA5String
contains an&str
with only valid characers. Implicit
is a type which wraps another ASN.1 type, indicating that the tag is an ASN.1IMPLICIT
. This will generally be used withOption
orChoice
.- Represents an ASN.1
OBJECT IDENTIFIER
.ObjectIdentifier
s are opaque, the only thing may be done with them is test if they are equal to anotherObjectIdentifier
. The generally recommended practice for handling them is to create someObjectIdentifier
constants withasn1::oid!()
and then compare them withObjectIdentifier
s you get from parsing. - Represents values that are encoded as an
OCTET STRING
containing an encoded TLV, of typeT
. - 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) - 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) - Represents an ASN.1
BIT STRING
whose contents owned. When used to parse data this will allocate. ParseError
are returned when there is an error parsing the ASN.1 data.- Encapsulates an ongoing parse. For almost all use-cases the correct entry-point is
parse
orparse_single
. - Type for use with
Parser.read_element
andWriter.write_element
for handling ASN.1PrintableString
. APrintableString
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 callSequence.parse
on this value to decode the actual contents therein. - Represents an ASN.1
SEQUENCE OF
. This is anIterator
over values that are decoded. - Writes a
SEQUENCE OF
ASN.1 structure from a slice ofT
. - Writes an ASN.1
SEQUENCE
using a callback that writes the inner elements. - Represents an ASN.1
SET OF
. This is anIterator
over values that are decoded. - Writes an ASN.1
SET OF
whose contents is a slice ofT
. 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
andWriter.write_element
for handling ASN.1UniversalString
. AUniversalString
contains encoded (UTF-32-BE) bytes which are known to be valid. - Used for parsing and writing ASN.1
UTC TIME
values. Wraps aDateTime
. - Type for use with
Parser.read_element
andWriter.write_element
for handling ASN.1UTF8String
. - Type for use with
Parser.read_element
andWriter.write_element
for handling ASN.1VisibleString
. AnVisibleString
contains an&str
with only valid characers. - Encapsulates an ongoing write. For almost all use-cases the correct entrypoint is
write()
orwrite_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. WriteError
are returned when there is an error writing 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 aDEFAULT
. Generaly called immediately afterParser::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 whereT
is a type with#[derive(asn1::Asn1Read)]
. - Attempts to parse the
Tlv
at the start ofdata
(allows trailing data). If successful, theTlv
and the trailing data after it are returned, if unsuccessful aParseError
is returned. - Prepares an
OPTIONAL
ASN.1 value which has aDEFAULT
for writing. Generally called immediately beforeWriter::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 Aliases§
- The ASN.1 NULL type, for use with
Parser.read_element
andWriter.write_element
. - The result of a
parse
. Either a successful value or aParseError
.