crypto: golang.org/x/crypto/cryptobyte Index | Examples | Files | Directories

package cryptobyte

import "golang.org/x/crypto/cryptobyte"

Package cryptobyte contains types that help with parsing and constructing length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage contains useful ASN.1 constants.)

The String type is for parsing. It wraps a []byte slice and provides helper functions for consuming structures, value by value.

The Builder type is for constructing messages. It providers helper functions for appending values and also for appending length-prefixed submessages – without having to worry about calculating the length prefix ahead of time.

See the documentation and examples for the Builder and String types to get started.

Index

Examples

Package Files

asn1.go builder.go string.go

type BuildError Uses

type BuildError struct {
    Err error
}

BuildError wraps an error. If a BuilderContinuation panics with this value, the panic will be recovered and the inner error will be returned from Builder.Bytes.

type Builder Uses

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

A Builder builds byte strings from fixed-length and length-prefixed values. Builders either allocate space as needed, or are ‘fixed’, which means that they write into a given buffer and produce an error if it's exhausted.

The zero value is a usable Builder that allocates space as needed.

Simple values are marshaled and appended to a Builder using methods on the Builder. Length-prefixed values are marshaled by providing a BuilderContinuation, which is a function that writes the inner contents of the value to a given Builder. See the documentation for BuilderContinuation for details.

Code:

// This is an example of building ASN.1 data that looks like:
//    Foo ::= SEQUENCE {
//      version [6] INTEGER DEFAULT 0
//      data OCTET STRING
//    }

version := int64(2)
data := []byte("hello")
const defaultVersion = 0

var b cryptobyte.Builder
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
    if version != defaultVersion {
        b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) {
            b.AddASN1Int64(version)
        })
    }
    b.AddASN1OctetString(data)
})

result, err := b.Bytes()
if err != nil {
    panic(err)
}

Output:

300ca603020102040568656c6c6f

Code:

// Writing more data that can be expressed by the length prefix results
// in an error from Bytes().

tooLarge := make([]byte, 256)

var b cryptobyte.Builder
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
    b.AddBytes(tooLarge)
})

result, err := b.Bytes()
fmt.Printf("len=%d err=%s\n", len(result), err)

Output:

len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix

Code:

// This is an example of building length-prefixed data (as found in,
// for example, TLS). Imagine a 16-bit prefixed series of 8-bit
// prefixed strings.
input := []string{"hello", "world"}

var b cryptobyte.Builder
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
    for _, value := range input {
        b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
            b.AddBytes([]byte(value))
        })
    }
})

result, err := b.Bytes()
if err != nil {
    panic(err)
}

Output:

000c0568656c6c6f05776f726c64

func NewBuilder Uses

func NewBuilder(buffer []byte) *Builder

NewBuilder creates a Builder that appends its output to the given buffer. Like append(), the slice will be reallocated if its capacity is exceeded. Use Bytes to get the final buffer.

func NewFixedBuilder Uses

func NewFixedBuilder(buffer []byte) *Builder

NewFixedBuilder creates a Builder that appends its output into the given buffer. This builder does not reallocate the output buffer. Writes that would exceed the buffer's capacity are treated as an error.

func (*Builder) AddASN1 Uses

func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation)

AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. Tags greater than 30 are not supported and result in an error (i.e. low-tag-number form only). The child builder passed to the BuilderContinuation can be used to build the content of the ASN.1 object.

func (*Builder) AddASN1BigInt Uses

func (b *Builder) AddASN1BigInt(n *big.Int)

AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.

func (*Builder) AddASN1BitString Uses

func (b *Builder) AddASN1BitString(data []byte)

AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not support BIT STRINGs that are not a whole number of bytes.

func (*Builder) AddASN1Boolean Uses

func (b *Builder) AddASN1Boolean(v bool)

func (*Builder) AddASN1Enum Uses

func (b *Builder) AddASN1Enum(v int64)

AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.

func (*Builder) AddASN1GeneralizedTime Uses

func (b *Builder) AddASN1GeneralizedTime(t time.Time)

AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.

func (*Builder) AddASN1Int64 Uses

func (b *Builder) AddASN1Int64(v int64)

AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.

func (*Builder) AddASN1NULL Uses

func (b *Builder) AddASN1NULL()

func (*Builder) AddASN1ObjectIdentifier Uses

func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier)

func (*Builder) AddASN1OctetString Uses

func (b *Builder) AddASN1OctetString(bytes []byte)

AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.

func (*Builder) AddASN1Uint64 Uses

func (b *Builder) AddASN1Uint64(v uint64)

AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.

func (*Builder) AddBytes Uses

func (b *Builder) AddBytes(v []byte)

AddBytes appends a sequence of bytes to the byte string.

func (*Builder) AddUint16 Uses

func (b *Builder) AddUint16(v uint16)

AddUint16 appends a big-endian, 16-bit value to the byte string.

func (*Builder) AddUint16LengthPrefixed Uses

func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation)

AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.

func (*Builder) AddUint24 Uses

func (b *Builder) AddUint24(v uint32)

AddUint24 appends a big-endian, 24-bit value to the byte string. The highest byte of the 32-bit input value is silently truncated.

func (*Builder) AddUint24LengthPrefixed Uses

func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation)

AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.

func (*Builder) AddUint32 Uses

func (b *Builder) AddUint32(v uint32)

AddUint32 appends a big-endian, 32-bit value to the byte string.

func (*Builder) AddUint32LengthPrefixed Uses

func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation)

AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.

func (*Builder) AddUint8 Uses

func (b *Builder) AddUint8(v uint8)

AddUint8 appends an 8-bit value to the byte string.

func (*Builder) AddUint8LengthPrefixed Uses

func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation)

AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.

func (*Builder) AddValue Uses

func (b *Builder) AddValue(v MarshalingValue)

AddValue calls Marshal on v, passing a pointer to the builder to append to. If Marshal returns an error, it is set on the Builder so that subsequent appends don't have an effect.

func (*Builder) Bytes Uses

func (b *Builder) Bytes() ([]byte, error)

Bytes returns the bytes written by the builder or an error if one has occurred during during building.

func (*Builder) BytesOrPanic Uses

func (b *Builder) BytesOrPanic() []byte

BytesOrPanic returns the bytes written by the builder or panics if an error has occurred during building.

func (*Builder) MarshalASN1 Uses

func (b *Builder) MarshalASN1(v interface{})

MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if successful or records an error if one occurred.

type BuilderContinuation Uses

type BuilderContinuation func(child *Builder)

BuilderContinuation is continuation-passing interface for building length-prefixed byte sequences. Builder methods for length-prefixed sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation supplied to them. The child builder passed to the continuation can be used to build the content of the length-prefixed sequence. For example:

parent := cryptobyte.NewBuilder()
parent.AddUint8LengthPrefixed(func (child *Builder) {
  child.AddUint8(42)
  child.AddUint8LengthPrefixed(func (grandchild *Builder) {
    grandchild.AddUint8(5)
  })
})

It is an error to write more bytes to the child than allowed by the reserved length prefix. After the continuation returns, the child must be considered invalid, i.e. users must not store any copies or references of the child that outlive the continuation.

If the continuation panics with a value of type BuildError then the inner error will be returned as the error from Bytes. If the child panics otherwise then Bytes will repanic with the same value.

Code:

var b cryptobyte.Builder
// Continuations that panic with a BuildError will cause Bytes to
// return the inner error.
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
    b.AddUint32(0)
    panic(cryptobyte.BuildError{Err: errors.New("example error")})
})

result, err := b.Bytes()
fmt.Printf("len=%d err=%s\n", len(result), err)

Output:

len=0 err=example error

type MarshalingValue Uses

type MarshalingValue interface {
    // Marshal is called by Builder.AddValue. It receives a pointer to a builder
    // to marshal itself into. It may return an error that occurred during
    // marshaling, such as unset or invalid values.
    Marshal(b *Builder) error
}

A MarshalingValue marshals itself into a Builder.

type String Uses

type String []byte

String represents a string of bytes. It provides methods for parsing fixed-length and length-prefixed values from it.

Code:

// This is an example of parsing ASN.1 data that looks like:
//    Foo ::= SEQUENCE {
//      version [6] INTEGER DEFAULT 0
//      data OCTET STRING
//    }

input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'})

var (
    version                   int64
    data, inner, versionBytes cryptobyte.String
    haveVersion               bool
)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
    !input.Empty() ||
    !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) ||
    (haveVersion && !versionBytes.ReadASN1Integer(&version)) ||
    (haveVersion && !versionBytes.Empty()) ||
    !inner.ReadASN1(&data, asn1.OCTET_STRING) ||
    !inner.Empty() {
    panic("bad format")
}

Output:

haveVersion: true, version: 2, data: hello

Code:

// This is an example of parsing length-prefixed data (as found in, for
// example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed
// strings.

input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'})
var result []string

var values cryptobyte.String
if !input.ReadUint16LengthPrefixed(&values) ||
    !input.Empty() {
    panic("bad format")
}

for !values.Empty() {
    var value cryptobyte.String
    if !values.ReadUint8LengthPrefixed(&value) {
        panic("bad format")
    }

    result = append(result, string(value))
}

Output:

[]string{"hello", "world"}

func (*String) CopyBytes Uses

func (s *String) CopyBytes(out []byte) bool

CopyBytes copies len(out) bytes into out and advances over them. It returns true on success and false on error.

func (String) Empty Uses

func (s String) Empty() bool

Empty reports whether the string does not contain any bytes.

func (String) PeekASN1Tag Uses

func (s String) PeekASN1Tag(tag asn1.Tag) bool

PeekASN1Tag returns true if the next ASN.1 value on the string starts with the given tag.

func (*String) ReadASN1 Uses

func (s *String) ReadASN1(out *String, tag asn1.Tag) bool

ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, and advances. The element must match the given tag. It returns true on success and false on error.

Tags greater than 30 are not supported (i.e. low-tag-number format only).

func (*String) ReadASN1BitString Uses

func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool

ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It returns true on success and false on error.

func (*String) ReadASN1BitStringAsBytes Uses

func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool

ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is an error if the BIT STRING is not a whole number of bytes. This function returns true on success and false on error.

func (*String) ReadASN1Boolean Uses

func (s *String) ReadASN1Boolean(out *bool) bool

func (*String) ReadASN1Bytes Uses

func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool

ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, and advances. The element must match the given tag. It returns true on success and false on error.

func (*String) ReadASN1Element Uses

func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool

ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including tag and length bytes) into out, and advances. The element must match the given tag. It returns true on success and false on error.

Tags greater than 30 are not supported (i.e. low-tag-number format only).

func (*String) ReadASN1Enum Uses

func (s *String) ReadASN1Enum(out *int) bool

ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns true on success and false on error.

func (*String) ReadASN1GeneralizedTime Uses

func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool

ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and advances. It returns true on success and false on error.

func (*String) ReadASN1Integer Uses

func (s *String) ReadASN1Integer(out interface{}) bool

ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does not point to an integer or to a big.Int, it panics. It returns true on success and false on error.

func (*String) ReadASN1ObjectIdentifier Uses

func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool

ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and advances. It returns true on success and false on error.

func (*String) ReadAnyASN1 Uses

func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool

ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, sets outTag to its tag, and advances. It returns true on success and false on error.

Tags greater than 30 are not supported (i.e. low-tag-number format only).

func (*String) ReadAnyASN1Element Uses

func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool

ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element (including tag and length bytes) into out, sets outTag to is tag, and advances. It returns true on success and false on error.

Tags greater than 30 are not supported (i.e. low-tag-number format only).

func (*String) ReadBytes Uses

func (s *String) ReadBytes(out *[]byte, n int) bool

ReadBytes reads n bytes into out and advances over them. It returns true on success and false and error.

func (*String) ReadOptionalASN1 Uses

func (s *String) ReadOptionalASN1(out *String, outPresent *bool, tag asn1.Tag) bool

ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1 element (not including tag and length bytes) tagged with the given tag into out. It stores whether an element with the tag was found in outPresent, unless outPresent is nil. It returns true on success and false on error.

func (*String) ReadOptionalASN1Boolean Uses

func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool

ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or, if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.

func (*String) ReadOptionalASN1Integer Uses

func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool

ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly tagged with tag into out and advances. If no element with a matching tag is present, it writes defaultValue into out instead. If out does not point to an integer or to a big.Int, it panics. It returns true on success and false on error.

func (*String) ReadOptionalASN1OctetString Uses

func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag asn1.Tag) bool

ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING explicitly tagged with tag into out and advances. If no element with a matching tag is present, it writes defaultValue into out instead. It returns true on success and false on error.

func (*String) ReadUint16 Uses

func (s *String) ReadUint16(out *uint16) bool

ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint16LengthPrefixed Uses

func (s *String) ReadUint16LengthPrefixed(out *String) bool

ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit length-prefixed value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint24 Uses

func (s *String) ReadUint24(out *uint32) bool

ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint24LengthPrefixed Uses

func (s *String) ReadUint24LengthPrefixed(out *String) bool

ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit length-prefixed value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint32 Uses

func (s *String) ReadUint32(out *uint32) bool

ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint8 Uses

func (s *String) ReadUint8(out *uint8) bool

ReadUint8 decodes an 8-bit value into out and advances over it. It returns true on success and false on error.

func (*String) ReadUint8LengthPrefixed Uses

func (s *String) ReadUint8LengthPrefixed(out *String) bool

ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value into out and advances over it. It returns true on success and false on error.

func (*String) Skip Uses

func (s *String) Skip(n int) bool

Skip advances the String by n byte and reports whether it was successful.

func (*String) SkipASN1 Uses

func (s *String) SkipASN1(tag asn1.Tag) bool

SkipASN1 reads and discards an ASN.1 element with the given tag.

func (*String) SkipOptionalASN1 Uses

func (s *String) SkipOptionalASN1(tag asn1.Tag) bool

SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or else leaves s unchanged.

Directories

PathSynopsis
asn1Package asn1 contains supporting types for parsing and building ASN.1 messages with the cryptobyte package.

Package cryptobyte imports 7 packages (graph). Updated 2017-10-19. Refresh now. Tools for package owners.