Skip to content
CBOR library (in Go) designed to be easy, small, safe and reliable
Go
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore Initial commit May 15, 2019
.travis.yml
BENCHMARKS.md Improve decoding speed affected by commit 1a29187 Nov 7, 2019
CODE_OF_CONDUCT.md Create CODE_OF_CONDUCT.md Oct 27, 2019
CONTRIBUTING.md Update CONTRIBUTING.md Nov 11, 2019
LICENSE Initial commit May 15, 2019
README.md Update README.md Nov 12, 2019
bench_test.go
decode.go Improve encoding speed, reduce mem, refactor Nov 11, 2019
decode_test.go Improve encoding speed Nov 12, 2019
encode.go
encode_test.go Fix encoding struct with null ptr to embedded struct Nov 12, 2019
example_test.go
go.mod
stream.go Add RawMessage, Marshaler, and Unmarshaler Nov 1, 2019
stream_test.go Add RawMessage, Marshaler, and Unmarshaler Nov 1, 2019
structfields.go
valid.go Improve gocyclo score to 80% (was 70%) Oct 2, 2019

README.md

CBOR library big picture



CBOR library in Go

CBOR is a concise binary alternative to JSON, and is specified in RFC 7049.

This library makes encoding and decoding CBOR painless. There's practically no learning curve if you know encoding/json.

It's a great fit for a variety of projects. It’s small enough for IoT. And reliable enough for WebAuthn (FIDO2) servers. With extensive tests, fuzzing, and data validation, it avoids crashing on malicious CBOR data.

Install with go get github.com/fxamacker/cbor and use it like Go's encoding/json. It supports `json:"name"` keys!

Design Goals

This CBOR library is designed to be:

  • Easy – idiomatic API like encoding/json to reduce learning curve.
  • Small and self-contained – compiles to under 0.5 MB and has no external dependencies.
  • Safe and reliable – no unsafe pkg, coverage >95%, fuzz tested, data validation to prevent crashes on malformed or malicious data.

Competing factors are balanced:

  • Speed vs safety vs size – to keep size small, avoid code generation. For safety, validate data and avoid Go's unsafe package. For speed, use safe optimizations: cache struct metadata, bypass reflect when appropriate, use sync.Pool to reuse transient objects, and etc.
  • Standards compliance – support CBOR, including canonical CBOR encodings (RFC 7049 and CTAP2) with minor limitations. For example, negative numbers that can't fit into Go's int64 aren’t supported (like encoding/json.)

Faster CBOR libraries exist. Choose this one if you value your time, program size, and reliability. Avoiding crashes caused by malformed or malicious CBOR data means fewer headaches. See Fuzzing and Coverage.

Current Status

Version 1.x has:

  • Stable API – won't make breaking API changes.
  • Stable requirements – will always support Go v1.12.
  • Passed fuzzing – v1.2 passed 42+ hours of cbor-fuzz. See Fuzzing and Code Coverage.

Nov 05, 2019: v1.2 adds RawMessage type, Marshaler and Unmarshaler interfaces. Passed 42+ hrs of fuzzing.

🚀 Milestone v1.3 will improve speed, reduce memory use, and simplify decoding COSE data (RFC 8152).

Size Comparisons

Libraries and programs were compiled for linux_amd64 using Go 1.12.

alt text

Features

  • Idiomatic API like encoding/json.
  • Decode slices, maps, and structs in-place.
  • Decode into struct with field name case-insensitive match.
  • Support canonical CBOR encoding for map/struct.
  • Support both "cbor" and "json" keys for struct field format tags.
  • Encode anonymous struct fields by encoding/json package struct fields visibility rules.
  • Encode and decode nil slice/map/pointer/interface values correctly.
  • Encode and decode indefinite length bytes/string/array/map ("streaming").
  • Encode and decode time.Time as RFC 3339 formatted text string or Unix time.
  • v1.1 -- Support encoding.BinaryMarshaler and encoding.BinaryUnmarshaler interfaces.
  • v1.2 -- cbor.RawMessage can delay CBOR decoding or precompute CBOR encoding.
  • v1.2 -- User-defined types can have custom CBOR encoding and decoding by implementing cbor.Marshaler and cbor.Unmarshaler interfaces.

Fuzzing and Code Coverage

Each release passes coverage-guided fuzzing using fxamacker/cbor-fuzz. Default corpus has:

Unit tests include all RFC 7049 examples, bugs found by fuzzing, 2 maliciously crafted CBOR data, and etc.

Minimum code coverage is 95%. Minimum fuzzing is 10 hours for each release but often longer (v1.2 passed 42+ hours.)

Code coverage is 97.8% (go test -cover) for cbor v1.2 which is among the highest for libraries of this type.

Standards

This library implements CBOR as specified in RFC 7049, with minor limitations.

It also supports canonical CBOR encodings (both RFC 7049 and CTAP2). CTAP2 canonical CBOR encoding is used by CTAP and WebAuthn in FIDO2 framework.

Limitations

  • CBOR tags (type 6) are ignored. Decoder simply decodes tagged data after ignoring the tags.
  • CBOR negative int (type 1) that cannot fit into Go's int64 are not supported, such as RFC 7049 example -18446744073709551616. Decoding these values returns cbor.UnmarshalTypeError like Go's encoding/json.
  • CBOR Undefined (0xf7) value decodes to Go's nil value. Use CBOR Null (0xf6) to round-trip with Go's nil.

System Requirements

  • Go 1.12 (or newer)
  • Tested and fuzzed on linux_amd64, but it should work on other platforms.

Versions and API Changes

This project uses Semantic Versioning, so the API is always backwards compatible unless the major version number changes.

API

See API docs for more details.

package cbor // import "github.com/fxamacker/cbor"

func Marshal(v interface{}, encOpts EncOptions) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error
func Valid(data []byte) (rest []byte, err error)
type Decoder struct{ ... }
    func NewDecoder(r io.Reader) *Decoder
    func (dec *Decoder) Decode(v interface{}) (err error)
    func (dec *Decoder) NumBytesRead() int
type EncOptions struct{ ... }
type Encoder struct{ ... }
    func NewEncoder(w io.Writer, encOpts EncOptions) *Encoder
    func (enc *Encoder) Encode(v interface{}) error
    func (enc *Encoder) StartIndefiniteByteString() error
    func (enc *Encoder) StartIndefiniteTextString() error
    func (enc *Encoder) StartIndefiniteArray() error
    func (enc *Encoder) StartIndefiniteMap() error
    func (enc *Encoder) EndIndefinite() error
type InvalidUnmarshalError struct{ ... }
type Marshaler interface{ ... }
type RawMessage []byte
type SemanticError struct{ ... }
type SyntaxError struct{ ... }
type UnmarshalTypeError struct{ ... }
type Unmarshaler interface{ ... }
type UnsupportedTypeError struct{ ... }

Installation

go get github.com/fxamacker/cbor

Usage

See examples.

Decoding:

// create a decoder
dec := cbor.NewDecoder(reader)

// decode into empty interface
var i interface{}
err = dec.Decode(&i)

// decode into struct 
var stru ExampleStruct
err = dec.Decode(&stru)

// decode into map
var m map[string]string
err = dec.Decode(&m)

// decode into primitive
var f float32
err = dec.Decode(&f)

Encoding:

// create an encoder with canonical CBOR encoding enabled
enc := cbor.NewEncoder(writer, cbor.EncOptions{Canonical: true})

// encode struct
err = enc.Encode(stru)

// encode map
err = enc.Encode(m)

// encode primitive
err = enc.Encode(f)

Encoding indefinite length array:

enc := cbor.NewEncoder(writer, cbor.EncOptions{})

// start indefinite length array encoding
err = enc.StartIndefiniteArray()

// encode array element
err = enc.Encode(1)

// encode array element
err = enc.Encode([]int{2, 3})

// start nested indefinite length array as array element
err = enc.StartIndefiniteArray()

// encode nested array element
err = enc.Encode(4)

// encode nested array element
err = enc.Encode(5)

// end nested indefinite length array
err = enc.EndIndefinite()

// end indefinite length array
err = enc.EndIndefinite()

Benchmarks

Go structs are faster than maps:

  • decoding into struct is >66% faster than decoding into map.
  • encoding struct is >63% faster than encoding map.

See Benchmarks for fxamacker/cbor.

Code of Conduct

This project has adopted the Contributor Covenant Code of Conduct. Contact faye.github@gmail.com with any questions or comments.

Contributing

Please refer to How to Contribute.

Security Policy

For v1, security fixes are provided only for the latest released version since the API won't break compatibility.

To report security vulnerabilities, please email faye.github@gmail.com and allow time for the problem to be resolved before reporting it to the public.

Disclaimers

Phrases like "NO CRASHES" and "NO EXPLOITS" mean there are none known to the maintainer based on results of unit tests and fuzzing. It doesn't imply the software is perfect or 100% invulnerable to all known and unknown attacks.

Please read the license for additional disclaimers and terms.

License

Copyright (c) 2019 Faye Amacker

Licensed under MIT License

You can’t perform that action at this time.