Documentation
¶
Overview ¶
Package ber implements the ASN.1 Basic Encoding Rules (BER). The Basic Encoding Rules are defined in Rec. ITU-T X.690. See also “A Layman's Guide to a Subset of ASN.1, BER, and DER”.
See the package documentation of the asn1 package for details how Go types translate to ASN.1 types. Types following that specification can be encoded into and decoded from a stream of binary data using the Basic Encoding Rules using this package. The following limitations apply:
- When decoding an ASN.1 INTEGER type into a Go integer the size of the integer is limited by the size of the Go type. This limitation does not apply to *math/big.Int.
- When decoding an ASN.1 REAL type into a Go float64 or float32, the size of the value is limited by the size of the Go type. When using *math/big.Float the size limitations of that type apply.
- When decoding binary data into a pre-allocated byte slice the data will overwrite existing data in the slice.
- When decoding binary data into a byte array, the number of bytes in the element must match the length of the array exactly.
- When decoding a constructed element into an array the number of sequence elements must match the length of the array exactly.
- Decoding into an interface{} will decode known types as their corresponding Go values. Unrecognized types will be stored as RawValue.
Index ¶
- Constants
- func CombinedLength(ls ...int) int
- func Marshal(val any) ([]byte, error)
- func MarshalWithParams(val any, params string) ([]byte, error)
- func Unmarshal(b []byte, val any) error
- func UnmarshalWithParams(b []byte, val any, params string) error
- type BerDecoder
- type BerEncoder
- type BerMatcher
- type Decoder
- type ElementReader
- type EncodeError
- type Encoder
- type Flag
- type Header
- type InvalidDecodeError
- type RawValue
- type Sequence
- type StringReader
- func (r *StringReader) Bytes() ([]byte, error)
- func (r *StringReader) Constructed() bool
- func (r *StringReader) Read(p []byte) (n int, err error)
- func (r *StringReader) ReadByte() (b byte, err error)
- func (r *StringReader) String() (string, error)
- func (r *StringReader) Strings() iter.Seq2[ElementReader, error]
- type StructuralError
- type SyntaxError
- type UnsupportedTypeError
Constants ¶
const LengthIndefinite = -1
LengthIndefinite when used as a magic number for the length of a Header indicates that the element is encoded using the constructed indefinite-length format.
Variables ¶
This section is empty.
Functions ¶
func CombinedLength ¶
CombinedLength returns the length of an element (not including its header) consisting of child elements of the specified lengths. If any of the passed lengths are LengthIndefinite, the result is LengthIndefinite as well.
func MarshalWithParams ¶
MarshalWithParams marshals the BER-encoding of val into a byte slice and returns it. The format of the params is described in the asn1 package. Using the `asn1:"-"` option has no effect here.
func Unmarshal ¶
Unmarshal parses a BER-encoded ASN.1 data structure from b. See Decoder.Decode for details. If any data is left over in b after val has been decoded, an error is returned.
func UnmarshalWithParams ¶
UnmarshalWithParams allows field parameters to be specified for the top-level element. The form of the params is the same as the field tags. See Decoder.Decode for details.
Types ¶
type BerDecoder ¶
type BerDecoder interface {
BerDecode(tag asn1.Tag, r ElementReader) error
}
BerDecoder is the interfaces implemented by types that can decode themselves from a binary representation in BER-encoding. In addition, types may want to implement the BerMatcher interface to provide support for optional elements.
The reader r reads the contents of the element, identified by tag. In particular r does not read the tag and length bytes of the element being decoded. At the end of the element r returns io.EOF, even if there are more bytes in the original data stream. If an implementation does not read r to completion, any remaining bytes are discarded. If r.Constructed() returns true, the remaining elements are syntactically validated.
Implementations must attempt to decode from r irrespective of the tag. However, implementations may alter their decoding behavior according to the tag used. Implementations SHOULD validate that r.Constructed() meets the requirements of the element. If decoding fails, an error must be returned that explains the failure. Usually such an error should be a SyntaxError or StructuralError. Implementations can also return io.ErrUnexpectedEOF to indicate that r returned io.EOF before the entire data was read.
The length of the element being decoded is available through r. Note that an element may use the indefinite length encoding in which case r might indicate a length of LengthIndefinite.
type BerEncoder ¶
BerEncoder is an interface that can be implemented by types that provide custom logic to encode themselves as an ASN.1 type using Basic Encoding Rules.
Encoding using BER is a two-step process: First the size of values is estimated and then elements are written to a byte stream. The BerEncode method realizes this by returning an io.WriterTo instead of writing data directly to a writer. Implementations write exactly the amount of bytes promised by h.Length. The writer passed to wt implements io.ByteWriter.
Implementations should return any validation errors from BerEncode. Errors returned from wt are assumed to be writing errors of the underlying writer.
If an element uses the indefinite-length format, the final two zero octets are written automatically and must not be written by wt. Custom constructed elements may want to use the Sequence type to facilitate their encoding. Note that struct tags override the class and tag of the returned header.
type BerMatcher ¶
BerMatcher can be implemented by types that implement BerDecoder to add support for optional elements. The BerMatch method is consulted if no tag number is given via struct tags. Implementations implement this interface by returning a boolean value indicating whether h.Class and h.Tag match the intrinsic tag of the element, i.e. if based on the h.Class and h.Tag it is expected that decoding will succeed.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder implements stream-based decoding of BER-encoded ASN.1 types. The Decoder type implements specialized buffering for BER-data. See the NewDecoder function for details.
To create a Decoder, use the NewDecoder function.
func NewDecoder ¶
NewDecoder creates a new Decoder reading from r.
Decoding BER requires single-byte reads. If r implements io.ByteReader then it is assumed that the reader is efficient enough so no buffering is done by d. Assuming that r produces a valid BER-encoding then d will never read more bytes than required to parse one element.
If r implements ElementReader and is reading a constructed element, d will decode those elements from r without additional buffering.
If r does not implement io.ByteReader then the Decoder will use its own buffering. If possible buffering is restricted to a single BER-encoded type: As long as the BER-encoded types read from r only use a definite-length format on the top-level element, d will not read more bytes from r than required to parse one element. If the indefinite-length encoding is used, then d might read more bytes from r than needed.
func (*Decoder) Decode ¶
Decode parses a BER-encoded ASN.1 data structure and uses the reflect package to fill in an arbitrary value pointed at by val. Because Decode uses the reflect package, the structs being written to must use exported (upper case) field names. If val is nil or not a pointer, Unmarshal returns an error.
func (*Decoder) DecodeAll ¶
DecodeAll decodes all elements from d into the value pointed to by val. The value pointed to by val must be able to decode a constructed ASN.1 type. See Decoder.Decode for details on the decoding process.
This method blocks until the underlying reader of d returns io.EOF, or an error is encountered.
func (*Decoder) DecodeWithParams ¶
DecodeWithParams works like Decoder.Decode but accepts additional parameters applied to the top-level element. The format for params is the same as for struct tags supported by this package. Using the `asn1:"optional"` or `asn1:"-"` options has no effect here.
func (*Decoder) More ¶
More indicates whether there might be more elements in d that can be decoded.
If d encounters a BER-encoded type during decoding that is syntactically invalid, d tries to discard the respective element so that decoding can continue. However, some errors are irrecoverable so that d is in an unsafe state where decoding more elements may yield invalid results.
This method indicates whether d is in a valid state and can decode more elements. This method does not indicate if there are more elements. In particular a return value of true does not guarantee that d.Next() does not return an error.
After d.Next() has returned an io.EOF error, this method will return false.
func (*Decoder) Next ¶
func (d *Decoder) Next() (Header, ElementReader, error)
Next parses the next element from d.
The returned ElementReader is valid until the next call to Next(). If the reader is not read to completion, any remaining bytes will be discarded when Next() is called. It is the responsibility of the caller to close the returned ElementReader in order to validate the syntax of any remaining bytes.
If no more elements are available, io.EOF is returned.
type ElementReader ¶
type ElementReader interface { // Constructed reports whether this ElementReader is reading a constructed or // primitive element. Constructed() bool // Next parses the next child element of a constructed element. If Next is // called for an element that uses the primitive encoding, an error is returned. // // The returned ElementReader is valid until the next call to Next(). If it is // not read to completion, any remaining bytes will be discarded when Next() is // called again. It is the responsibility of the caller to close the returned // ElementReader in order to validate the syntax of any remaining bytes. // // If no more elements are available, io.EOF is returned. Next() (Header, ElementReader, error) // only constructed // More reports whether the reader is in a valid state to decode more data. This // method does not indicate if reading the next element or byte will succeed. In // particular a return value of true does not guarantee that Next() or Read() // does not return an error. After Next() or Read() has returned an io.EOF // error, this method will return false. // // For primitive elements this is equivalent to Len() > 0. More() bool // Len returns the number of bytes remaining in the reader or -1 if its size is // unknown. Before Read(), ReadByte(), Close(), or Next() is called this returns // the indicated length of the element. If the element uses the indefinite // length encoding but a parent element uses a fixed length encoding, this // returns the number of remaining bytes in that parent. // // When used with constructed elements the result after calling Next() is // undefined until the returned element has been closed. Len() int // Close discards any remaining bytes in the reader. If a constructed format is // used, this will validate the BER structure of the remaining bytes. If the // remaining bytes are not a valid BER encoding, an error is returned. // // It is safe to call Close() multiple times, however subsequent calls may // return different errors or nil. Close() error io.Reader // only primitive io.ByteReader // only primitive }
ElementReader is a reader type for reading a BER-encoded element.
Elements can use the primitive or constructed encoding method. Depending on the encoding method only certain methods can be used. Reading methods of an ElementReader return io.EOF when the element is read to completion, although the underlying data source might have more bytes available. Before the element is read to completion, io.ErrUnexpectedEOF may be returned.
Closing an ElementReader is optional. Closing validates that the remaining bytes of a constructed element are valid BER-encoding.
type EncodeError ¶
EncodeError indicates that a value failed validation during encoding. Errors returned from a BerDecoder are wrapped in an EncodeError before they are returned from the Encoder.
func (*EncodeError) Error ¶
func (e *EncodeError) Error() string
func (*EncodeError) Unwrap ¶
func (e *EncodeError) Unwrap() error
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder implements encoding ASN.1 types into a BER-encoded data stream. It is the counterpart to the Decoder type.
To create a new Encoder, use the NewEncoder function.
func NewEncoder ¶
NewEncoder creates a new Encoder. Writing BER data requires single-byte writes. If w implements io.ByteWriter it is assumed to be efficient enough so no additional buffering is done. If w does not implement io.ByteWriter, writes to w will be buffered. The buffer will be flushed after writing an element in Encoder.Encode or Encoder.EncodeWithParams.
func (*Encoder) Encode ¶
Encode writes the BER-encoding of val to its underlying writer. If encoding fails, an error is returned. If a value fails validation before encoding, an EncodeError will be returned.
type Flag ¶
type Flag bool
A Flag accepts any data and is set to true if present. A flag cannot be encoded into BER. In most cases a Flag should be used on an optional element.
type Header ¶
Header represents the BER header of an encoded element. The Length of an element indicates the number of bytes that make up the contents of the element. Length can also be the special value LengthIndefinite if the element uses the constructed indefinite-length encoding. In that case Constructed must also be set to true.
type InvalidDecodeError ¶
InvalidDecodeError indicates that an invalid value was passed to an Unmarshal or Decode function. The invalid value might be nested within the passed value.
func (*InvalidDecodeError) Error ¶
func (e *InvalidDecodeError) Error() string
type RawValue ¶
A RawValue represents an un-decoded ASN.1 object. During decoding the syntax of structured elements is validated so the Bytes are guaranteed to contain a valid BER encoding. During encoding the bytes are written as-is without any validation.
type Sequence ¶
type Sequence struct { Tag asn1.Tag // defaults to [UNIVERSAL 16] // contains filtered or unexported fields }
Sequence is a type that simplifies the encoding of constructed BER elements. The zero value constitutes an empty sequence. If you want to implement a custom, constructed BerEncoder you can use a Sequence like this:
func (*myType) BerEncode() (asn1.Header, io.WriterTo, error) { s := &Sequence{ Tag: asn1.Tag{asn1.ClassApplication, 15} } s.Append("A String") s.Append(42) return s.BerEncode() }
Despite its name the Sequence type can be used to encode any constructed type, not just ASN.1 SEQUENCE types.
func SequenceOf ¶
SequenceOf returns a sequence containing the elements of the passed struct, slice, or array. If val is not a struct, slice, or array, or any if the values contained within val cannot be encoded, an error is returned.
func (*Sequence) Append ¶
Append adds an element at the end of the sequence. If the type of val does not permit encoding to BER an error of type UnsupportedTypeError is returned. In particular if the type of val is supported, no error will be returned. Validation is deferred to the BerEncode method.
func (*Sequence) AppendWithParams ¶
AppendWithParams adds an element at the end of the sequence. The format of params is the same as for struct tags documented in the documentation of this package. If the type of val does not permit encoding to BER an error of type UnsupportedTypeError is returned. In particular if the type of val is supported, no error will be returned. Validation is deferred to the BerEncode method.
func (*Sequence) BerEncode ¶
BerEncode encodes the sequence into the BER format. The length of the returned header is calculated as follows:
- If any of the sequence elements use the indefinite length format, the resulting length is also indefinite.
- If the sum of the lengths of the elements of s overflows the int type, the resulting length is indefinite.
- Otherwise the length is the sum of the lengths of the elements of s.
If encoding of any element fails, the error is returned by this method.
type StringReader ¶
type StringReader struct {
// contains filtered or unexported fields
}
StringReader implements reading of BER-encoded ASN.1 string types. String types can use the primitive or constructed encoding. When using the constructed encoding strings can be arbitrarily nested. StringReader understands both types of encodings and offers a flexible interface to read arbitrary string types.
A StringReader must be created via NewStringReader.
func NewStringReader ¶
func NewStringReader(tag asn1.Tag, r ElementReader) *StringReader
NewStringReader creates a new StringReader reading from r. r can be constructed or primitive. If r is constructed, every child element must use the class and tag identified by the specified tag.
func (*StringReader) Bytes ¶
func (r *StringReader) Bytes() ([]byte, error)
Bytes returns all unread bytes from r in a new byte slice. The returned slice may be retained by the caller. If a read error occurs, it is returned.
func (*StringReader) Constructed ¶
func (r *StringReader) Constructed() bool
Constructed indicates whether r is using the constructed or primitive encoding.
func (*StringReader) Read ¶
func (r *StringReader) Read(p []byte) (n int, err error)
Read reads the encoded string as a sequence of bytes. This method takes care of combining strings that use the constructed encoding. After the whole string has been read, io.EOF is returned.
func (*StringReader) ReadByte ¶
func (r *StringReader) ReadByte() (b byte, err error)
ReadByte complements Read by only reading a single byte form r.
func (*StringReader) String ¶
func (r *StringReader) String() (string, error)
String returns all unread bytes from r as a string.
func (*StringReader) Strings ¶
func (r *StringReader) Strings() iter.Seq2[ElementReader, error]
Strings returns a sequence of string elements that use the primitive encoding. The error will be nil for all elements of the sequence, except potentially the last one. The sequence ends when io.EOF is encountered. Note that there will be no sequence element with an io.EOF error.
If reading has already begun via Read or ReadByte, the sequence will only contain elements that are completely unread. Any primitive element that has been partially read is discarded.
type StructuralError ¶
A StructuralError suggests that the ASN.1 data is valid, but the Go type which is receiving it doesn't match or can't fit the data.
See also SyntaxError.
func (*StructuralError) Error ¶
func (e *StructuralError) Error() string
func (*StructuralError) Unwrap ¶
func (e *StructuralError) Unwrap() error
type SyntaxError ¶
A SyntaxError suggests that the ASN.1 data is invalid. This can either indicate that the nesting of structured elements contains an error, or that a primitive element could not be decoded from its BER representation.
For errors that are not directly related to the syntax of the BER byte stream, StructuralError is a better fit.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
func (*SyntaxError) Unwrap ¶
func (e *SyntaxError) Unwrap() error
type UnsupportedTypeError ¶
UnsupportedTypeError indicates that a value was passed to Marshal or an Encode function that cannot be encoded to BER.
func (*UnsupportedTypeError) Error ¶
func (e *UnsupportedTypeError) Error() string