Welcome to asn1_der
🎉
This crate provides a basic no_std
-compatible, no-panic and zero-copy
DER implementation. It is designed to be reliable and reasonable fast without getting too large or
sacrificing too much comfort. To achieve this, asn1_der
makes extensive use of the
no-panic
crate and offers slice-based object views to avoid
allocations and unnecessary copies.
use asn1_der::{
DerObject,
typed::{ DerEncodable, DerDecodable }
};
fn main() {
/// An ASN.1-DER encoded integer `7`
const INT7: &'static[u8] = b"\x02\x01\x07";
// Decode an arbitrary DER object
let object = DerObject::decode(INT7).expect("Failed to decode object");
// Encode an arbitrary DER object
let mut encoded_object = Vec::new();
object.encode(&mut encoded_object).expect("Failed to encode object");
// Decode a `u8`
let number = u8::decode(INT7).expect("Failed to decode number");
assert_eq!(number, 7);
// Encode a new `u8`
let mut encoded_number = Vec::new();
7u8.encode(&mut encoded_number).expect("Failed to encode number");
}
For the (de-)serialization of structs and similar via derive
, see
serde_asn1_der
.
There are also some direct DerDecodable
/DerDecodable
implementations for native Rust type
equivalents:
- The ASN.1-
BOOLEAN
type as Rust-bool
- The ASN.1-
INTEGER
type as Rust-[u8
,u16
,u32
,u64
,u128
,usize
] - The ASN.1-
NULL
type as either()
orOption::None
(which allows the encoding of optionals) - The ASN.1-
OctetString
type asVec<u8>
- The ASN.1-
SEQUENCE
type asSequenceVec(Vec<T>)
- The ASN.1-
UTF8String
type asString
asn1_der
is designed to be as panic-free as possible. To ensure that, nearly every function is
attributed with #[no_panic]
, which forces the compiler to prove that a function cannot panic in
the given circumstances. However since no_panic
can cause a lot of false-positives, it is
currently only used by the CI-tests and disabled by default in normal builds. If you want to use
this crate with no_panic
enabled, you can do so by specifying the no_panic
feature.
It is important to know that no_panic
is no silver bullet and does not help against certain kinds
of errors that can also happen in this crate. This especially includes:
-
Dynamic memory allocation errors: Since it is not possible to predict memory allocation errors, everything that requires dynamic memory allocation is mutually exclusive to
no_panic
and will be omitted ifno_panic
is enabled.This crate might allocate memory in the following circumstances:
- When writing to a dynamically allocating sink (e.g.
Vec<u8>
,VecBacking(Vec<u8>)
) - When decoding a native owned type such as
Vec<u8>
,SequenceVec(Vec<T>)
orString
- During error propagation
If the crate is compiled without
std
enabled, it does performy any dynamic memory allocation directly by itself – however for foreign implementations passed to this crate may still allocate memory and fail (e.g. a customSink
implementation). - When writing to a dynamically allocating sink (e.g.
-
Stack overflows: Since the stack size is not necessarily known during compile time, it is not possible to predict stack overflow errors e.g. caused by recursion.
-
Calls to
abort
or similar: Since calls toabort
or similar do not trigger stack unwinding, they can also no be detected byno_panic
. This also means thatno_panic
does not work for builds that usepanic = "abort"
in their config.This crate by itself does never call
abort
directly.
Due to the limitations described above, the following functions are mutually exclusive to
no_panic
and disabled if no_panic
is set:
- Error stacking/propagation (
propagate
is a no-op if compiled withno_panic
) - The sink implementation for a byte vector (
impl Sink for Vec<u8>
) - The
VecBacking(Vec<u8>)
type - The native OctetString type which uses
Vec<u8>
(impl<'a> DerDecodable<'a> for Vec<u8>
andimpl DerEncodable for Vec<u8>
) - The native Sequence type wrapper
SequenceVec
since it is based uponVec
- The native Utf8String type based upon
String
(impl<'a> DerDecodable<'a> for String
andimpl DerEncodable for String
)
The crate is designed to be as much zero-copy as possible. In fact this means that the DerObject
type and all typed views are zero-copy views over the underlying slice. Of course, zero-copy is not
always reasonable: The new
-constructors are not zero-copy because they construct a new object into
a sink and the native type implementations are not zero-copy because they are either Copy
-types
(e.g. u128
) or owned (e.g. String
).
Since version 0.7.0, the asn1_der_derive
-crates has been deprecated in favor of
serde_asn1_der
. If you have a specific use-case why you
cannot use serde
, let me know; it's probably not that hard to revive asn1_der_derive
😊