fxamacker/cbor

GitHub: fxamacker/cbor

Stars: 1051 | Forks: 77

[fxamacker/cbor](https://github.com/fxamacker/cbor) is a library for encoding and decoding [CBOR](https://www.rfc-editor.org/info/std94) and [CBOR Sequences](https://www.rfc-editor.org/rfc/rfc8742.html). CBOR is a [trusted alternative](https://www.rfc-editor.org/rfc/rfc8949.html#name-comparison-of-other-binary-) to JSON, MessagePack, Protocol Buffers, etc.  CBOR is an Internet Standard defined by [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94) and is designed to be relevant for decades. `fxamacker/cbor` is used in projects by Arm Ltd., EdgeX Foundry, Flow Foundation, Fraunhofer‑AISEC, IBM, Kubernetes[*](https://github.com/search?q=org%3Akubernetes%20fxamacker%2Fcbor&type=code), Let's Encrypt, Linux Foundation, Microsoft, Oasis Protocol, Red Hat[*](https://github.com/search?q=org%3Aopenshift+fxamacker%2Fcbor&type=code), Tailscale[*](https://github.com/search?q=org%3Atailscale+fxamacker%2Fcbor&type=code), Veraison[*](https://github.com/search?q=org%3Averaison+fxamacker%2Fcbor&type=code), [etc](https://github.com/fxamacker/cbor#who-uses-fxamackercbor). See [Quick Start](#quick-start) and [Releases](https://github.com/fxamacker/cbor/releases/). 🆕 `UnmarshalFirst` and `DiagnoseFirst` can decode CBOR Sequences. `MarshalToBuffer` and `UserBufferEncMode` accepts user-specified buffer. ## fxamacker/cbor [![](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/b19f020695020256.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3Aci) [![](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/4fc60a20c7020257.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3A%22cover+%E2%89%A597%25%22) [![CodeQL](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/e5f489f3de020258.svg)](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml) [![](https://img.shields.io/badge/fuzzing-passing-44c010)](#fuzzing-and-code-coverage) [![Go Report Card](https://goreportcard.com/badge/github.com/fxamacker/cbor)](https://goreportcard.com/report/github.com/fxamacker/cbor) [![](https://img.shields.io/ossf-scorecard/github.com/fxamacker/cbor?label=openssf%20scorecard)](https://github.com/fxamacker/cbor#fuzzing-and-code-coverage) `fxamacker/cbor` is a CBOR codec in full conformance with [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94). It also supports CBOR Sequences ([RFC 8742](https://www.rfc-editor.org/rfc/rfc8742.html)) and Extended Diagnostic Notation ([Appendix G of RFC 8610](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G)). API is mostly same as `encoding/json`, plus interfaces that simplify concurrency and CBOR options. Design balances trade-offs between security, speed, concurrency, encoded data size, usability, etc.
🔎  Highlights

__🚀  Speed__ Encoding and decoding is fast without using Go's `unsafe` package. Slower settings are opt-in. Default limits allow very fast and memory efficient rejection of malformed CBOR data. __🔒  Security__ Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported. By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security). Codec passed multiple confidential security assessments in 2022. No vulnerabilities found in subset of codec in a [nonconfidential security assessment](https://github.com/veraison/go-cose/blob/v1.0.0-rc.1/reports/NCC_Microsoft-go-cose-Report_2022-05-26_v1.0.pdf) prepared by NCC Group for Microsoft Corporation. __🗜️  Data Size__ Struct tag options (`toarray`, `keyasint`, `omitempty`, `omitzero`) and field tag "-" automatically reduce size of encoded structs. Encoding optionally shrinks float64→32→16 when values fit. __:jigsaw:  Usability__ API is mostly same as `encoding/json` plus interfaces that simplify concurrency for CBOR options. Encoding and decoding modes can be created at startup and reused by any goroutines. Presets include Core Deterministic Encoding, Preferred Serialization, CTAP2 Canonical CBOR, etc. __📆  Extensibility__ Features include CBOR [extension points](https://www.rfc-editor.org/rfc/rfc8949.html#section-7.1) (e.g. CBOR tags) and extensive settings. API has interfaces that allow users to create custom encoding and decoding without modifying this library.


### Secure Decoding with Configurable Settings `fxamacker/cbor` has configurable limits, etc. that defend against malicious CBOR data. Notably, `fxamacker/cbor` is fast at rejecting malformed CBOR data. In contrast, some codecs can crash or use excessive resources while decoding bad data. ### Smaller Encodings with Struct Tag Options Struct tags automatically reduce encoded size of structs and improve speed. We can write less code by using struct tag options: - `toarray`: encode without field names (decode back to original struct) - `keyasint`: encode field names as integers (decode back to original struct) - `omitempty`: omit empty field when encoding - `omitzero`: omit zero-value field when encoding As a special case, struct field tag "-" omits the field. NOTE: When a struct uses `toarray`, the encoder will ignore `omitempty` and `omitzero` to prevent position of encoded array elements from changing. This allows decoder to match encoded elements to their Go struct field. ![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags") ## Quick Start __Install__: `go get github.com/fxamacker/cbor/v2` and `import "github.com/fxamacker/cbor/v2"`. ### Key Points This library can encode and decode CBOR (RFC 8949) and CBOR Sequences (RFC 8742). - __CBOR data item__ is a single piece of CBOR data and its structure may contain 0 or more nested data items. - __CBOR sequence__ is a concatenation of 0 or more encoded CBOR data items. Configurable limits and options can be used to balance trade-offs. - Encoding and decoding modes are created from options (settings). - Modes can be created at startup and reused. - Modes are safe for concurrent use. ### Default Mode Package level functions only use this library's default settings. They provide the "default mode" of encoding and decoding. // API matches encoding/json for Marshal, Unmarshal, Encode, Decode, etc. b, err = cbor.Marshal(v) // encode v to []byte b err = cbor.Unmarshal(b, &v) // decode []byte b to v decoder = cbor.NewDecoder(r) // create decoder with io.Reader r err = decoder.Decode(&v) // decode a CBOR data item to v // v2.7.0 added MarshalToBuffer() and UserBufferEncMode interface. err = cbor.MarshalToBuffer(v, b) // encode v to b instead of using built-in buf pool. // v2.5.0 added new functions that return remaining bytes. // UnmarshalFirst decodes first CBOR data item and returns remaining bytes. rest, err = cbor.UnmarshalFirst(b, &v) // decode []byte b to v // DiagnoseFirst translates first CBOR data item to text and returns remaining bytes. text, rest, err = cbor.DiagnoseFirst(b) // decode []byte b to Diagnostic Notation text // NOTE: Unmarshal() returns ExtraneousDataError if there are remaining bytes, but // UnmarshalFirst() and DiagnoseFirst() allow trailing bytes. ### Presets Presets can be used as-is or as a starting point for custom settings. // EncOptions is a struct of encoder settings. func CoreDetEncOptions() EncOptions // RFC 8949 Core Deterministic Encoding func PreferredUnsortedEncOptions() EncOptions // RFC 8949 Preferred Serialization func CanonicalEncOptions() EncOptions // RFC 7049 Canonical CBOR func CTAP2EncOptions() EncOptions // FIDO2 CTAP2 Canonical CBOR Presets are used to create custom modes. ### Custom Modes Modes are created from settings. Once created, modes have immutable settings. 💡 Create the mode at startup and reuse it. It is safe for concurrent use. // Create encoding mode. opts := cbor.CoreDetEncOptions() // use preset options as a starting point opts.Time = cbor.TimeUnix // change any settings if needed em, err := opts.EncMode() // create an immutable encoding mode // Reuse the encoding mode. It is safe for concurrent use. // API matches encoding/json. b, err := em.Marshal(v) // encode v to []byte b encoder := em.NewEncoder(w) // create encoder with io.Writer w err := encoder.Encode(v) // encode v to io.Writer w Default mode and custom modes automatically apply struct tags. ### User Specified Buffer for Encoding (v2.7.0) `UserBufferEncMode` interface extends `EncMode` interface to add `MarshalToBuffer()`. It accepts a user-specified buffer instead of using built-in buffer pool. em, err := myEncOptions.UserBufferEncMode() // create UserBufferEncMode mode var buf bytes.Buffer err = em.MarshalToBuffer(v, &buf) // encode v to provided buf ### Struct Tags Struct tag options (`toarray`, `keyasint`, `omitempty`, `omitzero`) reduce encoded size of structs. As a special case, struct field tag "-" omits the field.
🔎  Example encoding with struct field tag "-"

https://go.dev/play/p/aWEIFxd7InX // https://github.com/fxamacker/cbor/issues/652 package main import ( "encoding/json" "fmt" "github.com/fxamacker/cbor/v2" ) // The `cbor:"-"` tag omits the Type field when encoding to CBOR. type Entity struct { _ struct{} `cbor:",toarray"` ID uint64 `json:"id"` Type string `cbor:"-" json:"typeOf"` Name string `json:"name"` } func main() { entity := Entity{ ID: 1, Type: "int64", Name: "Identifier", } c, _ := cbor.Marshal(entity) diag, _ := cbor.Diagnose(c) fmt.Printf("CBOR in hex: %x\n", c) fmt.Printf("CBOR in edn: %s\n", diag) j, _ := json.Marshal(entity) fmt.Printf("JSON: %s\n", string(j)) fmt.Printf("JSON encoding is %d bytes\n", len(j)) fmt.Printf("CBOR encoding is %d bytes\n", len(c)) // Output: // CBOR in hex: 82016a4964656e746966696572 // CBOR in edn: [1, "Identifier"] // JSON: {"id":1,"typeOf":"int64","name":"Identifier"} // JSON encoding is 45 bytes // CBOR encoding is 13 bytes }

🔎  Example encoding 3-level nested Go struct to 1 byte CBOR

https://go.dev/play/p/YxwvfPdFQG2 // Example encoding nested struct (with omitempty tag) // - encoding/json: 18 byte JSON // - fxamacker/cbor: 1 byte CBOR package main import ( "encoding/hex" "encoding/json" "fmt" "github.com/fxamacker/cbor/v2" ) type GrandChild struct { Quux int `json:",omitempty"` } type Child struct { Baz int `json:",omitempty"` Qux GrandChild `json:",omitempty"` } type Parent struct { Foo Child `json:",omitempty"` Bar int `json:",omitempty"` } func cb() { results, _ := cbor.Marshal(Parent{}) fmt.Println("hex(CBOR): " + hex.EncodeToString(results)) text, _ := cbor.Diagnose(results) // Diagnostic Notation fmt.Println("DN: " + text) } func js() { results, _ := json.Marshal(Parent{}) fmt.Println("hex(JSON): " + hex.EncodeToString(results)) text := string(results) // JSON fmt.Println("JSON: " + text) } func main() { cb() fmt.Println("-------------") js() } Output (DN is Diagnostic Notation): hex(CBOR): a0 DN: {} ------------- hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d JSON: {"Foo":{"Qux":{}}}


🔎  Example using struct tag options

![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags")

Struct tag options simplify use of CBOR-based protocols that require CBOR arrays or maps with integer keys. ### CBOR Tags CBOR tags are specified in a `TagSet`. Custom modes can be created with a `TagSet` to handle CBOR tags. em, err := opts.EncMode() // no CBOR tags em, err := opts.EncModeWithTags(ts) // immutable CBOR tags em, err := opts.EncModeWithSharedTags(ts) // mutable shared CBOR tags `TagSet` and modes using it are safe for concurrent use. Equivalent API is available for `DecMode`.
🔎  Example using TagSet and TagOptions

// Use signedCWT struct defined in "Decoding CWT" example. // Create TagSet (safe for concurrency). tags := cbor.NewTagSet() // Register tag COSE_Sign1 18 with signedCWT type. tags.Add( cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, reflect.TypeOf(signedCWT{}), 18) // Create DecMode with immutable tags. dm, _ := cbor.DecOptions{}.DecModeWithTags(tags) // Unmarshal to signedCWT with tag support. var v signedCWT if err := dm.Unmarshal(data, &v); err != nil { return err } // Create EncMode with immutable tags. em, _ := cbor.EncOptions{}.EncModeWithTags(tags) // Marshal signedCWT with tag number. if data, err := em.Marshal(v); err != nil { return err }

👉 `fxamacker/cbor` allows user apps to use almost any current or future CBOR tag number by implementing `cbor.Marshaler` and `cbor.Unmarshaler` interfaces. Basically, `MarshalCBOR` and `UnmarshalCBOR` functions can be implemented by user apps and those functions will automatically be called by this CBOR codec's `Marshal`, `Unmarshal`, etc. The following [example](https://github.com/fxamacker/cbor/blob/master/example_embedded_json_tag_for_cbor_test.go) shows how to encode and decode a tagged CBOR data item with tag number 262. The tag content is a JSON object "embedded" as a CBOR byte string (major type 2).
🔎  Example using Embedded JSON Tag for CBOR (tag 262) // https://github.com/fxamacker/cbor/issues/657 package cbor_test // NOTE: RFC 8949 does not mention tag number 262. IANA assigned // CBOR tag number 262 as "Embedded JSON Object" specified by the // document Embedded JSON Tag for CBOR: // // "Tag 262 can be applied to a byte string (major type 2) to indicate // that the byte string is a JSON Object. The length of the byte string // indicates the content." // // For more info, see Embedded JSON Tag for CBOR at: // https://github.com/toravir/CBOR-Tag-Specs/blob/master/embeddedJSON.md import ( "bytes" "encoding/json" "fmt" "github.com/fxamacker/cbor/v2" ) // cborTagNumForEmbeddedJSON is the CBOR tag number 262. const cborTagNumForEmbeddedJSON = 262 // EmbeddedJSON represents a Go value to be encoded as a tagged CBOR data item // with tag number 262 and the tag content is a JSON object "embedded" as a // CBOR byte string (major type 2). type EmbeddedJSON struct { any } func NewEmbeddedJSON(val any) EmbeddedJSON { return EmbeddedJSON{val} } // MarshalCBOR encodes EmbeddedJSON to a tagged CBOR data item with the // tag number 262 and the tag content is a JSON object that is // "embedded" as a CBOR byte string. func (v EmbeddedJSON) MarshalCBOR() ([]byte, error) { // Encode v to JSON object. data, err := json.Marshal(v) if err != nil { return nil, err } // Create cbor.Tag representing a tagged CBOR data item. tag := cbor.Tag{ Number: cborTagNumForEmbeddedJSON, Content: data, } // Marshal to a tagged CBOR data item. return cbor.Marshal(tag) } // UnmarshalCBOR decodes a tagged CBOR data item to EmbeddedJSON. // The byte slice provided to this function must contain a single // tagged CBOR data item with the tag number 262 and tag content // must be a JSON object "embedded" as a CBOR byte string. func (v *EmbeddedJSON) UnmarshalCBOR(b []byte) error { // Unmarshal tagged CBOR data item. var tag cbor.Tag if err := cbor.Unmarshal(b, &tag); err != nil { return err } // Check tag number. if tag.Number != cborTagNumForEmbeddedJSON { return fmt.Errorf("got tag number %d, expect tag number %d", tag.Number, cborTagNumForEmbeddedJSON) } // Check tag content. jsonData, isByteString := tag.Content.([]byte) if !isByteString { return fmt.Errorf("got tag content type %T, expect tag content []byte", tag.Content) } // Unmarshal JSON object. return json.Unmarshal(jsonData, v) } // MarshalJSON encodes EmbeddedJSON to a JSON object. func (v EmbeddedJSON) MarshalJSON() ([]byte, error) { return json.Marshal(v.any) } // UnmarshalJSON decodes a JSON object. func (v *EmbeddedJSON) UnmarshalJSON(b []byte) error { dec := json.NewDecoder(bytes.NewReader(b)) dec.UseNumber() return dec.Decode(&v.any) } func Example_embeddedJSONTagForCBOR() { value := NewEmbeddedJSON(map[string]any{ "name": "gopher", "id": json.Number("42"), }) data, err := cbor.Marshal(value) if err != nil { panic(err) } fmt.Printf("cbor: %x\n", data) var v EmbeddedJSON err = cbor.Unmarshal(data, &v) if err != nil { panic(err) } fmt.Printf("%+v\n", v.any) for k, v := range v.any.(map[string]any) { fmt.Printf(" %s: %v (%T)\n", k, v, v) } }
### Functions and Interfaces
🔎  Functions and interfaces at a glance

Common functions with same API as `encoding/json`: - `Marshal`, `Unmarshal` - `NewEncoder`, `(*Encoder).Encode` - `NewDecoder`, `(*Decoder).Decode` NOTE: `Unmarshal` will return `ExtraneousDataError` if there are remaining bytes because RFC 8949 treats CBOR data item with remaining bytes as malformed. - 💡 Use `UnmarshalFirst` to decode first CBOR data item and return any remaining bytes. Other useful functions: - `Diagnose`, `DiagnoseFirst` produce human-readable [Extended Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G) from CBOR data. - `UnmarshalFirst` decodes first CBOR data item and return any remaining bytes. - `Wellformed` returns nil error if the CBOR data item is well-formed. Interfaces identical or comparable to Go `encoding` packages include: `Marshaler`, `Unmarshaler`, `BinaryMarshaler`, and `BinaryUnmarshaler`. The `RawMessage` type can be used to delay CBOR decoding or precompute CBOR encoding.

### Security Tips 🔒 Use Go's `io.LimitReader` to limit size when decoding very large or indefinite size data. Default limits may need to be increased for systems handling very large data (e.g. blockchains). `DecOptions` can be used to modify default limits for `MaxArrayElements`, `MaxMapPairs`, and `MaxNestedLevels`. ## Status v2.9.2 (Sunday, May 3, 2026) refactors and hardens the streaming encoder by adding stricter checks for encoding to CBOR indefinite-length data. This prevents improper use of this library from producing malformed CBOR indefinite-length data that would be rejected by the decoder. This release includes other bugfixes, defensive checks, and added more tests. v2.9.2 passed fuzz tests (billions of executions) and is production quality. For more details, see [v2.9.2 release notes](https://github.com/fxamacker/cbor/releases). ### Prior Releases Releases and commits tend to be on Sundays because my work schedule didn't leave time to work on this during weekdays (sometimes consecutive weekends and consecutive Christmas breaks, too). Monday morning releases were to allow more fuzzing to run overnight before clicking the release button. [v2.9.1](https://github.com/fxamacker/cbor/releases/tag/v2.9.1) (Monday, Mar 30, 2026) includes important bugfixes, defensive checks, improved code quality, and more tests. Although not public, the fuzzer was also improved by adding more fuzz tests. It passed fuzz tests (billions of executions) and is production quality. [v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Sunday, Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs. It passed fuzz tests (billions of executions) and is production quality. [v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0) (Sunday, March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality. [v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0) (Monday, June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality. [v2.6.0](https://github.com/fxamacker/cbor/releases/tag/v2.6.0) (Sunday, Feb 11, 2024) adds important new features, optimizations, and bug fixes. It is especially useful to systems that need to convert data between CBOR and JSON. New options and optimizations improve handling of bignum, integers, maps, and strings. [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Sunday, August 13, 2023) adds new features and important bug fixes. It is fuzz tested and production quality after extended beta [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023). __IMPORTANT__: 👉 Before upgrading from v2.4 or older release, please read the notable changes highlighted in the release notes. v2.5.0 is a large release with bug fixes to error handling for extraneous data in `Unmarshal`, etc. that should be reviewed before upgrading. See [v2.5.0 release notes](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) for list of new features, improvements, and bug fixes. See ["Version and API Changes"](https://github.com/fxamacker/cbor#versions-and-api-changes) section for more info about version numbering, etc.