bertlv

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2026 License: MIT Imports: 6 Imported by: 6

README

BER-TLV

Go Reference Go Report Card

Package bertlv implements encoding and decoding of BER-TLV structures using struct tags, similar to encoding/json.

go get github.com/skythen/bertlv

Struct Tags

Use the bertlv struct tag to map struct fields to BER-TLV tags.

Hex Format

Use the 0x prefix to specify tags as hex bytes. Class and construction are derived from the encoded tag bytes:

type FCI struct {
    AID       []byte   `bertlv:"0x4F"`
    Label     []byte   `bertlv:"0x50"`
    Track2    []byte   `bertlv:"0x57"`
    ExpDate   []byte   `bertlv:"0x5F24"`  // multi-byte tags
    Records   []Record `bertlv:"0x70"`    // constructed tags decode recursively
}
Decimal Format

Specify tag number and class explicitly:

"<number>,<class>[,options...]"

  • number: Decimal tag number (0-16383)
  • class: One of universal, application, context, private
type Data struct {
    Field1 []byte `bertlv:"1,universal"`
    Field2 []byte `bertlv:"2,application"`
    Field3 []byte `bertlv:"3,context"`
}
Options
  • omitempty - skip field during encoding if empty/zero
  • required - return error during decoding if tag is not present
type Data struct {
    Required []byte `bertlv:"0x4F,required"`
    Optional []byte `bertlv:"0x50,omitempty"`
    Both     []byte `bertlv:"1,universal,required,omitempty"`
}

Unmarshal

Decode BER-TLV data into a struct:

var result struct {
    AID   []byte `bertlv:"0x4F"`
    Label []byte `bertlv:"0x50"`
}

err := bertlv.Unmarshal(data, &result)
Options
opts := bertlv.Options{
    DisallowUnknownFields: true,
}

err := bertlv.UnmarshalWithOptions(data, &result, opts)
Custom Unmarshaler

Implement the Unmarshaler interface for custom decoding:

type MyType struct {
    Value string
}

func (m *MyType) UnmarshalBERTLV(value []byte) error {
    m.Value = string(value)
    return nil
}

Marshal

Encode a struct into BER-TLV format:

data := struct {
    AID   []byte `bertlv:"0x4F"`
    Label []byte `bertlv:"0x50"`
}{
    AID:   []byte{0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10},
    Label: "GoCard",
}

encoded, err := bertlv.Marshal(data)
Custom Marshaler

Implement the Marshaler interface for custom encoding:

func (m MyType) MarshalBERTLV() ([]byte, error) {
    return []byte(m.Value), nil
}

Supported Types

The following Go types can be used as struct fields:

  • []byte - raw TLV value
  • string - UTF-8 encoded value
  • int, int8, int16, int32, int64 - big-endian signed integers
  • uint, uint8, uint16, uint32, uint64 - big-endian unsigned integers
  • bool - single byte (0x00 = false, non-zero = true)
  • struct - nested constructed TLV
  • []T (slice of structs) - repeated TLV elements

Documentation

Index

Examples

Constants

View Source
const MaxTagNumber = 0x3FFF

MaxTagNumber is the maximum allowed tag number (14 bits)

Variables

This section is empty.

Functions

func Marshal added in v0.2.0

func Marshal(v interface{}) ([]byte, error)

Marshal returns the BER-TLV encoding of v.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	data := struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}{
		AID:   []byte{0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10},
		Label: "GoCard",
	}

	encoded, err := bertlv.Marshal(data)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%x\n", encoded)
}
Output:
4f07a00000000410105006476f43617264

func MarshalWithOptions added in v0.2.0

func MarshalWithOptions(v interface{}, opts Options) ([]byte, error)

MarshalWithOptions returns the BER-TLV encoding of v with custom options.

func MarshalWithTag added in v0.2.0

func MarshalWithTag(v interface{}, tagStr string) ([]byte, error)

MarshalWithTag returns the BER-TLV encoding of v wrapped in a TLV with the given tag.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	data := struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}{
		AID:   []byte{0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10},
		Label: "GoCard",
	}

	// Wrap the struct in a constructed TLV with tag 0x6F (FCI Template)
	encoded, err := bertlv.MarshalWithTag(data, "0x6F")
	if err != nil {
		panic(err)
	}

	fmt.Printf("%x\n", encoded)
}
Output:
6f114f07a00000000410105006476f43617264

func MarshalWithTagAndOptions added in v0.2.0

func MarshalWithTagAndOptions(v interface{}, tagStr string, opts Options) ([]byte, error)

MarshalWithTagAndOptions returns the BER-TLV encoding of v wrapped in a TLV with the given tag and custom options.

func Unmarshal added in v0.2.0

func Unmarshal(data []byte, v interface{}) error

Unmarshal parses the BER-TLV-encoded data and stores the result in the value pointed to by v. If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	raw := []byte{
		0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10,
		0x50, 0x06, 0x47, 0x6F, 0x43, 0x61, 0x72, 0x64,
	}

	var result struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}

	if err := bertlv.Unmarshal(raw, &result); err != nil {
		panic(err)
	}

	fmt.Printf("AID: %x\n", result.AID)
	fmt.Printf("Label: %s\n", result.Label)
}
Output:
AID: a0000000041010
Label: GoCard

func UnmarshalWithOptions added in v0.2.0

func UnmarshalWithOptions(data []byte, v interface{}, opts Options) error

UnmarshalWithOptions parses the BER-TLV-encoded data with custom options and stores the result in the value pointed to by v.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	raw := []byte{
		0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10,
		0x50, 0x06, 0x47, 0x6F, 0x43, 0x61, 0x72, 0x64,
		0x01, 0x01, 0xFF, // unknown tag
	}

	var result struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}

	opts := bertlv.Options{
		DisallowUnknownFields: true,
	}

	err := bertlv.UnmarshalWithOptions(raw, &result, opts)
	fmt.Println(err)
}
Output:
bertlv: unknown tag [Universal Primitive 1] at offset 17

func UnmarshalWithTag added in v0.2.0

func UnmarshalWithTag(data []byte, v interface{}, tagStr string) error

UnmarshalWithTag unmarshals data expecting a specific tag

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	// Data wrapped in a constructed TLV with tag 0x6F (FCI Template)
	raw := []byte{
		0x6F, 0x11,
		0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10,
		0x50, 0x06, 0x47, 0x6F, 0x43, 0x61, 0x72, 0x64,
	}

	var result struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}

	if err := bertlv.UnmarshalWithTag(raw, &result, "0x6F"); err != nil {
		panic(err)
	}

	fmt.Printf("AID: %x\n", result.AID)
	fmt.Printf("Label: %s\n", result.Label)
}
Output:
AID: a0000000041010
Label: GoCard

func UnmarshalWithTagAndOptions added in v0.2.0

func UnmarshalWithTagAndOptions(data []byte, v interface{}, tagStr string, opts Options) error

UnmarshalWithTagAndOptions unmarshals data with specific tag and options

Types

type Class added in v0.1.2

type Class byte

Class represents the tag class in BER-TLV encoding. The four classes are Universal, Application, Context-specific, and Private.

const (
	// Universal class for types defined in the standard
	Universal Class = 0x00
	// Application class for application-specific types
	Application Class = 0x40
	// ContextSpecific class for context-specific types within a constructed type
	ContextSpecific Class = 0x80
	// Private class for private use
	Private Class = 0xC0
)

type DecodeError added in v0.2.0

type DecodeError struct {
	Offset  int
	Field   string
	Type    reflect.Type
	Message string
}

DecodeError represents an error that occurred during BER-TLV decoding.

func (*DecodeError) Error added in v0.2.0

func (e *DecodeError) Error() string

Error implements the error interface for DecodeError.

type Decoder added in v0.2.0

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder represents the state while decoding a BER-TLV value.

func NewDecoder added in v0.2.0

func NewDecoder(data []byte) *Decoder

NewDecoder creates a new decoder for the given data.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	raw := []byte{
		0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10,
		0x50, 0x06, 0x47, 0x6F, 0x43, 0x61, 0x72, 0x64,
	}

	var result struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}

	d := bertlv.NewDecoder(raw)
	if err := d.Decode(&result); err != nil {
		panic(err)
	}

	fmt.Printf("AID: %x\n", result.AID)
	fmt.Printf("Label: %s\n", result.Label)
}
Output:
AID: a0000000041010
Label: GoCard

func NewDecoderWithOptions added in v0.2.0

func NewDecoderWithOptions(data []byte, opts Options) *Decoder

NewDecoderWithOptions creates a new decoder with custom options.

func (*Decoder) Decode added in v0.2.0

func (d *Decoder) Decode(v interface{}) error

Decode decodes the BER-TLV data into v.

func (*Decoder) DecodeWithTag added in v0.2.0

func (d *Decoder) DecodeWithTag(v interface{}, expectedTag TagInfo) error

DecodeWithTag decodes a single TLV element, verifying that its tag matches expectedTag, and stores the result in the value pointed to by v.

type EncodeError added in v0.2.0

type EncodeError struct {
	Type    reflect.Type
	Field   string
	Message string
}

EncodeError represents an error that occurred during BER-TLV encoding.

func (*EncodeError) Error added in v0.2.0

func (e *EncodeError) Error() string

Error implements the error interface for EncodeError.

type Encoder added in v0.2.0

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder handles BER-TLV encoding with configurable options.

func NewEncoder added in v0.2.0

func NewEncoder() *Encoder

NewEncoder creates a new encoder with default options.

Example
package main

import (
	"fmt"

	"github.com/skythen/bertlv"
)

func main() {
	e := bertlv.NewEncoder()

	data := struct {
		AID   []byte `bertlv:"0x4F"`
		Label string `bertlv:"0x50"`
	}{
		AID:   []byte{0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10},
		Label: "GoCard",
	}

	if err := e.Encode(data); err != nil {
		panic(err)
	}

	fmt.Printf("%x\n", e.Bytes())
}
Output:
4f07a00000000410105006476f43617264

func NewEncoderWithOptions added in v0.2.0

func NewEncoderWithOptions(opts Options) *Encoder

NewEncoderWithOptions creates a new encoder with custom options.

func (*Encoder) Bytes added in v0.2.0

func (e *Encoder) Bytes() []byte

Bytes returns the encoded bytes.

func (*Encoder) Encode added in v0.2.0

func (e *Encoder) Encode(v interface{}) error

Encode encodes v into BER-TLV format.

func (*Encoder) EncodeWithTag added in v0.2.0

func (e *Encoder) EncodeWithTag(v interface{}, tagInfo TagInfo) error

EncodeWithTag encodes v into BER-TLV format wrapped in a TLV with the given tag.

type InvalidUnmarshalError added in v0.2.0

type InvalidUnmarshalError struct {
	Type reflect.Type
}

InvalidUnmarshalError describes an invalid argument passed to Unmarshal.

func (*InvalidUnmarshalError) Error added in v0.2.0

func (e *InvalidUnmarshalError) Error() string

Error implements the error interface for InvalidUnmarshalError.

type Length added in v0.2.0

type Length uint32

Length represents the length component in a BER-TLV structure.

type Marshaler added in v0.2.0

type Marshaler interface {
	MarshalBERTLV() ([]byte, error)
}

Marshaler is the interface implemented by types that can marshal themselves into a valid BER-TLV value.

type MissingRequiredFieldError added in v0.2.0

type MissingRequiredFieldError struct {
	Field string
	Tag   TagInfo
}

MissingRequiredFieldError describes that field that was marked as required wasn't encountered in the BER-TLV data.

func (*MissingRequiredFieldError) Error added in v0.2.0

func (e *MissingRequiredFieldError) Error() string

Error implements the error interface for MissingRequiredFieldError.

type Options added in v0.2.0

type Options struct {
	// DisallowUnknownFields causes decoding to fail when encountering unknown tags
	DisallowUnknownFields bool
}

Options configures the behavior of encoding and decoding operations.

func DefaultOptions added in v0.2.0

func DefaultOptions() Options

DefaultOptions returns the default options for encoding/decoding.

type Tag added in v0.2.0

type Tag uint32

Tag represents a BER-TLV tag identifier. It combines class, construction, and tag number according to ITU-T X.690.

type TagInfo added in v0.2.0

type TagInfo struct {
	Class       Class
	Constructed bool
	Number      uint16
}

TagInfo holds complete metadata about a BER-TLV tag.

func (TagInfo) String added in v0.2.0

func (t TagInfo) String() string

String returns a human-readable representation of the tag.

type UnknownFieldError added in v0.2.0

type UnknownFieldError struct {
	Tag    TagInfo
	Offset int
}

UnknownFieldError is returned when an unknown tag is encountered with DisallowUnknownFields.

func (*UnknownFieldError) Error added in v0.2.0

func (e *UnknownFieldError) Error() string

Error implements the error interface for UnknownFieldError.

type UnmarshalTypeError added in v0.2.0

type UnmarshalTypeError struct {
	Value  string       // description of BER-TLV value
	Type   reflect.Type // type of Go value it could not be assigned to
	Offset int64        // error occurred after reading Offset bytes
	Struct string       // name of the struct type containing the field
	Field  string       // name of the field holding the Go value
}

UnmarshalTypeError describes a BER-TLV value that was not appropriate for a value of a specific Go type.

func (*UnmarshalTypeError) Error added in v0.2.0

func (e *UnmarshalTypeError) Error() string

Error implements the error interface for UnmarshalTypeError.

type Unmarshaler added in v0.2.0

type Unmarshaler interface {
	UnmarshalBERTLV(value []byte) error
}

Unmarshaler is the interface implemented by types that can unmarshal a BER-TLV value of themselves. The input is the value of a BER-TLV.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL