class
ASN1::BER
Overview
A single ASN.1 Basic Encoding Rules (BER) TLV element: an identifier (tag), a length and a payload. Used to build and parse SNMP, LDAP, X.509 and similar protocols.
require "bindata/asn1"
ber = ASN1::BER.new
ber.set_integer(42)
io.write_bytes(ber)
ber = io.read_bytes(ASN1::BER)
ber.get_integer # => 42
Typed payload accessors live in data_types.cr (#get_integer/#set_integer,
#get_object_id/#set_object_id, #get_string, #get_boolean, ...). A
constructed element can be split into / built from sub-elements with
#children / #children=.
Defined in:
bindata/asn1.crbindata/asn1/data_types.cr
bindata/asn1/identifier.cr
bindata/asn1/length.cr
Constant Summary
-
AFTER_DESERIALIZE =
[] of Nil -
BEFORE_SERIALIZE =
[] of Nil -
DIRECT_STRING_TAGS =
{UniversalTags::UTF8String, UniversalTags::CharacterString, UniversalTags::PrintableString, UniversalTags::IA5String, UniversalTags::OctetString, UniversalTags::NumericString, UniversalTags::VisibleString, UniversalTags::GeneralString, UniversalTags::GraphicString} -
String types whose repertoire is ASCII-compatible, so the UTF-8
String.newdecodes them directly. (T61String / VideotexString use the T.61 / videotex character sets, which are neither ASCII nor UTF-8, so they are not decoded here rather than mis-decoded.) -
ENDIAN =
["big"] -
GENERALIZEDTIME_FORMAT =
/\A(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d+)?(Z|[+-]\d{4})\z/ -
YYYYMMDDHHMMSS(.fff)?(Z|±HHMM). -
KLASS_NAME =
[ASN1::BER] -
PARTS =
[{type: "basic", name: identifier, cls: ASN1::BER::Identifier, onlyif: nil, verify: nil, value: nil}, {type: "basic", name: length, cls: ASN1::BER::Length, onlyif: nil, verify: nil, value: nil}] of Nil -
REMAINING =
[] of Nil -
UTCTIME_FORMAT =
/\A(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})?(Z|[+-]\d{4})\z/ -
YYMMDDHHMM[SS](Z|±HHMM)— the seconds are optional.
Class Method Summary
Instance Method Summary
-
#__format__ : IO::ByteFormat
A
grouporbit_fieldcaptures the endianness at its declaration point, so declaringendianafter one would silently leave it system-endian. -
#bitstring_unused_bits : UInt8
The number of unused (padding) bits in the final data byte (0..7).
-
#children
Parses the payload as a sequence of nested BER elements.
-
#children=(parts)
Encodes parts into the payload and marks this element constructed.
- #constructed
- #constructed=(custom : Bool)
- #extended
- #extended=(parts : Array(ExtendedIdentifier))
- #extended?
-
#get_bit_array : BitArray
The BIT STRING's significant bits as a
BitArray, numbered MSB-first from the first data byte (ASN.1 bit 0 is the high bit of the first byte). -
#get_bitstring : Bytes
Reads the BIT STRING data bytes (dropping the leading unused-bit count).
-
#get_boolean
Reads the payload as a BOOLEAN.
-
#get_bytes : Slice(UInt8)
Returns the raw bytes
-
#get_hexstring(universal = true, tag = UniversalTags::OctetString)
Gets a hex representation of the bytes
-
#get_integer(check_tags = {UniversalTags::Integer, UniversalTags::Enumerated}, check_class = TagClass::Universal) : Int64
Reads the payload as a two's-complement signed INTEGER (or ENUMERATED).
-
#get_integer_bytes : Bytes
Returns the INTEGER payload as raw bytes, with a leading zero/sign pad removed.
-
#get_object_id
Returns the object ID in string format.
-
#get_string
Decodes the payload to a
String. -
#get_time : Time
Reads the payload as a UTCTime or GeneralizedTime, normalised to UTC.
-
#identifier : Identifier
Components of a BER object
-
#identifier=(identifier : Identifier)
Components of a BER object
-
#inspect(io : IO) : Nil
Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.
- #length : Length
- #length=(length : Length)
-
#max_depth : Int32
Maximum nesting depth that
#childrenwill descend before raisingMaxDepthExceeded. -
#max_depth=(max_depth : Int32)
Maximum nesting depth that
#childrenwill descend before raisingMaxDepthExceeded. -
#null?
Whether this is a well-formed universal NULL element: primitive, tag
05, empty payload (X.690 §8.8). - #payload : Bytes
- #payload=(payload : Bytes)
-
#read(io : IO) : IO
Reads the fields of this instance from io, in declaration order, and returns io.
-
#sequence?
Whether this is a constructed universal Sequence or Set, i.e.
-
#set_bit_array(bits : BitArray)
Sets a BIT STRING from a
BitArray(numbered MSB-first, as ASN.1 expects). -
#set_bitstring(bytes : Bytes, unused_bits : Int = 0)
Sets a BIT STRING from bytes, with unused_bits (0..7) of padding in the final byte.
-
#set_boolean(value)
Sets a BOOLEAN payload.
-
#set_bytes(data, tag = UniversalTags::OctetString, tag_class = TagClass::Universal)
Sets the raw payload bytes and the given tag.
-
#set_hexstring(string, tag = UniversalTags::OctetString, tag_class = TagClass::Universal)
Sets bytes from a hexstring
-
#set_integer(value, tag = UniversalTags::Integer, tag_class = TagClass::Universal)
Encodes value as a minimal two's-complement INTEGER payload.
-
#set_null
Sets an empty, primitive NULL payload (encodes as
05 00). -
#set_object_id(oid)
Sets a string representing an object ID.
-
#set_string(string, tag = UniversalTags::UTF8String, tag_class = TagClass::Universal)
Sets a string.
-
#set_time(time : Time, tag = UniversalTags::GeneralizedTime)
Encodes time (converted to UTC) as a GeneralizedTime (default) or UTCTime, in the canonical
…Zform. -
#size
The current payload length in bytes.
-
#tag
The universal tag as a
UniversalTagsenum. - #tag_class
- #tag_class=(tag : TagClass)
- #tag_number
- #tag_number=(tag_type : Int | UniversalTags)
-
#write(io : IO)
Writes the fields of this instance to io in declaration order.
Instance methods inherited from class BinData
__format__ : IO::ByteFormat
__format__,
max_content_length : Int32
max_content_length,
max_content_length=(max_content_length : Int32)
max_content_length=,
read(io : IO) : IO
read,
to_io(io : IO, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
to_io,
to_s(io)
to_s,
to_slice
to_slice,
write(io : IO)
write
Class methods inherited from class BinData
bit_fields
bit_fields,
from_io(io : IO, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
from_io,
from_slice(bytes : Slice, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
from_slice
Macros inherited from class BinData
__add_enum_field(name, cls, onlyif, verify, value, encoding, enum_type)
__add_enum_field,
__build_methods__
__build_methods__,
after_deserialize(&block)
after_deserialize,
array(name, length, onlyif = nil, verify = nil, value = nil)
array,
before_serialize(&block)
before_serialize,
bit_field(onlyif = nil, verify = nil, endian = nil, &block)
bit_field,
bits(size, name, value = nil, default = nil)
bits,
bool(name, default = false)
bool,
bytes(name, length, onlyif = nil, verify = nil, value = nil, default = nil)
bytes,
custom(name, onlyif = nil, verify = nil, value = nil)
custom,
endian(format)
endian,
enum_bits(size, name)
enum_bits,
enum_field(size, name, onlyif = nil, verify = nil, value = nil)
enum_field,
field(type_declaration, onlyif = nil, verify = nil, value = nil, length = nil, read_next = nil, encoding = nil, endian = nil)
field,
float32(name, onlyif = nil, verify = nil, value = nil, default = nil)
float32,
float32be(name, onlyif = nil, verify = nil, value = nil, default = nil)
float32be,
float32le(name, onlyif = nil, verify = nil, value = nil, default = nil)
float32le,
float64(name, onlyif = nil, verify = nil, value = nil, default = nil)
float64,
float64be(name, onlyif = nil, verify = nil, value = nil, default = nil)
float64be,
float64le(name, onlyif = nil, verify = nil, value = nil, default = nil)
float64le,
group(name, onlyif = nil, verify = nil, value = nil, &block)
group,
int128(name, onlyif = nil, verify = nil, value = nil, default = nil)
int128,
int128be(name, onlyif = nil, verify = nil, value = nil, default = nil)
int128be,
int128le(name, onlyif = nil, verify = nil, value = nil, default = nil)
int128le,
int16(name, onlyif = nil, verify = nil, value = nil, default = nil)
int16,
int16be(name, onlyif = nil, verify = nil, value = nil, default = nil)
int16be,
int16le(name, onlyif = nil, verify = nil, value = nil, default = nil)
int16le,
int32(name, onlyif = nil, verify = nil, value = nil, default = nil)
int32,
int32be(name, onlyif = nil, verify = nil, value = nil, default = nil)
int32be,
int32le(name, onlyif = nil, verify = nil, value = nil, default = nil)
int32le,
int64(name, onlyif = nil, verify = nil, value = nil, default = nil)
int64,
int64be(name, onlyif = nil, verify = nil, value = nil, default = nil)
int64be,
int64le(name, onlyif = nil, verify = nil, value = nil, default = nil)
int64le,
int8(name, onlyif = nil, verify = nil, value = nil, default = nil)
int8,
int8be(name, onlyif = nil, verify = nil, value = nil, default = nil)
int8be,
int8le(name, onlyif = nil, verify = nil, value = nil, default = nil)
int8le,
remaining_bytes(name, onlyif = nil, verify = nil, default = nil)
remaining_bytes,
skip(length, onlyif = nil, verify = nil)
skip,
string(name, onlyif = nil, verify = nil, length = nil, value = nil, encoding = nil, default = nil)
string,
uint128(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint128,
uint128be(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint128be,
uint128le(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint128le,
uint16(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint16,
uint16be(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint16be,
uint16le(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint16le,
uint32(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint32,
uint32be(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint32be,
uint32le(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint32le,
uint64(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint64,
uint64be(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint64be,
uint64le(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint64le,
uint8(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint8,
uint8be(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint8be,
uint8le(name, onlyif = nil, verify = nil, value = nil, default = nil)
uint8le,
variable_array(name, read_next, onlyif = nil, verify = nil, value = nil)
variable_array
Class Method Detail
Instance Method Detail
A group or bit_field captures the endianness at its declaration point, so
declaring endian after one would silently leave it system-endian. Fail loudly.
The number of unused (padding) bits in the final data byte (0..7).
Parses the payload as a sequence of nested BER elements. The
max_content_length and #max_depth caps propagate to each child.
Only valid for a constructed element; on a primitive the payload is raw
content, not a TLV list, so parsing it would yield garbage. Raises
ASN1::Error in that case.
Encodes parts into the payload and marks this element constructed. The
tag class/number are left untouched — set them yourself (e.g. to a universal
Sequence/Set, or a constructed context tag) so #sequence? reflects the
intended type; this accessor only guarantees the #constructed flag.
The BIT STRING's significant bits as a BitArray, numbered MSB-first from
the first data byte (ASN.1 bit 0 is the high bit of the first byte).
Reads the BIT STRING data bytes (dropping the leading unused-bit count). The
final byte's low #bitstring_unused_bits bits are padding. Any unused count
0..7 is accepted; use #get_bit_array for the exact significant bits.
Gets a hex representation of the bytes
Reads the payload as a two's-complement signed INTEGER (or ENUMERATED).
With the default universal check_class the tag is validated against
check_tags. With a non-universal check_class (e.g. an SNMP context-tagged
Counter/Gauge) only the class is checked — the universal-tag check is skipped,
since check_tags are universal tags and don't apply to a context tag.
Returns the INTEGER payload as raw bytes, with a leading zero/sign pad removed.
Returns the object ID in string format.
Sub-identifiers are decoded as big-endian base-128 numbers per X.690 §8.19
(every octet but the last has its high bit set), so arcs of any size are
supported. BigInt is used because OID arcs are unbounded (e.g. UUID-based
OIDs under 2.25, ITU-T X.667).
Decodes the payload to a String. BMPString is transcoded from UTF-16BE and
UniversalString from UTF-32BE (leniently — surrogate pairs are accepted, not
strict UCS-2/UCS-4); the ASCII-repertoire types are read directly. An
incomplete/malformed byte sequence raises ASN1::InvalidPayload; individual
invalid code points may be substituted by the platform transcoder.
Reads the payload as a UTCTime or GeneralizedTime, normalised to UTC.
A time zone is required (Z or a numeric ±HHMM offset); a bare local time
is rejected. UTCTime's two-digit year uses the RFC 5280 pivot (>= 50 =>
19xx, < 50 => 20xx).
Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.
class Person
def initialize(@name : String, @age : Int32)
end
end
Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>
Maximum nesting depth that #children will descend before raising
MaxDepthExceeded. The default (100) guards a recursive consumer walk
against stack overflow on a deeply nested message (a few KB of 30 80 …
encodes thousands of levels); 0 disables the limit. Propagated to each
child alongside max_content_length.
Maximum nesting depth that #children will descend before raising
MaxDepthExceeded. The default (100) guards a recursive consumer walk
against stack overflow on a deeply nested message (a few KB of 30 80 …
encodes thousands of levels); 0 disables the limit. Propagated to each
child alongside max_content_length.
Whether this is a well-formed universal NULL element: primitive, tag 05,
empty payload (X.690 §8.8).
Reads the fields of this instance from io, in declaration order, and
returns io. Raises BinData::ParseError (or BinData::VerificationException)
on malformed input.
Whether this is a constructed universal Sequence or Set, i.e. an element
whose payload is itself a list of BER elements (see #children).
Sets a BIT STRING from a BitArray (numbered MSB-first, as ASN.1 expects).
Sets a BIT STRING from bytes, with unused_bits (0..7) of padding in the final byte.
Sets the raw payload bytes and the given tag.
Sets bytes from a hexstring
Encodes value as a minimal two's-complement INTEGER payload. ameba:disable Metrics/CyclomaticComplexity
Sets a string representing an object ID.
Each arc is encoded as a big-endian base-128 number per X.690 §8.19. Arcs
are parsed as BigInt, so arbitrarily large values are supported.
Sets a string. BMPString is encoded to UTF-16BE and UniversalString to
UTF-32BE; every other type stores the string's UTF-8 bytes. tag may be a
UniversalTags or its integer value.
Encodes time (converted to UTC) as a GeneralizedTime (default) or UTCTime,
in the canonical …Z form. UTCTime can only represent years 1950..2049.
Sub-second precision is dropped (DER forbids fractional seconds), so a Time
with a fractional part does not round-trip exactly through #get_time.
The current payload length in bytes. Reads from the payload itself (not the
decoded Length, which is only refreshed on #write), so it is correct for
in-memory-built objects and for indefinite-length elements too.
The universal tag as a UniversalTags enum. Raises unless this is a
universal-class element.
Writes the fields of this instance to io in declaration order. Raises
BinData::WriteError (or BinData::VerificationException) on failure.