Built-in Go libraries for asn1 support are either reflection-based (crypto/asn1) or very low-level (golang.org/x/crypto/cryptobyte). Idea is to provide Protobuf-like experience for working with ASN1 in Golang.
Note: currently provided code generator implementation creates definitions to be used with crypto/asn1, so all its limitations (no real CHOICE support) apply for this project as well.
- Custom Lexer consumes from bufio.Reader and called by Parser
- Parser is built using goyacc based on BNF provided in X.680 standard. As the result, Parser produces ASN1 module AST.
- AST is used by Code Generator to produce declarations, serialization, and deserialization code.
Feature | Parsing | Codegen |
---|---|---|
Exports | Syntax only | No |
Imports | Yes | No |
Type assignments | Yes | Yes |
Value assignments | Yes | Partial 1 |
XML | No | |
Objects | No | |
Parameterization | No |
Type | Parsing | Codegen |
---|---|---|
BIT STRING | Yes | Yes; named bits not translated |
BOOLEAN | Yes | Yes |
CHARACTER STRING | Yes | Yes |
CHOICE | Yes | Yes; common demoninator type is used |
Embedded PDV | No | |
External | No | |
ENUMERATED | Yes 2 | Yes; alternative values not translated |
Instance Of | No | |
INTEGER | Yes | Yes |
NULL | Yes | |
Object Class | No | |
Object Identifier | Yes | |
OCTET STRING | Yes | Yes |
REAL | Yes | Yes |
Relative OID | No | |
SEQUENCE | Yes 3 | Yes |
SEQUENCE OF | Yes | Yes |
SET | Yes 3 | Yes |
SET OF | Yes | Yes |
ANY | Yes 4 | Yes |
Tagged types | Yes | Yes 5 |
Constrained types | Partial | Partial; generates wrapped type |
Value | Parsing | Codegen |
---|---|---|
BOOLEAN | Yes | Yes |
INTEGER | Yes | Yes |
OID | Yes | No |
Real | Yes | Yes |
Referenced | No | |
Object class fields | No | |
BIT STRING | No | |
Other | No |
- Lexer
- identifiers
- numbers
- keywords
- symbols
- strings, bit strings, hex strings
- XML
- Parser
- module definition BNF
- parse Kerberos (rfc4120)
- yield AST from parser
- parse SNMPv1 (rfc1157, rfc1155); no codegen, depends on CHOICE
- parse LDAP (rfc4511, partially - required minor modifications); no codegen, depends on CHOICE
- parse X.509 (rfc 5280) - depends on ANY
- SNMPv2 (rfc3411–3418)
- Code Generator
- declaration generator
- crypto/asn1 compatible generation mode
- verify serialization on Kerberos
- DER serialization generator
- DER deserialization generator
- Supported ASN features
- SET type
- ANY type (1988 standard) - mapped to interface{}
- CHOICE type - mapped to interface{}, or asn1.RawValue if selections are tagged
- Extensions in SEQUENCE, SET, CHOICE
- Add more as found
Real-world ASN.1 descriptions from RFC documents are used to gauge completeness of the implementation. Standard itself is pretty huge, so features are added as needed.
Typically, this requires:
- Modifying asn1.y to uncomment unsupported branches of syntax notation, and add missing declarations. Refer to goyacc documentation for .y syntax notation.
- Extending ast.go with necessary fields and types.
- Modifying codegen.go to produce corresponding Go declarations. Note that not all ASN declarations can be mapped to crypto/asn1.
For example, refer to CHOICE implementation.
Footnotes
-
Only literal values are supported, referenced values are not implemented. ↩
-
With ASN.1 syntax limitations: explicit extensibility and non-literal values are not supported. ↩
-
With ASN.1 syntax limitations: two component type lists, exceptions and extension addition groups are not supported, extensions are not exposed in generated Go code. ↩ ↩2
-
Not defined in the latest ASN.1 standard. ↩
-
Used by encoding/asn1 only in SEQUENCE and SET fields. CHOICE with tagged alternatives is represented as RawValue. ↩