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.cr
bindata/asn1/data_types.cr
bindata/asn1/identifier.cr
bindata/asn1/length.cr

Constant Summary

AFTER_DESERIALIZE = [] of Nil
BEFORE_SERIALIZE = [] of Nil
ENDIAN = ["big"]
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

Class Method Summary

Macro Summary

Instance Method Summary

Instance methods inherited from class BinData

__format__ : IO::ByteFormat __format__, 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

def self.bit_fields #

[View source]

Macro Detail

macro asn1_ber(name, onlyif = nil, verify = nil, value = nil) #

[View source]
macro ber(name, onlyif = nil, verify = nil, value = nil) #

[View source]

Instance Method Detail

def __format__ : IO::ByteFormat #

A group captures the endianness at its declaration point, so declaring endian after one would silently leave it system-endian. Fail loudly.


[View source]
def children #

Parses the payload as a sequence of nested BER elements. The #max_content_length cap propagates to each child.


[View source]
def children=(parts) #

Encodes parts into the payload and marks this element constructed.


[View source]
def constructed #

[View source]
def constructed=(custom : Bool) #

[View source]
def extended #

[View source]
def extended=(parts : Array(ExtendedIdentifier)) #

[View source]
def extended? #

[View source]
def get_bitstring #

Reads the payload as a BIT STRING (only the zero-unused-bits form is supported).


[View source]
def get_boolean #

Reads the payload as a BOOLEAN.


[View source]
def get_bytes : Slice(UInt8) #

Returns the raw bytes


[View source]
def get_hexstring(universal = true, tag = UniversalTags::OctetString) #

Gets a hex representation of the bytes


[View source]
def 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).


[View source]
def get_integer_bytes : Bytes #

Returns the INTEGER payload as raw bytes, with a leading zero/sign pad removed.


[View source]
def get_object_id #

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


[View source]
def get_string #

Returns a UTF8 string


[View source]
def identifier : Identifier #

Components of a BER object


def identifier=(identifier : Identifier) #

Components of a BER object


def inspect(io : IO) : Nil #
Description copied from class Reference

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>

[View source]
def length : Length #

def length=(length : Length) #

def max_content_length : Int32 #

Maximum number of payload bytes this object (and its children) may allocate or read. 0, the default, means unlimited. Set a positive cap before reading untrusted input to guard against allocation/exhaustion DoS, reading the root explicitly so the cap is in place before parsing:

ber = ASN1::BER.new
ber.max_content_length = 64 * 1024
ber.read(io)

[View source]
def max_content_length=(max_content_length : Int32) #

Maximum number of payload bytes this object (and its children) may allocate or read. 0, the default, means unlimited. Set a positive cap before reading untrusted input to guard against allocation/exhaustion DoS, reading the root explicitly so the cap is in place before parsing:

ber = ASN1::BER.new
ber.max_content_length = 64 * 1024
ber.read(io)

[View source]
def payload : Bytes #

[View source]
def payload=(payload : Bytes) #

[View source]
def read(io : IO) : IO #
Description copied from class BinData

Reads the fields of this instance from io, in declaration order, and returns io. Raises BinData::ParseError (or BinData::VerificationException) on malformed input.


[View source]
def sequence? #

Whether this is a constructed universal Sequence or Set, i.e. an element whose payload is itself a list of BER elements (see #children).


[View source]
def set_boolean(value) #

Sets a BOOLEAN payload.


[View source]
def set_bytes(data, tag = UniversalTags::OctetString, tag_class = TagClass::Universal) #

Sets the raw payload bytes and the given tag.


[View source]
def set_hexstring(string, tag = UniversalTags::OctetString, tag_class = TagClass::Universal) #

Sets bytes from a hexstring


[View source]
def set_integer(value, tag = UniversalTags::Integer, tag_class = TagClass::Universal) #

Encodes value as a minimal two's-complement INTEGER payload. ameba:disable Metrics/CyclomaticComplexity


[View source]
def set_object_id(oid) #

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.


[View source]
def set_string(string, tag = UniversalTags::UTF8String, tag_class = TagClass::Universal) #

Sets a UTF8 string


[View source]
def size #

The decoded payload length in bytes.


[View source]
def tag #

The universal tag as a UniversalTags enum. Raises unless this is a universal-class element.


[View source]
def tag_class #

[View source]
def tag_class=(tag : TagClass) #

[View source]
def tag_number #

[View source]
def tag_number=(tag_type : Int | UniversalTags) #

[View source]
def write(io : IO) #
Description copied from class BinData

Writes the fields of this instance to io in declaration order. Raises BinData::WriteError (or BinData::VerificationException) on failure.


[View source]