Git Product home page Git Product logo

der-parser's Introduction

License: MIT Apache License 2.0 docs.rs crates.io Download numbers dependency status Github CI Minimum rustc version

BER/DER Parser

A parser for Basic Encoding Rules (BER [X.690]) and Distinguished Encoding Rules(DER [X.690]), 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.

Historically, this parser was intended for DER only, and BER support was added later. This may still reflect on some naming schemes, but has no other consequence: the BerObject and DerObject used in this crate are type aliases, so all functions are compatible.

DER parsing functions have additional constraints verification, however.

Serialization has also been added (see Serialization )

The code is available on Github and is part of the Rusticata project.

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 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.

See the related modules for object definitions, functions, and example:

  • [ber]: Basic Encoding Rules
  • [der]: Distinguished Encoding Rules

Examples

Parse two BER integers (see BER/DER Integers):

use der_parser::ber::parse_ber_integer;

let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
let (rem, obj2) = parse_ber_integer(&rem).expect("parsing failed");

Parse a DER sequence of integers:

use der_parser::der::{parse_der_integer, parse_der_sequence_of};

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (rem, seq) = parse_der_sequence_of(parse_der_integer)(&bytes)
                    .expect("parsing failed");

Note: all parsing functions return the remaining (unparsed) bytes and the parsed object, or an error.

DER parser design

Parsing functions are inspired from nom, and follow the same interface. The most common return type is BerResult, that stores the remaining bytes and parsed BerObject, or an error. Reading the nom documentation may help understanding how to write parsers and use the output.

There are two different approaches for parsing DER objects: reading the objects recursively as long as the tags are known, or specifying a description of the expected objects (generally from the ASN.1 description).

The first parsing method can be done using the parse_ber and parse_der methods. It is useful when decoding an arbitrary DER object. However, it cannot fully parse all objects, especially those containing IMPLICIT, OPTIONAL, or DEFINED BY items.

use der_parser::parse_der;

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let parsed = parse_der(&bytes);

The second (and preferred) parsing method is to specify the expected objects recursively. The following functions can be used:

For example, to read a BER sequence containing two integers:

use der_parser::ber::*;
use der_parser::error::BerResult;

fn localparse_seq(i:&[u8]) -> BerResult {
    parse_ber_sequence_defined(|data| {
        let (rem, a) = parse_ber_integer(data)?;
        let (rem, b) = parse_ber_integer(rem)?;
        Ok((rem, vec![a, b]))
    })(i)
}

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");

assert_eq!(parsed[0].as_u64(), Ok(65537));
assert_eq!(parsed[1].as_u64(), Ok(65536));

All functions return a BerResult object: the parsed BerObject, an Incomplete value, or an error.

Note that this type is also a Result, so usual functions (map, unwrap etc.) are available.

Notes

BER/DER Integers

DER integers can be of any size, so it is not possible to store them as simple integers (they are stored as raw bytes).

Note that, by default, BER/DER integers are signed. Functions are provided to request reading unsigned values, but they will fail if the integer value is negative.

To get the integer value for all possible integer sign and size, use BerObject::as_bigint) (requires the bigint feature).

To get a simple value expected to be in a known range, use methods like BerObject::as_i32) and BerObject::as_i64 (or the unsigned versions BerObject::as_u32 and BerObject::as_u64 ), which will return the value, or an error if the integer is too large (or is negative).

use der_parser::ber::*;

let data = &[0x02, 0x03, 0x01, 0x00, 0x01];

let (_, object) = parse_ber_integer(data).expect("parsing failed");
assert_eq!(object.as_u64(), Ok(65537));

#[cfg(feature = "bigint")]
assert_eq!(object.as_bigint(), Ok(65537.into()))

Access to the raw value is possible using the as_slice method.

Parsers, combinators, macros

Some parsing tools (for ex for tagged objects) are available in different forms:

  • parsers: (regular) functions that takes input and create an object
  • combinators: functions that takes parsers (or combinators) as input, and return a function (usually, the parser). They are used (combined) as building blocks to create more complex parsers.
  • macros: these are generally previous (historic) versions of parsers, kept for compatibility. They can sometime reduce the amount of code to write, but are hard to debug. Parsers should be preferred when possible.

Misc Notes

  • The DER constraints are verified if using parse_der.
  • BerObject and DerObject are the same objects (type alias). The only difference is the verification of constraints during parsing.

Rust version requirements

The 9.0 series of der-parser requires Rustc version 1.63 or greater, based on asn1-rs and nom 7 dependencies.

Serialization

Support for encoding BER/DER objects is currently being tested and can be used by activating the serialize feature. Note that current status is experimental.

See the ber_encode_* functions in the ber module, and BerObject::to_vec

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).

Changes

See CHANGELOG.md, and UPGRADING.md for instructions for upgrading major versions.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

der-parser's People

Contributors

cccs-sadugas avatar chifflier avatar cpu avatar dependabot[bot] avatar ericmarkmartin avatar focusaurus avatar geal avatar ibeckermayer avatar jannschu avatar jeamland avatar kornelski avatar mehcode avatar nhynes avatar nickelc avatar p1-mmr avatar pc-anssi avatar scouten avatar sergiobenitez avatar yuguorui avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

der-parser's Issues

oid! macro assumes der_parser is in the current namespace

The oid! macro evaluates to a reference to der_parser::โ€ฆ. This doesn't work if I don't have the crate in my namespace, e.g. if I'm using the macro via use x509_parser::der_parser::oid;. If this was a macro_rules! macro I'd say it needs to be using $crate, I hope proc macros have an equivalent (heck, can they just use $crate directly too?).

Integers are handled incorrectly

You decode integers as hex strings, but they are not encoded this way. Also, the error seems to get swallowed up. I can provide more information later, but for now I've simply commented out the integer branch in der_read_element_content_as and get these as an unknown.

handle context-specific tag incorrect

I have a signed data encoded by DER, but get strange output while parse

pub fn parse_signed_data(input: &[u8]) {
    let (_, top_object) = parse_der(input).unwrap();

    let pretty_object = top_object.as_pretty(4, 4);
    println!("{:?}", pretty_object);
}

The input

        let raw_bytes = [
            0x30, 0x82, 0x05, 0x20, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0,
            0x82, 0x05, 0x11, 0x30, 0x82, 0x05, 0x0D, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09,
            0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A,
            0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x57, 0x30, 0x82, 0x03, 0x53,
            0x30, 0x82, 0x02, 0x3B, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x77, 0xA4, 0xD5, 0xE2, 0x30,
            0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x5A,
            0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31, 0x0B, 0x30,
            0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x53, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
            0x55, 0x04, 0x07, 0x13, 0x02, 0x53, 0x48, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
            0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04,
            0x0B, 0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55,
            0x04, 0x03, 0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x30,
            0x31, 0x31, 0x30, 0x38, 0x30, 0x36, 0x33, 0x39, 0x34, 0x33, 0x5A, 0x17, 0x0D, 0x33, 0x30, 0x31,
            0x31, 0x30, 0x36, 0x30, 0x36, 0x33, 0x39, 0x34, 0x33, 0x5A, 0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09,
            0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
            0x04, 0x08, 0x13, 0x02, 0x53, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
            0x02, 0x53, 0x48, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x06, 0x71, 0x71,
            0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x06, 0x71,
            0x71, 0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x06,
            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
            0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82,
            0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA7, 0xE0, 0x84, 0x4E, 0x72, 0x99, 0xE0, 0x0F, 0x4A,
            0x91, 0x06, 0x08, 0x03, 0xC7, 0x8C, 0x10, 0xB5, 0x54, 0x20, 0x03, 0x63, 0x06, 0xCB, 0x03, 0x1F,
            0xB3, 0xA5, 0xAE, 0x5A, 0x4D, 0x47, 0xA2, 0x38, 0x3E, 0x57, 0xBD, 0xFF, 0x3F, 0x0E, 0xC0, 0xCD,
            0x82, 0x17, 0x18, 0x72, 0x71, 0xE4, 0x4B, 0xDE, 0xEC, 0x3E, 0xAF, 0xFD, 0x8D, 0x36, 0xF0, 0xFF,
            0x49, 0xE5, 0x5F, 0x6A, 0xB2, 0xE7, 0xCA, 0xBA, 0xF1, 0x0F, 0x65, 0x85, 0x92, 0xA6, 0xA2, 0xF9,
            0x3B, 0xBC, 0xA3, 0xC1, 0x46, 0x42, 0xDF, 0x34, 0x30, 0x3A, 0x90, 0xA5, 0x0A, 0xD2, 0x41, 0xD1,
            0xD7, 0x0F, 0xC0, 0xC2, 0x08, 0x41, 0x71, 0x16, 0x88, 0x4E, 0x4F, 0x5C, 0x48, 0xE1, 0xDE, 0x08,
            0xB2, 0x1F, 0x10, 0x3B, 0xB2, 0x25, 0x35, 0xDB, 0xCF, 0xFD, 0x16, 0x4F, 0x5A, 0x9D, 0x2F, 0xF6,
            0xCE, 0xC9, 0xB9, 0x57, 0xFE, 0x24, 0xE5, 0x52, 0x42, 0x02, 0x42, 0x1A, 0xE5, 0x42, 0xC3, 0xC5,
            0x5D, 0x4D, 0x31, 0x52, 0x22, 0x7A, 0x44, 0x67, 0x99, 0xD9, 0x8A, 0x41, 0x4E, 0xAC, 0x11, 0x80,
            0x66, 0x23, 0x47, 0x6D, 0xC3, 0x65, 0x14, 0x6C, 0x9D, 0x6F, 0x96, 0xD4, 0xDC, 0xC4, 0x85, 0x16,
            0xCC, 0x34, 0x14, 0xE7, 0x38, 0xA3, 0x9D, 0x7D, 0xB2, 0x51, 0xE1, 0xE1, 0x3C, 0x90, 0xE7, 0x26,
            0x7F, 0x12, 0x7C, 0x3B, 0xCC, 0xD3, 0x6A, 0x3F, 0xDF, 0x00, 0xFC, 0x1C, 0x7B, 0x2B, 0x48, 0x44,
            0x84, 0xA4, 0x9D, 0xEB, 0xE9, 0x2F, 0x8E, 0x26, 0x6A, 0x38, 0x6F, 0xBB, 0xF1, 0x1C, 0x2B, 0x11,
            0x29, 0x9D, 0xF0, 0x57, 0x91, 0x10, 0x60, 0xDD, 0xD2, 0xDC, 0x64, 0xAE, 0xDD, 0x94, 0x53, 0x40,
            0xBF, 0xDB, 0x11, 0xEA, 0xB0, 0x15, 0xDA, 0xD2, 0x8B, 0xAA, 0x08, 0x70, 0x4A, 0x21, 0x1E, 0x54,
            0x2C, 0xF9, 0x9E, 0x52, 0xD0, 0x6B, 0x13, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x21, 0x30, 0x1F,
            0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC5, 0x15, 0x25, 0x97, 0xD0,
            0x4B, 0xF9, 0x05, 0x87, 0x37, 0x95, 0x2F, 0xF1, 0x68, 0x1A, 0x22, 0xB3, 0xA7, 0x7F, 0xFC, 0x30,
            0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82,
            0x01, 0x01, 0x00, 0x54, 0x9A, 0x99, 0x39, 0x86, 0x3B, 0xC0, 0x91, 0xBB, 0x53, 0xA5, 0xB2, 0x2D,
            0x9B, 0xD3, 0x7E, 0xD1, 0x51, 0xB4, 0x5E, 0xC0, 0x36, 0x11, 0x2D, 0x52, 0x5C, 0x25, 0xDD, 0x91,
            0xD2, 0x5B, 0x42, 0xFA, 0xF6, 0x0E, 0x50, 0x30, 0x68, 0x2E, 0x86, 0xD9, 0x46, 0x19, 0x99, 0x42,
            0xD1, 0x87, 0x6F, 0xFF, 0x7E, 0xD2, 0x54, 0x93, 0x0D, 0x82, 0x6E, 0x85, 0xC2, 0x7D, 0x76, 0xA5,
            0x58, 0x57, 0x6C, 0x06, 0xE5, 0x8E, 0x05, 0xF7, 0x8B, 0x58, 0xD9, 0xBC, 0x64, 0xB0, 0x5E, 0x31,
            0x88, 0xFD, 0xB1, 0xDB, 0x63, 0x4B, 0xA1, 0x22, 0xD2, 0xA9, 0x71, 0x97, 0x34, 0x3D, 0x31, 0xE1,
            0xF7, 0xEE, 0xF4, 0xD4, 0x66, 0x6F, 0xB0, 0xD0, 0x9C, 0xDB, 0x82, 0x2A, 0x57, 0x08, 0xF7, 0x9F,
            0x33, 0x5B, 0xF3, 0x29, 0xF9, 0x21, 0xDB, 0xC6, 0x82, 0x4D, 0x09, 0x90, 0xBA, 0xA9, 0xD7, 0x7D,
            0x2B, 0xDD, 0xE8, 0xCA, 0x86, 0x21, 0xDF, 0xA5, 0xE3, 0xED, 0xED, 0x3B, 0x07, 0x2E, 0xDD, 0xBA,
            0x27, 0xB3, 0xAF, 0x4E, 0xBE, 0x09, 0x96, 0x14, 0x4A, 0xED, 0x5B, 0x5A, 0xB3, 0x6E, 0xD0, 0x1D,
            0x9E, 0x45, 0xC0, 0x70, 0xDF, 0x75, 0x7B, 0x77, 0xA1, 0x57, 0xC5, 0x76, 0x60, 0x58, 0x5C, 0xF2,
            0x2F, 0xAD, 0xF1, 0xAA, 0x15, 0xA6, 0x7D, 0x5A, 0x94, 0x95, 0xB7, 0x10, 0x81, 0xC5, 0xE4, 0x49,
            0xF1, 0x87, 0xB3, 0xA5, 0x97, 0xF8, 0xBE, 0xC4, 0xE0, 0xFD, 0x12, 0xCB, 0x14, 0x86, 0x98, 0xA0,
            0x73, 0xFE, 0xEF, 0x9B, 0xE0, 0x14, 0x6A, 0x0E, 0x06, 0xDE, 0x77, 0xE1, 0x5A, 0xC4, 0xF4, 0x4E,
            0xEB, 0x8D, 0x37, 0xF1, 0x3A, 0xCF, 0x4D, 0x4D, 0x36, 0xFC, 0xC0, 0x92, 0xA4, 0xE9, 0xA6, 0x49,
            0x7B, 0xCC, 0x93, 0x66, 0x51, 0x2A, 0x24, 0xD3, 0x15, 0x75, 0x9B, 0x6C, 0x4F, 0x60, 0x44, 0xE9,
            0x15, 0x59, 0x68, 0x31, 0x82, 0x01, 0x8D, 0x30, 0x82, 0x01, 0x89, 0x02, 0x01, 0x01, 0x30, 0x62,
            0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31,
            0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x53, 0x48, 0x31, 0x0B, 0x30, 0x09,
            0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x02, 0x53, 0x48, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55,
            0x04, 0x0A, 0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03,
            0x55, 0x04, 0x0B, 0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x31, 0x0F, 0x30, 0x0D, 0x06,
            0x03, 0x55, 0x04, 0x03, 0x13, 0x06, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x02, 0x04, 0x77, 0xA4,
            0xD5, 0xE2, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
            0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
            0x04, 0x82, 0x01, 0x00, 0x4B, 0x60, 0xBF, 0xF7, 0xF0, 0x7F, 0x3E, 0x06, 0xBE, 0xCA, 0x8F, 0xAD,
            0x7E, 0xB6, 0x1B, 0xBE, 0xE9, 0x0D, 0x27, 0x02, 0x35, 0xF1, 0x31, 0xA6, 0xF7, 0xA6, 0x08, 0x6A,
            0x48, 0xE0, 0x77, 0xA9, 0xFA, 0x30, 0xB1, 0xDB, 0xA8, 0xD9, 0x70, 0x2A, 0xA2, 0x21, 0x96, 0x02,
            0x6F, 0x45, 0x94, 0xBD, 0x75, 0xA9, 0x1C, 0xF6, 0x04, 0x61, 0xB5, 0xCD, 0x39, 0xA5, 0xAB, 0xDD,
            0x58, 0xCD, 0x50, 0x01, 0x22, 0x55, 0x04, 0x1D, 0x5A, 0x6A, 0x7A, 0xD7, 0x30, 0xA0, 0xBD, 0x36,
            0x9E, 0x9D, 0xC9, 0x66, 0xBA, 0x13, 0x75, 0xB4, 0x46, 0x28, 0xA5, 0xF0, 0x1F, 0x09, 0x36, 0x9C,
            0x05, 0x01, 0x7A, 0x66, 0x94, 0x55, 0xD4, 0x12, 0x0D, 0xC0, 0x3F, 0x77, 0x31, 0xFD, 0x06, 0x41,
            0x48, 0x43, 0xC3, 0x17, 0x7B, 0x7F, 0x7D, 0x45, 0x39, 0x73, 0x00, 0x1E, 0xC2, 0x99, 0x3A, 0x25,
            0x59, 0xB2, 0x78, 0xDD, 0x3E, 0x86, 0x06, 0xF0, 0x6E, 0x84, 0x0C, 0xB6, 0x33, 0x69, 0x73, 0x9B,
            0x52, 0xBA, 0x0B, 0x5D, 0x2F, 0x0A, 0x01, 0x30, 0x42, 0x93, 0x2E, 0x16, 0x6B, 0x9A, 0xDB, 0x82,
            0xF2, 0x30, 0x90, 0x1D, 0xC6, 0x1B, 0xB2, 0x2E, 0x19, 0x97, 0x40, 0xEC, 0xE1, 0x3F, 0xF3, 0x56,
            0xD2, 0xD3, 0xAC, 0xA6, 0xF9, 0x07, 0x5E, 0xCF, 0xBE, 0x91, 0x1B, 0xEE, 0x75, 0x30, 0xEE, 0x2B,
            0x7C, 0x45, 0x52, 0x1A, 0x76, 0x2F, 0x67, 0xE7, 0xCC, 0x8B, 0xCD, 0x93, 0xAD, 0xE4, 0xED, 0xEE,
            0x28, 0x64, 0x2D, 0x08, 0x4F, 0xB2, 0xA5, 0xE8, 0x38, 0x85, 0xDE, 0x65, 0x40, 0x06, 0x68, 0x6D,
            0xF6, 0x13, 0xC5, 0xE1, 0x2F, 0xE8, 0xA1, 0x74, 0x20, 0x44, 0x56, 0xD2, 0x9C, 0xF4, 0x0B, 0x78,
            0xA2, 0x10, 0x9F, 0xAC, 0x81, 0x82, 0x26, 0xC6, 0x63, 0xBC, 0x02, 0x7D, 0x2F, 0x6C, 0xD4, 0x2F,
            0xBD, 0x08, 0xD0, 0xA7
        ];

The output

    Sequence[
        OID(OID(1.2.840.113549.1.7.2))
        Unknown(EndOfContent,[30, 82, 5, d, 2, 1, 1, 31, f, 30, d, 6, 9, 60, 86, 48, 1, 65, 3, 4, 2, 1, 5, 0, 30, b, 6, 9, 2a, 86, 48, 86, f7, d, 1, 7, 1, a0, 82, 3, 57, 30, 82, 3, 53, 30, 82, 2, 3b, a0, 3, 2, 1, 2, 2, 4, 77, a4, d5, e2, 30, d, 6, 9, 2a, 86, 48, 86, f7, d, 1, 1, b, 5, 0, 30, 5a, 31, b, 30, 9, 6, 3, 55, 4, 6, 13, 2, 43, 4e, 31, b, 30, 9, 6, 3, 55, 4, 8, 13, 2, 53, 48, 31, b, 30, 9, 6, 3, 55, 4, 7, 13, 2, 53, 48, 31, f, 30, d, 6, 3, 55, 4, a, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, b, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, 3, 13, 6, 71, 71, 71, 71, 71, 71, 30, 1e, 17, d, 32, 30, 31, 31, 30, 38, 30, 36, 33, 39, 34, 33, 5a, 17, d, 33, 30, 31, 31, 30, 36, 30, 36, 33, 39, 34, 33, 5a, 30, 5a, 31, b, 30, 9, 6, 3, 55, 4, 6, 13, 2, 43, 4e, 31, b, 30, 9, 6, 3, 55, 4, 8, 13, 2, 53, 48, 31, b, 30, 9, 6, 3, 55, 4, 7, 13, 2, 53, 48, 31, f, 30, d, 6, 3, 55, 4, a, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, b, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, 3, 13, 6, 71, 71, 71, 71, 71, 71, 30, 82, 1, 22, 30, d, 6, 9, 2a, 86, 48, 86, f7, d, 1, 1, 1, 5, 0, 3, 82, 1, f, 0, 30, 82, 1, a, 2, 82, 1, 1, 0, a7, e0, 84, 4e, 72, 99, e0, f, 4a, 91, 6, 8, 3, c7, 8c, 10, b5, 54, 20, 3, 63, 6, cb, 3, 1f, b3, a5, ae, 5a, 4d, 47, a2, 38, 3e, 57, bd, ff, 3f, e, c0, cd, 82, 17, 18, 72, 71, e4, 4b, de, ec, 3e, af, fd, 8d, 36, f0, ff, 49, e5, 5f, 6a, b2, e7, ca, ba, f1, f, 65, 85, 92, a6, a2, f9, 3b, bc, a3, c1, 46, 42, df, 34, 30, 3a, 90, a5, a, d2, 41, d1, d7, f, c0, c2, 8, 41, 71, 16, 88, 4e, 4f, 5c, 48, e1, de, 8, b2, 1f, 10, 3b, b2, 25, 35, db, cf, fd, 16, 4f, 5a, 9d, 2f, f6, ce, c9, b9, 57, fe, 24, e5, 52, 42, 2, 42, 1a, e5, 42, c3, c5, 5d, 4d, 31, 52, 22, 7a, 44, 67, 99, d9, 8a, 41, 4e, ac, 11, 80, 66, 23, 47, 6d, c3, 65, 14, 6c, 9d, 6f, 96, d4, dc, c4, 85, 16, cc, 34, 14, e7, 38, a3, 9d, 7d, b2, 51, e1, e1, 3c, 90, e7, 26, 7f, 12, 7c, 3b, cc, d3, 6a, 3f, df, 0, fc, 1c, 7b, 2b, 48, 44, 84, a4, 9d, eb, e9, 2f, 8e, 26, 6a, 38, 6f, bb, f1, 1c, 2b, 11, 29, 9d, f0, 57, 91, 10, 60, dd, d2, dc, 64, ae, dd, 94, 53, 40, bf, db, 11, ea, b0, 15, da, d2, 8b, aa, 8, 70, 4a, 21, 1e, 54, 2c, f9, 9e, 52, d0, 6b, 13, 2, 3, 1, 0, 1, a3, 21, 30, 1f, 30, 1d, 6, 3, 55, 1d, e, 4, 16, 4, 14, c5, 15, 25, 97, d0, 4b, f9, 5, 87, 37, 95, 2f, f1, 68, 1a, 22, b3, a7, 7f, fc, 30, d, 6, 9, 2a, 86, 48, 86, f7, d, 1, 1, b, 5, 0, 3, 82, 1, 1, 0, 54, 9a, 99, 39, 86, 3b, c0, 91, bb, 53, a5, b2, 2d, 9b, d3, 7e, d1, 51, b4, 5e, c0, 36, 11, 2d, 52, 5c, 25, dd, 91, d2, 5b, 42, fa, f6, e, 50, 30, 68, 2e, 86, d9, 46, 19, 99, 42, d1, 87, 6f, ff, 7e, d2, 54, 93, d, 82, 6e, 85, c2, 7d, 76, a5, 58, 57, 6c, 6, e5, 8e, 5, f7, 8b, 58, d9, bc, 64, b0, 5e, 31, 88, fd, b1, db, 63, 4b, a1, 22, d2, a9, 71, 97, 34, 3d, 31, e1, f7, ee, f4, d4, 66, 6f, b0, d0, 9c, db, 82, 2a, 57, 8, f7, 9f, 33, 5b, f3, 29, f9, 21, db, c6, 82, 4d, 9, 90, ba, a9, d7, 7d, 2b, dd, e8, ca, 86, 21, df, a5, e3, ed, ed, 3b, 7, 2e, dd, ba, 27, b3, af, 4e, be, 9, 96, 14, 4a, ed, 5b, 5a, b3, 6e, d0, 1d, 9e, 45, c0, 70, df, 75, 7b, 77, a1, 57, c5, 76, 60, 58, 5c, f2, 2f, ad, f1, aa, 15, a6, 7d, 5a, 94, 95, b7, 10, 81, c5, e4, 49, f1, 87, b3, a5, 97, f8, be, c4, e0, fd, 12, cb, 14, 86, 98, a0, 73, fe, ef, 9b, e0, 14, 6a, e, 6, de, 77, e1, 5a, c4, f4, 4e, eb, 8d, 37, f1, 3a, cf, 4d, 4d, 36, fc, c0, 92, a4, e9, a6, 49, 7b, cc, 93, 66, 51, 2a, 24, d3, 15, 75, 9b, 6c, 4f, 60, 44, e9, 15, 59, 68, 31, 82, 1, 8d, 30, 82, 1, 89, 2, 1, 1, 30, 62, 30, 5a, 31, b, 30, 9, 6, 3, 55, 4, 6, 13, 2, 43, 4e, 31, b, 30, 9, 6, 3, 55, 4, 8, 13, 2, 53, 48, 31, b, 30, 9, 6, 3, 55, 4, 7, 13, 2, 53, 48, 31, f, 30, d, 6, 3, 55, 4, a, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, b, 13, 6, 71, 71, 71, 71, 71, 71, 31, f, 30, d, 6, 3, 55, 4, 3, 13, 6, 71, 71, 71, 71, 71, 71, 2, 4, 77, a4, d5, e2, 30, d, 6, 9, 60, 86, 48, 1, 65, 3, 4, 2, 1, 5, 0, 30, d, 6, 9, 2a, 86, 48, 86, f7, d, 1, 1, 1, 5, 0, 4, 82, 1, 0, 4b, 60, bf, f7, f0, 7f, 3e, 6, be, ca, 8f, ad, 7e, b6, 1b, be, e9, d, 27, 2, 35, f1, 31, a6, f7, a6, 8, 6a, 48, e0, 77, a9, fa, 30, b1, db, a8, d9, 70, 2a, a2, 21, 96, 2, 6f, 45, 94, bd, 75, a9, 1c, f6, 4, 61, b5, cd, 39, a5, ab, dd, 58, cd, 50, 1, 22, 55, 4, 1d, 5a, 6a, 7a, d7, 30, a0, bd, 36, 9e, 9d, c9, 66, ba, 13, 75, b4, 46, 28, a5, f0, 1f, 9, 36, 9c, 5, 1, 7a, 66, 94, 55, d4, 12, d, c0, 3f, 77, 31, fd, 6, 41, 48, 43, c3, 17, 7b, 7f, 7d, 45, 39, 73, 0, 1e, c2, 99, 3a, 25, 59, b2, 78, dd, 3e, 86, 6, f0, 6e, 84, c, b6, 33, 69, 73, 9b, 52, ba, b, 5d, 2f, a, 1, 30, 42, 93, 2e, 16, 6b, 9a, db, 82, f2, 30, 90, 1d, c6, 1b, b2, 2e, 19, 97, 40, ec, e1, 3f, f3, 56, d2, d3, ac, a6, f9, 7, 5e, cf, be, 91, 1b, ee, 75, 30, ee, 2b, 7c, 45, 52, 1a, 76, 2f, 67, e7, cc, 8b, cd, 93, ad, e4, ed, ee, 28, 64, 2d, 8, 4f, b2, a5, e8, 38, 85, de, 65, 40, 6, 68, 6d, f6, 13, c5, e1, 2f, e8, a1, 74, 20, 44, 56, d2, 9c, f4, b, 78, a2, 10, 9f, ac, 81, 82, 26, c6, 63, bc, 2, 7d, 2f, 6c, d4, 2f, bd, 8, d0, a7])
    ]

As show above, I think 0xA0 is not a unknown tag and the tag number should not be parsed as EOC, this is a context-specific tag.

`BerObjectHeader.structured` should be a `bool`

Not a Contribution

This field is a u8 and yet it can only hold the values 0 and 1. This is confusing and leads to somewhat odd behavior such as serializing a header looks at the lsb, so hdr.structured = 2 is serialized as 0. It also means you can have a header that is neither primitive nor constructed (as both accessors do an equality test on the flag).

Instead this should be a bool. Anyone who wants to recover the 0u8/1u8 value can just cast it to u8 (hdr.structured as u8), so that actually simplifies the encoding, and it simplifies the decoding too because right now it's a conditional

let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 };

and with this change it would just be let b = i[0] & 0b0010_0000 != 0.

Code that prints this today such as .as_pretty() currently prints e.g. s:0 or s:1, so if you wanted to preserve that you'd need to add a cast to the printing, though it might actually be clearer to just let it print as s:false or s:true anyway.

Side note

I don't know why this is called structured, that word doesn't appear anywhere in X.690, I would have expected it to be called constructed instead.

Parsing empty sequences fail

Parsing an empty sequence (30 00) fails: Incomplete(Size(1))

Length 0 is wrongly interpreted as indefinite length.

Panic on overflow in subtraction

Found using cargo-fuzz.

extern crate der_parser;

fn main() {
    let data = b"\x03\x00\x00kk\x00\x00\x00\x00\x00\x00\x00.\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff;\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\xff\x0a\xff";
    let _ = der_parser::parse_der(data);
}
thread '<unnamed>' panicked at 'attempt to subtract with overflow', /home/neo/dev/work/der-parser/src/der.rs:496
stack backtrace:
   0:     0x55a334805553 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hf9ed9ccfd9f14c2b
                               at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x55a334801ea4 - std::sys_common::backtrace::_print::hd8a1b72dcf3955ef
                               at /checkout/src/libstd/sys_common/backtrace.rs:71
   2:     0x55a334806527 - std::panicking::default_hook::{{closure}}::h5ff605bba7612658
                               at /checkout/src/libstd/sys_common/backtrace.rs:60
                               at /checkout/src/libstd/panicking.rs:355
   3:     0x55a3348060ab - std::panicking::default_hook::h9bc4f6dfee57d6bd
                               at /checkout/src/libstd/panicking.rs:371
   4:     0x55a33480698b - std::panicking::rust_panic_with_hook::hdc01585dc2bf7122
                               at /checkout/src/libstd/panicking.rs:549
   5:     0x55a334806864 - std::panicking::begin_panic::hf84f4975d9f9b642
                               at /checkout/src/libstd/panicking.rs:511
   6:     0x55a334806799 - std::panicking::begin_panic_fmt::hcc3f360b2ba80419
                               at /checkout/src/libstd/panicking.rs:495
   7:     0x55a334806727 - rust_begin_unwind
                               at /checkout/src/libstd/panicking.rs:471
   8:     0x55a3348f8e3d - core::panicking::panic_fmt::h795d9a9608ddc2bb
                               at /checkout/src/libcore/panicking.rs:69
   9:     0x55a3348f8d74 - core::panicking::panic::hcab3e0dfa81beee9
                               at /checkout/src/libcore/panicking.rs:49
  10:     0x55a3347d963e - der_parser::der::der_read_element_content_as::hec8b190837fd2b88
                               at /home/neo/dev/work/der-parser/src/der.rs:494
  11:     0x55a3347db053 - der_parser::der::der_read_element_content::h4613f91403cc33be
                               at /home/neo/dev/work/der-parser/src/der.rs:612
  12:     0x55a3347f7a99 - der_parser::der::parse_der::h012b5d2e9c9f1cdb
                               at /home/neo/dev/work/der-parser/src/der.rs:834
  13:     0x55a334766b01 - rust_fuzzer_test_input
                               at /home/neo/dev/work/der-parser/fuzz/fuzzers/fuzzer_script_1.rs:7
  14:     0x55a33476a71a - libfuzzer_sys::test_input_wrap::{{closure}}::h01afe675cf6a0c88
                               at /home/neo/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/src/lib.rs:13
  15:     0x55a3347687df - std::panicking::try::do_call::hfeac5113da58e53b
                               at /checkout/src/libstd/panicking.rs:454
  16:     0x55a33480c67b - <unknown>
                               at /checkout/src/libpanic_abort/lib.rs:40
==5893== ERROR: libFuzzer: deadly signal
    #0 0x55a3348d80d9 in __sanitizer_print_stack_trace /checkout/src/compiler-rt/lib/asan/asan_stack.cc:38
    #1 0x55a33477bb11 in fuzzer::Fuzzer::CrashCallback() /home/neo/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerLoop.cpp:280
    #2 0x55a33477ba5b in fuzzer::Fuzzer::StaticCrashSignalCallback() /home/neo/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerLoop.cpp:264
    #3 0x55a33479924d in fuzzer::CrashHandler(int, siginfo_t*, void*) /home/neo/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/36a3928/llvm/lib/Fuzzer/FuzzerUtilPosix.cpp:37
    #4 0x7fa3147ecfdf  (/usr/lib/libpthread.so.0+0x11fdf)
    #5 0x7fa31424ea0f in __GI_raise (/usr/lib/libc.so.6+0x33a0f)
    #6 0x7fa314250139 in __GI_abort (/usr/lib/libc.so.6+0x35139)
    #7 0x55a33480c688 in panic_abort::__rust_start_panic::abort /checkout/src/libpanic_abort/lib.rs:61
    #8 0x55a33480c688 in __rust_start_panic /checkout/src/libpanic_abort/lib.rs:56

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 5 CrossOver-PersAutoDict-ChangeBinInt-InsertByte-PersAutoDict- DE: "\x01\x00\x00\x00"-"\x00\x00"-; base unit: 2bdab388248e0d022b7b852c59983788a3ee86e4
0x3,0x0,0x0,0x6b,0x6b,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2e,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0xff,0xa,0xff,
\x03\x00\x00kk\x00\x00\x00\x00\x00\x00\x00.\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff;\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\xff\x0a\xff
artifact_prefix='artifacts/'; Test unit written to artifacts/crash-99d752339e4c2516982a7eba4ddbe586ee4972dc
Base64: AwAAa2sAAAAAAAAALgD///////////////////////87////////////AQAAAP8K/w==

Enhancement: Re-export `rusticata-macros`

der-parser appears to use a crate internally called rusticata-macros, but it doesn't re-export it. It would be nice if this could be re-exported, to make it easier for clients of der-parser to write their own parsers.

The drawback here is it means der-parser can't update to incompatible versions of rusticata-macros without making it a breaking change for der-parser, but the last two major version updates to rusticata-macros appear to have been accompanied by major version updates to der-parser anyway.

asn1 length

Is there any way to get the asn1 length? It seems to be available in the DerElementHeader

Switch to complete nom parser from current streaming ones

Hi,

der-parser currently uses the streaming variant of the nom parsers. Version 5 now offers complete variants.

The streaming versions make using optionals opt! and many1! etc. a bit cumbersome. There are a few issues in the nom repo with examples for such problems.

At least for the application in x509-parser (and other cryptography realated parsers in general) the parsing of partial data is not necessary (?).

To ease usage (and increase performance?) I suggest to switch to the complete nom parsers.

issues building with nightly due to proc-macro2 version usage?

noticed when i'm using a crate that relies on der-parsers 8.2, and build as nightly i'm getting the following not sure if this is a problem that can be resolved at this level
ย 
error[E0635]: unknown feature proc_macro_span_shrink
--> C:\Users\chris.cargo\registry\src\index.crates.io-6f17d22bba15001f\proc-macro2-1.0.56\src\lib.rs:92:30
|
92 | feature(proc_macro_span, proc_macro_span_shrink)

BerObject::as_pretty() drops tag class when printing Unknown contents

BerObjectContent::Unknown carries the BerTag but not the BerClass. I don't know why this is, it seems like an oversight, but the class is stored in the BerObjectHeader. Unfortunately, the BerObject::as_pretty() method only prints the contents (barring the ShowHeader flag). What's more, it prints the enum name for any BerTags even if they don't belong to the Universal class. This means that my pretty-printed object is showing up containing a Sequence[Unknown(EndOfContent,[de, ad, be, ef])]. Printing the header tells me this is actually a context-specific tag, which means it should have been printed as something like Sequence[Unknown(ContextSpecific(0),[de, ad, be, ef])] instead.

Concatenate a relative OID onto a base OID

I would really like to be able to concatenate relative OIDs onto base OIDs at compile-time. I'm not sure if this is actually possible, but I want to be able to write something like

const OID_BASE: Oid = oid!(1.2.840.1234);
const OID_SUB_1: Oid = oid!(OID_BASE 10);
const OID_SUB_2: Oid = oid!(OID_SUB_1 15);

Or some alternative syntax that achieves the same thing. I don't know if there's any way to achieve this without heap allocation. I really wish Rust had built-in syntax for "please flatten this array into the enclosing array literal".

The goal here is of course to be able to represent a tree of OIDs using a similar structure to how they're declared in ASN.1, instead of having to repeat the OID base everywhere.

Decoding ASN.1 signed integers always produces unsigned result

BerObject doesn't seem to have any way of actually parsing a negative ASN.1 integer as a negative number. It only exposes .as_u32() and .as_u64(), both of which simply assume the whole thing is unsigned (even though ASN.1 integers are signed and BER/DER-encoding represents them as two's complement integers). Because of the variable length of an integer I can't even cast the result to a signed value, as e.g. -123 encodes as [0x85] which is then just 133 (and therefore casting to a signed integer preserves the 133 representation).

The only nod towards signed integers is the existence of .as_bigint() in addition to .as_biguint(). Unfortunately (and completely undocumented), the result is always a positive BigInt, as the implementation explicitly provides the positive sign instead of using the constructor that detects the sign from the bytes.

Example:

DerObject::from_int_slice(&BigInt::from(42).to_signed_bytes_be()).as_bigint().unwrap() // returns 42
DerObject::from_int_slice(&BigInt::from(-123).to_signed_bytes_be()).as_bigint().unwrap() // returns 133

Usage help: ecdsa parameters

I wonder if you can help me parse the last 2 fields in an ecdsa ssh private key. I have working code to handle the sequence, integer, and octet string, but the final 2 fields I can't figure out how to parse with der-parser. Here's the ASN.1 structure:

ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, publicKey [1] BIT STRING OPTIONAL
}

And here's my code, with the first 2 fields of the sequence working but last 2 wrong.

fn der_read_opt_oid(i:&[u8]) -> IResult<&[u8],DerObject,u32> {
    parse_der_optional!(i, parse_der_oid)
}

fn der_read_opt_bitstring(i:&[u8]) -> IResult<&[u8],DerObject,u32> {
    parse_der_optional!(i, parse_der_bitstring)
}

fn parse_oid(i: &[u8]) -> IResult<&[u8], DerObject> {
    parse_der_explicit(i, DerTag::Oid as u8, parse_der_oid)
}

fn parse_bits(i: &[u8]) -> IResult<&[u8], DerObject> {
    parse_der_explicit(i, DerTag::BitString as u8, parse_der_bitstring)
}

fn ecdsa_private(input: &[u8]) -> Algorithm {
    match parse_der_sequence_defined!(
        input,
        parse_der_integer,
        parse_der_octetstring,
        der_read_opt_oid,
        der_read_opt_bitstring,
    ) {
        IResult::Done(_unparsed_suffix, der) => {
            assert_eq!(_unparsed_suffix.len(), 0);
            Algorithm::Ecdsa(0)
        }
        IResult::Error(error) => {
            eprintln!("Error {}", error);
            Algorithm::Unknown
        }
        IResult::Incomplete(_needed) => {
            eprintln!("Incomplete {:?}", _needed);
            Algorithm::Unknown
        }
    }
}

How do I convert an `asn1_rs::Any` to a `BerObject`?

NOT A CONTRIBUTION

I'm looking to update my code that uses x509-parser (and transitively der-parser). I have code that takes an x509_parser::x509::AlgorithmIdentifier, reads the parameters field, and pretty-prints it. In x509-parser v0.12, the parameters are a DerObject so that works. In v0.15 it's an Any. The pretty-printing provided by der-parser exists on BerObject.

So, my question, how do I convert an asn1_rs::Any to a BerObject? I would have expected BerObject to implement TryFrom<Any> but it doesn't1. Is there any alternative way I'm missing?

Footnotes

  1. I see in the source a comment saying this is because of the lack of a max_depth argument, but I would have expected such an implementation to be recursive, and perhaps a method on BerObject for converting from Any with a maximum depth specified. โ†ฉ

Macros require importing other crates

Using any of the macros in this crate requires both of the following imports in one's own code to work:

// for the map!() macro
#[macro_use]
extern crate nom;

// for custom_check!()
#[macro_use]
extern crate rusticata_macros;

The former breaks code if you use dbg!() from the standard library because Nom defines the same macro name with incompatible semantics.

Der sequence not parsed correctly

Here is an example program and its output. From looking at the data I believe there should be many more entries in the iterator.

Program:

extern crate der_parser;

fn main() {
    let bytes = [0x30, 0x82, 0x4, 0xA4, 0x2, 0x1, 0x0, 0x2, 0x82, 0x1, 0x1, 0x0, 0xD8, 0xFE, 0xA3, 0x5E, 0x24, 0x58, 0xB9, 0xF4, 0x2, 0x49, 0x54, 0xBA, 0xAA, 0xCA, 0xA6, 0x13, 0x56, 0x4B, 0x40, 0x87, 0x1F, 0x70, 0x93, 0x19, 0x8E, 0x5E, 0x6A, 0x83, 0xE6, 0xBA, 0x54, 0x3F, 0x6C, 0xEF, 0x5C, 0xA1, 0xD2, 0x1C, 0x6E, 0xD2, 0x8C, 0x37, 0x17, 0x37, 0x3B, 0xC9, 0xE8, 0x77, 0x7E, 0xF9, 0xFE, 0xDA, 0xC5, 0x45, 0xBE, 0x53, 0x25, 0x67, 0xAA, 0x6E, 0xD1, 0x15, 0x44, 0xD5, 0x6, 0x9D, 0xE2, 0xAB, 0xE7, 0x46, 0xD1, 0x25, 0x75, 0x1B, 0x90, 0x61, 0xCA, 0xB8, 0x43, 0xE, 0x83, 0xFF, 0x74, 0xEA, 0xBD, 0xEC, 0x8D, 0x56, 0xC3, 0xBB, 0x35, 0xA0, 0x25, 0xE8, 0x4B, 0xBD, 0xCB, 0xD, 0xD7, 0x34, 0x67, 0x46, 0xED, 0xEA, 0x95, 0xCA, 0xBA, 0xC5, 0x52, 0x76, 0x17, 0x27, 0x43, 0xA2, 0xA5, 0x8E, 0x8B, 0x9F, 0x2C, 0x2, 0xB3, 0x7E, 0x46, 0xEC, 0x40, 0x14, 0xAE, 0x65, 0xBE, 0xF9, 0xD1, 0xF4, 0x2, 0xB9, 0xDD, 0xB4, 0x4A, 0x9B, 0xF2, 0xE3, 0xEB, 0xF, 0xB3, 0xF6, 0x13, 0xB7, 0xF8, 0xB5, 0x4E, 0x93, 0x65, 0xA4, 0x29, 0xBD, 0x99, 0xCF, 0xCB, 0xF3, 0xD5, 0x59, 0x47, 0xBC, 0x93, 0x85, 0x5E, 0xC8, 0x4B, 0xD0, 0x1, 0x22, 0xD, 0xE9, 0x14, 0x88, 0x8F, 0xB8, 0x4, 0x32, 0x55, 0xEC, 0xC9, 0xEE, 0x23, 0x80, 0x5C, 0x90, 0x99, 0x97, 0x2F, 0x17, 0xB7, 0x24, 0xA3, 0x7F, 0xDB, 0x85, 0x64, 0x86, 0xE9, 0x80, 0xF8, 0xFC, 0xB9, 0x85, 0xC8, 0x4C, 0x75, 0x82, 0x34, 0x24, 0xEA, 0xA1, 0x7, 0x45, 0x79, 0xBC, 0x8F, 0x95, 0xB5, 0xA, 0xF4, 0x94, 0x1B, 0x9E, 0x38, 0x18, 0x19, 0xDE, 0x2F, 0x3A, 0x16, 0x22, 0x8F, 0x3B, 0xBA, 0xE4, 0x0, 0x31, 0x79, 0x3F, 0x65, 0x7B, 0x60, 0x32, 0x71, 0xCE, 0x7A, 0xD2, 0xCE, 0xE2, 0x50, 0xBC, 0x43, 0x5F, 0x55, 0x7B, 0x2, 0x3, 0x1, 0x0, 0x1, 0x2, 0x82, 0x1, 0x0, 0x70, 0xF, 0xC8, 0xE4, 0x94, 0x56, 0xB1, 0xE9, 0x9E, 0xC8, 0xAA, 0x16, 0x20, 0x9F, 0xB8, 0xF6, 0xA1, 0x89, 0x9, 0x50, 0xFE, 0xDE, 0x8F, 0x49, 0x12, 0x6A, 0x16, 0xD, 0xFA, 0x38, 0xDD, 0xCB, 0x47, 0x81, 0xB1, 0xCF, 0xEC, 0x7, 0x3D, 0x0, 0x44, 0xE3, 0x2A, 0x7D, 0x1E, 0xC6, 0x5D, 0xE4, 0x60, 0x51, 0xD0, 0xD8, 0xC0, 0x2A, 0xD, 0x69, 0x39, 0x16, 0xF9, 0x40, 0x73, 0x7F, 0xCD, 0x65, 0x4A, 0x1E, 0x7D, 0x72, 0x13, 0x65, 0x52, 0x1B, 0x4B, 0x8, 0x2A, 0x1F, 0x26, 0xA6, 0xD4, 0x12, 0x89, 0xFE, 0x82, 0x2D, 0xBC, 0x59, 0x8E, 0x80, 0x71, 0x62, 0x9C, 0x6, 0x11, 0xAD, 0x8E, 0x77, 0xFC, 0x86, 0x30, 0x4E, 0x62, 0xCB, 0x91, 0x90, 0xA5, 0x3C, 0xE6, 0x9, 0x83, 0x55, 0x73, 0xD, 0x96, 0xF3, 0x47, 0x16, 0x7F, 0x6A, 0x7B, 0x3B, 0x5, 0xE1, 0x3F, 0xD5, 0x40, 0x1E, 0xAE, 0x14, 0xEF, 0xCE, 0x5A, 0x84, 0xAE, 0xB1, 0xE0, 0x7F, 0xA1, 0x8C, 0xC0, 0x49, 0x46, 0x84, 0x72, 0xE9, 0x97, 0xAA, 0xCF, 0xEC, 0x3F, 0xC4, 0x2C, 0xAA, 0xE7, 0xA7, 0xEF, 0xC4, 0xCD, 0xEA, 0x22, 0x4F, 0x9, 0xAA, 0x10, 0xF3, 0xB5, 0x4F, 0x8B, 0x9F, 0x4C, 0x7F, 0x6E, 0xE8, 0x37, 0x5E, 0xBC, 0xBF, 0x9, 0xC4, 0xAC, 0x75, 0x92, 0xF6, 0xC3, 0x19, 0x59, 0xC1, 0xF6, 0x83, 0xF0, 0xDA, 0x41, 0xD0, 0x64, 0x1B, 0x68, 0x30, 0x5F, 0x39, 0x75, 0x53, 0x19, 0xD8, 0xA5, 0xF2, 0xB1, 0x8B, 0x9C, 0xDE, 0xE1, 0x9, 0x43, 0xBD, 0x0, 0x9A, 0xA9, 0xB0, 0x25, 0x32, 0x11, 0x54, 0x64, 0x7, 0x8C, 0x41, 0x5B, 0x70, 0xA0, 0x65, 0x4F, 0x83, 0xA4, 0x17, 0xFA, 0xBD, 0x22, 0xAC, 0xB4, 0x5B, 0x11, 0x64, 0xC4, 0xA0, 0xDF, 0x61, 0x82, 0x1D, 0x55, 0x3B, 0x76, 0x1F, 0xFA, 0x4C, 0x8F, 0x31, 0xAB, 0x19, 0x2, 0x81, 0x81, 0x0, 0xE2, 0x18, 0xEB, 0xFB, 0x2A, 0x92, 0x9A, 0x14, 0x62, 0xE5, 0x31, 0x77, 0x2D, 0x6D, 0xFA, 0xFB, 0xBC, 0xF4, 0x78, 0x3C, 0x9A, 0xFB, 0xCD, 0xAB, 0x41, 0xC7, 0x6A, 0xAF, 0x2D, 0xF9, 0xF1, 0x24, 0x51, 0xBB, 0x5F, 0xD9, 0x94, 0x7, 0x5A, 0xFC, 0xDD, 0xFC, 0x42, 0xF8, 0xAB, 0xD0, 0x28, 0xF7, 0xF3, 0x92, 0x70, 0xDB, 0x5, 0xFC, 0x1D, 0x8B, 0xDE, 0xAE, 0xBC, 0xB4, 0x54, 0x96, 0xEC, 0x1B, 0x3E, 0x4E, 0x4, 0x20, 0x75, 0x75, 0x73, 0xFA, 0x1D, 0xF, 0x35, 0x24, 0x10, 0x91, 0xF2, 0x8A, 0xA0, 0xB5, 0x7F, 0x1A, 0x9C, 0x6B, 0xE5, 0x26, 0xC9, 0x90, 0x46, 0xD7, 0xB6, 0x81, 0x55, 0x5E, 0x14, 0xF7, 0xB5, 0x56, 0xC0, 0xC1, 0xC6, 0xB9, 0x94, 0x2A, 0x16, 0x57, 0x51, 0x2A, 0x4F, 0xC2, 0x31, 0x88, 0xAF, 0x73, 0xA5, 0xBE, 0xC2, 0x1B, 0x7A, 0xE8, 0x2, 0x3D, 0xC7, 0xF1, 0x68, 0xDF, 0x2, 0x81, 0x81, 0x0, 0xF5, 0xB1, 0x85, 0xF0, 0xC9, 0x85, 0x44, 0x4B, 0x41, 0xD9, 0x94, 0xBA, 0xC1, 0x98, 0xE8, 0x4A, 0x2B, 0xE3, 0x72, 0x80, 0x21, 0xB2, 0x52, 0x37, 0xAB, 0x39, 0x8B, 0x7F, 0xE8, 0xD0, 0x53, 0x7E, 0x3F, 0x6B, 0x47, 0xE2, 0x2C, 0xA6, 0xB7, 0x9A, 0xE6, 0x19, 0xF9, 0x90, 0xCA, 0xB2, 0x1F, 0x59, 0x4A, 0x58, 0xCA, 0xDF, 0xAE, 0x81, 0xBC, 0x9D, 0x5B, 0x53, 0xFA, 0x2C, 0x9D, 0x24, 0xAE, 0xBA, 0x4A, 0xED, 0x43, 0xCF, 0x2A, 0x66, 0x92, 0x49, 0xBD, 0xD5, 0x3D, 0x13, 0x4, 0xEA, 0x70, 0xDA, 0xFC, 0x2F, 0xBF, 0xB5, 0x8D, 0x90, 0x2B, 0xAC, 0xDF, 0xE1, 0x6C, 0x1F, 0xCB, 0x1, 0x18, 0x6E, 0xD6, 0xC8, 0xC6, 0x16, 0xAF, 0x4E, 0xDA, 0xFF, 0x3F, 0xF, 0x55, 0x28, 0xFD, 0xC8, 0xF3, 0x70, 0x50, 0x5A, 0x68, 0xD, 0xAB, 0x6E, 0x95, 0xD5, 0x3F, 0x83, 0x9C, 0x5C, 0x3C, 0x96, 0x3A, 0xE5, 0x2, 0x81, 0x80, 0x6D, 0xB0, 0xAF, 0x93, 0xFC, 0x14, 0x81, 0xC2, 0x10, 0x34, 0xA7, 0x69, 0xED, 0x55, 0x65, 0x25, 0x8A, 0x87, 0x84, 0x69, 0xCA, 0xBB, 0xD, 0xD, 0xDF, 0xEC, 0xD2, 0x7A, 0x48, 0xB0, 0xF0, 0xE7, 0xB0, 0xEB, 0x59, 0xD6, 0x22, 0x35, 0xEB, 0x53, 0xB0, 0x92, 0xB9, 0x1F, 0x11, 0xA3, 0xFC, 0xAC, 0x46, 0xB4, 0x2E, 0x22, 0x64, 0x65, 0xEB, 0x23, 0xB7, 0x96, 0x48, 0xA0, 0xA8, 0x45, 0x4C, 0x28, 0xEF, 0x72, 0x44, 0x18, 0x47, 0x44, 0x3, 0x4F, 0x3D, 0x97, 0xEA, 0x2D, 0x24, 0x8, 0xDA, 0x85, 0x9C, 0xF0, 0x50, 0xC8, 0xE5, 0x48, 0x87, 0x34, 0xE9, 0x27, 0x20, 0xE7, 0x78, 0x78, 0x88, 0xA5, 0xB, 0x41, 0x1D, 0xEE, 0x7, 0xB8, 0x3B, 0x24, 0x3F, 0x98, 0xA7, 0x9C, 0x17, 0x19, 0x92, 0xF6, 0x60, 0xB7, 0xB2, 0x7F, 0x45, 0xD3, 0x25, 0x32, 0xD5, 0xCF, 0x7, 0x7F, 0x57, 0xA8, 0x6C, 0x3B, 0x2, 0x81, 0x81, 0x0, 0xEA, 0x36, 0xD8, 0x13, 0x69, 0x58, 0x44, 0x79, 0x65, 0x85, 0xD0, 0x95, 0x93, 0xF6, 0x7B, 0x2, 0x32, 0x2, 0x79, 0xE5, 0x91, 0xB9, 0xD7, 0x4C, 0xC0, 0x4A, 0x74, 0x24, 0x74, 0x41, 0x1C, 0x46, 0xCE, 0x98, 0x2B, 0x87, 0x7D, 0xBF, 0x54, 0x6A, 0x32, 0x8E, 0x72, 0x6D, 0x47, 0xFD, 0x33, 0x8B, 0x40, 0x27, 0x93, 0x6, 0x56, 0xE9, 0xD0, 0x6F, 0x45, 0x5F, 0xB1, 0xAE, 0x94, 0x3, 0x23, 0x19, 0xEE, 0x51, 0x6E, 0x81, 0xEF, 0xCE, 0xA6, 0x7, 0xEC, 0x12, 0x7A, 0x4D, 0x46, 0x33, 0x63, 0x70, 0x2E, 0x56, 0x2A, 0x70, 0x1D, 0x4A, 0x61, 0x88, 0x44, 0x48, 0x35, 0x75, 0xBD, 0x65, 0x6, 0xF0, 0xAA, 0x89, 0xEC, 0xE4, 0x35, 0x2C, 0x7B, 0xF2, 0x35, 0x20, 0x1D, 0xB3, 0x9C, 0xF2, 0xD2, 0xB6, 0xAF, 0xB2, 0xEF, 0x5C, 0x90, 0x9F, 0x33, 0xF0, 0x7C, 0xC2, 0xAE, 0xEC, 0xF2, 0xC8, 0xD7, 0xCD, 0x2, 0x81, 0x81, 0x0, 0x85, 0xB4, 0xDD, 0x81, 0x45, 0x8, 0xF8, 0xA3, 0x29, 0x78, 0x8A, 0xD6, 0x90, 0x8, 0x6A, 0x16, 0x75, 0x16, 0x4B, 0x60, 0x93, 0x98, 0xE4, 0x6D, 0xAD, 0x9B, 0xF1, 0x9D, 0xFB, 0x1, 0xD0, 0x2B, 0x71, 0x6E, 0x6E, 0xB3, 0x9, 0xC9, 0x9A, 0x42, 0x20, 0xA8, 0x67, 0xBE, 0x19, 0x56, 0x87, 0xD8, 0x21, 0x36, 0x8C, 0xCC, 0xC, 0xF6, 0x82, 0xB2, 0xCD, 0xB6, 0x41, 0xC, 0xB1, 0x37, 0x69, 0x10, 0x74, 0x3D, 0x68, 0x79, 0x1D, 0x39, 0x47, 0x46, 0xC7, 0xE7, 0x43, 0x93, 0x6E, 0x79, 0x2A, 0xAE, 0x6D, 0x79, 0x86, 0x3, 0x61, 0xA8, 0xB1, 0xB2, 0x9D, 0x5D, 0x41, 0xF0, 0x98, 0x75, 0x32, 0x8D, 0x82, 0xB0, 0x8D, 0xC7, 0x98, 0x88, 0xFD, 0x5A, 0x10, 0x68, 0xE5, 0x79, 0xAF, 0xD5, 0x4A, 0x9F, 0x2A, 0xAD, 0xC7, 0xDF, 0x42, 0x15, 0xBE, 0xD2, 0xD2, 0x13, 0xEC, 0x5A, 0xEA, 0xA8, 0x13, 0x95];

    let der = der_parser::parse_der(&bytes).unwrap();

    let mut di = der.1.ref_iter();

    println!("rest:  {:?}", der.0);
    println!("next1: {:?}", di.next());
    println!("next2: {:?}", di.next());
}

Output:

rest:  []
next1: Some(DerObject { class: 0, structured: 0, tag: 2, content: Integer(0) })
next2: None

Should string decoding check the character set?

Hi,

to the best of my knowledge string character sets are not verified currently, for example PrintableString or IA5String. Is this correct?

To give some background for my question, suppose I parse an utf8 string and then do std::str::from_utf, which I then expect to succeed.

Dependency trouble with nom_pem

I'm running into some kind of dependency conflict trying to use both der-parser=0.4.4 and nom_pem=1.0.3. When I add both of these, I can't compile nom_pem.

   Compiling nom_pem v1.0.3
error[E0243]: wrong number of type arguments: expected at least 1, found 0
  --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/nom_pem-1.0.3/src/lib.rs:63:14
   |
63 |     NomError(nom::Err),
   |              ^^^^^^^^ expected at least 1 type argument

I think maybe it has something to do with the verbose-errors feature maybe?

BerObject struct changes

Currently looking at: https://redmine.openinfosecfoundation.org/issues/2977

I've run into an issue where to be able to implement the detect-asn1 checks, some fields cannot be accessed with the current API, such as the length len of the BerObjectHeader.

The parse_ber function currently returns a BerObject

#[derive(Debug, Clone)]
pub struct BerObject<'a> {
    pub class: BerClass,
    pub structured: u8,
    pub tag: BerTag,

    pub content: BerObjectContent<'a>,
    pub raw_tag: Option<&'a [u8]>,
}

Note, the similarities with BerObjectHeader

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BerObjectHeader<'a> {
    pub class: BerClass,
    pub structured: u8,
    pub tag: BerTag,
    pub len: u64,

    pub raw_tag: Option<&'a [u8]>,
}

And the following which is called in parse_ber after both the header/content are parsed:

impl<'a> BerObject<'a> {
    pub fn from_header_and_content<'hdr>(
        hdr: BerObjectHeader<'hdr>,
        c: BerObjectContent<'hdr>,
    ) -> BerObject<'hdr> {
        BerObject {
            class: hdr.class,
            structured: hdr.structured,
            tag: hdr.tag,
            content: c,
            raw_tag: hdr.raw_tag,
        }
    }

(Note, the len from hdr is not copied and can no longer be accessed, the .to_header() method on the BerObject explicitly sets this value to 0)

What if a BerObject looked like this?

/// Representation of a DER-encoded (X.690) object
#[derive(Debug, Clone)]
pub struct BerObject<'a> {
    pub header: BerObjectHeader<'a>,
    pub content: BerObjectContent<'a>,
}

Let me know what you think and I can start working on it!

Unable to get the exact form of the tag

Hello,

We are using your library to parse ASN.1 files from EMV cards. It works pretty well but we have a problem for some tags.

In EMV standards, tags like 0x8F or 0x9F0F means different things while there are both a "application-specific not-structured tag of value 15". Then it is not possible to differentiate them using BerObject tag property.

Would it be possible to add a way to access the exact representation of the tag (as a byte slice for example) ? That would be very useful, at least for non-universal tags.

Objects with private tags are parsed like universal tags

Looking at the parsing implementation, for parse_der() or parse_ber(), any object with a BerClass::Private tag is still parsed as though it were BerClass::Universal, even though private tags are enterprise-specific and therefore assuming they have the same meaning as universal tags is unlikely to be true.

`BerObject::as_pretty()` prints universal tag names for non-universal classes

Not a Contribution

BerObject::as_pretty() prints universal tag names when printing BerObjectContent::Tagged and BerObjectContent::Unknown contents. As of 5f76d92 (see #47) it includes the class name for BerObjectContent::Unknown, but it didn't change anything about how tags are printed.

Examples

DER: [80, 4, de, ad, be, ef]
Output: Unknown(ContextSpecific,EndOfContent,[de, ad, be, ef])

DER: [42, 4, de, ad, be, ef]
Output: Unknown(Application,Integer,[de, ad, be, ef])

If I parse tagged content, I get similarly busted output:

-- Type1 ::= VisibleString
-- Type2 ::= [APPLICATION 3] IMPLICIT Type1
-- Type3 ::= [APPLICATION 2] Type2
-- Type4 ::= [1] Type3
DER: [a1, 9, 62, 7, 43, 5, 4a, 6f, 6e, 65, 73]
Output: ContextSpecific [CONTEXT-SPECIFIC Boolean] {
  ContextSpecific [APPLICATION Integer] {
    VisibleString("Jones")
  }
}

There's two issues here. The first is of course that it's printing universal tag names for non-universal classes. The second is that it always prints ContextSpecific for tagged objects even for other classes.

Parsing private tags is also curious:

DER: [c3, 4, de, ad, be, ef]
Output: Private(c:PRIVATE s:0 t:3): [de ad be ef]

It's no longer trying to print the tag name, but instead it prints "Private" twice with this odd formatting. It also puts the bytes outside of the parens, whereas Unknown puts it inside.

Expected behavior

I would expect BerObjectContent::Unknown and BerObjectContent::Private to print similarly. For that matter, I don't even know why Private gets its own variant whereas ContextSpecific and Application share an "Unknown" one. I would have expected either all three to get their own variants, or all three to share a variant (the latter being simpler of course).

In any case, I would have expected something like Unknown(ContextSpecific(0),[de, ad, be, ef]) and Unknown(Application(2),[de, ad, be, ef]) (note how the tag name isn't interpreted), or possibly instead formatting similar to Private. And for tagged vales, I might expect it to say something like Tagged [CONTEXT-SPECIFIC 1] instead.

Musings on underlying issues

I think the core issue here is really the fact that tags and classes are separate, and so BerTag(2) prints automatically as Integer regardless of the class. I would expect this to be a problem for parsing too. For example, my parser for the tagged content looks like

parse_der_tagged_explicit(1, |i| {
    parse_der_tagged_explicit(2, |i| {
        parse_der_tagged_implicit(3, parse_der_content(DerTag::VisibleString))(i)
    })(i)
})

Notice here how my parser doesn't mention classes anywhere. It parsed [a1, 9, 62, 7, 43, 5, 4a, 6f, 6e, 65, 73], but it would have happily parsed [61, 9, a2, 7, 43, 5, 4a, 6f, 6e, 65, 73] as well despite the fact that the change in class means the tags might have very different meanings.

I really think this needs to be changed such that the class and tag are a single value. This also fixes the naming issue, as ASN.1 uses "tag" to mean "class and number". So we can use something like the following:

pub struct BerTag(pub BerClass, pub u32);

It can then have a Display impl that prints like "{class}({number})" (Debug can just be derived). (EDIT: Or maybe it should print like [{class} {number}], optionally printing ContextSpecific like [{number}] to match ASN.1 notation for tagged types.)

This is of course a rather significant change to the crate.

Side note about the parser

If you look at my tagged parser above, you'll notice the use of |i| parse_fn(โ€ฆ)(i). This feels redundant, but it's necessary right now because parse_der_tagged_explicit (and similar functions) take a F: Fn but return an impl FnMut. This means they can't be nested without the closure wrappers. My expectation is they could be modified to take F: FnMut rather trivially (just by adding a mut keyword) and the fact that they don't is likely an oversight due to the fact that none of the built-in parsers use them (and the doc examples don't nest them).

der-parser 6.0 roadmap

placeholder for now, roadmap is not defined yet

Some ideas:

  • Add &[u8] to error type ? (consequence: BerError will now have a lifetime, but we will be able to tell where the parsing failed)
  • Use Cow<'a, [u8]> everywhere so BerObject can own data
  • Support BER constructed strings. This may be done either be reconstructing the data (requiring owned data, see above), ropes (new dependency, for ex the bytes crate), or new/recursive object types (resulting in a complex API)

Make Oid zero-copy

Hi,

when parsing oids the binary representation is converted to Vec<u64>.

I propose to keep the binary representation and provide api for the conversion to Vec<u64> (or an iterator implementation).

In my case I use oids basically only for comparison with other oids.

The downsides I see for my proposal are:

  • the hierachical structure is not as easily visible in this way
  • api break: Oid would get an lifetime parameter (users of der-parser already handle lifetimes a lot, so I don't think this is a big issue)

The advantages:

  • zero-copy, Oid becomes smaller. In particular cloning does not heap allocate which is useful if you use them in many places.
  • parsing is faster
  • edit: a u64 can be too small (?)

I also propose to add a proc macro for easy construction and a Hash implementation.

I can implement the proposed changes if you are interested.

fails to build on Debian 10

I suspect this is a Debian issue, but not sure. Recently Debian 10 updated its rustc to 1.41.1 (and cargo to 1.42.1). Since then this crate fails to build inside Suricata:

error: /builds/inliniac/suricata-ci/suricata/rust/target/release/deps/libder_oid_macro-6303e17a207c2efa.so: undefined symbol: llvm.x86.subborrow.64
--> /builds/inliniac/suricata-ci/suricata/rust/vendor/der-parser/src/lib.rs:171:9
     |
 171 | pub use der_oid_macro::oid;
     |         ^^^^^^^^^^^^^

This happens in Suricata CI builds.

Interestingly it does not happen on Debian 10 on ARM. Not sure what could cause this.

Running into build errors on debian stretch

I can run der-parser just fine on Ubuntu 20.04, which comes with glibc version 2.31:

$ ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9) 2.31

But when I run on Debian stretch in a docker environment, I run into the following error:

error: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /cfsetup_build/target/debug/deps/libder_oid_macro-9517fe04de556285.so)
 --> src/config.rs:2:5
  |
2 | use der_parser::{ber::BerObjectContent, parse_der};
  |     ^^^^^^^^^^

error: aborting due to previous error

It looks like there is an older version of glibc on stretch which is causing this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.