The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

zucbor

R-CMD-check coverage

zucbor encodes and decodes CBOR (RFC 8949), the binary counterpart of JSON, to and from ordinary R vectors and lists. It is built for input you do not trust — COSE and CWT tokens, WebAuthn passkey data, CoAP device telemetry — and for output that must be byte-exact.

Installation

install.packages("zucbor")

# or the development version:
# install.packages("pak")
pak::pak("pedrobtz/zucbor")

Building from source needs a C compiler; with GCC, version 11 or newer (older GCC rejects a construct in the bundled TinyCBOR 7.0).

Decoding

library(zucbor)

cbor_decode(as.raw(c(0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03)))
#> $a
#> [1] 1
#>
#> $b
#> [1] 2 3

A map whose keys are not all text — a COSE header, say — is a cbor_map, never a list with the keys quietly turned into names:

cbor_decode(as.raw(c(0xa2, 0x01, 0x26, 0x04, 0x42, 0x31, 0x31)))
#> <cbor_map: 2 entries>
#> [[1]]
#> [1] -7
#> [[4]]
#> [1] 31 31

Hostile input fails with a classed condition, before any R object exists:

# An array header claiming 2^64 - 1 elements, in nine bytes.
tryCatch(cbor_decode(as.raw(c(0x9b, rep(0xff, 8)))),
         zucbor_error = function(e) class(e)[1])
#> [1] "zucbor_parse_error"

# The same key twice, once in a longer encoding: refused by value.
cbor_validate(as.raw(c(0xa2, 0x01, 0x00, 0x18, 0x01, 0x00)))
#> [1] FALSE

Encoding

b <- cbor_encode(list(alg = -7, kid = charToRaw("11"),
                      when = as.POSIXct("2026-01-01", tz = "UTC")))
b
#>  [1] a3 63 61 6c 67 26 63 6b 69 64 42 31 31 64 77 68 65 6e c1 1a 69 55 b9 00

cbor_diagnose(b)
#> [1] "{\"alg\": -7, \"kid\": h'3131', \"when\": 1(1767225600)}"

# Deterministic: map entries are sorted by their encoded keys.
identical(cbor_encode(list(b = 1, a = 2)), cbor_encode(list(a = 2, b = 1)))
#> [1] TRUE

-7 is a double in R, but it is written as the integer a COSE algorithm identifier must be: a whole double is always an integer in CBOR.

What zucbor is not

It decodes and encodes CBOR. It does not verify COSE signatures, validate against CDDL schemas, or decode base64: those belong to other packages.

Learn more

zucbor is one of the zu* packages, with zujson, zuyaml and zuxml.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.