Skip to content
Faye Amacker edited this page Jun 24, 2021 · 3 revisions

What is CBOR?

CBOR is a concise binary data format inspired by JSON and MessagePack. CBOR is defined in RFC 8949 (December 2020) which obsoletes RFC 7049 (October 2013).

CBOR is an Internet Standard by IETF and is used to define other standards. It is used in WebAuthn by W3CCOSE (RFC 8152)CWT (RFC 8392)CDDL (RFC 8610) and more.

CBOR is a self-describing format, CBOR doesn't require schemas or code generation. CBOR specifies and "recommends" Preferred Serialization, which encodes data to the fewest number of bytes. It also specifies Core Deterministic Encoding, which requires Preferred Serialization and deprecates Canonical CBOR.

What is fxamacker/cbor?

fxamacker/cbor is a CBOR codec written in Go. It has an API often identical to Go's built-in encoding/json which makes it easy to use.

fxamacker/cbor is used by Berlin Institute of Health at Charité, Chainlink, ConsenSys, Dapper Labs, Duo Labs (cisco), and others to handle CBOR data. It has been fuzz-tested since before release 1.0.

Can CBOR replace JSON?

JSON's generic data model is a subset of CBOR's generic data model. This allows CBOR to replace JSON. CBOR typically achieves smaller encoded data size and faster speed.

For more info about reducing encoded data size, see "Using CBOR in New Protocols" below.

To further reduce encoded data size, you can use ZStandard with a custom dictionary created from your data (PDF at fnal.gov) for best results.

Using CBOR in New Protocols

It is the responsibility of protocol designers to specify precisely how they want CBOR to be encoded and what to allow during decoding.

There are many valid encodings allowed in CBOR RFC 8949. Different CBOR encoders can produce different results while still being compatible with generic decoders.

For example, fxamacker/cbor options for encoding time to CBOR are: TimeUnix, TimeUnixMicro, TimeUnixDynamic, TimeRFC3339, and TimeRFC3339Nano.

Preferred Serialization (specified in RFC 8949 in Dec 2020) is a good starting point for specifying CBOR encoding settings for new protocols. Core Deterministic Encoding is another good starting point that is slightly slower because map keys are sorted.

To improve speed and reduce data size, CBOR Array is preferred over CBOR Map when feasible. If a CBOR Map is required, then integer keys are preferred over string keys.

Using arrays can be tedious and error-prone compared to using Go structs. fxamacker/cbor has toarray, keyasint and omitempty struct tags to automate the translation of a Go struct into/from a CBOR Array. This can greatly reduce encoded data size and improve speed.

Go Struct Tags

CBOR Security Considerations

Users of serialization (not just CBOR) need to be familiar with security considerations. CBOR security considerations are well-documented in CBOR RFC 8949.

fxamacker/cbor allows users to specify various max limits and other options. These include: MaxNestedLevels, MaxArrayElements, MaxMapPairs, and IndefLength.

The option to detect and reject duplicate map keys should be used in security-sensitive protocols. This security feature slows down decoding and is often missing in CBOR codecs.

When decoding CBOR data (especially from untrusted sources), Go's io.LimitReader should be used with an appropriate size limit to help prevent denial-of-service attacks.

If the size of the entire encoded CBOR "message" is known, it may be useful to wrap that encoded message inside a CBOR byte string, because the CBOR byte string includes size in its header. CBOR Tag 24 (Encoded Data Item) and CBOR Tag 55799 (Self-Described CBOR) may also be useful. fxamacker/cbor has built-in support for CBOR Tag 55799.

To securely transport CBOR data, consider using a secure channel such as TLS 1.2 or TLS 1.3 with AEAD+PFS ciphers. Limiting cipher suites to AEAD+PFS can prevent downgrade attacks. Ask a security expert for current best practices for handling potentially malicious data or preserving secrecy.