Native CBOR support

Since WebAuthN uses CBOR, I felt it would be a good idea to bring broad base support for CBOR throughout.

What is CBOR? CBOR is a serialization format much like JSON (and some more). However, unlike JSON, CBOR is a binary format. Its binary format can sometimes be 20-30% smaller than JSON. At scale, it can make a massive difference in bandwidth and memory. In many libraries, CBOR can be even faster when decoding and encoding. All valid JSON can be represented as CBOR. It also has the ability to encode and decode things into native JavaScript like dates, integers, UInt8Array and more.

I felt that it was weird for WebAuthN to support CBOR (as it's available in all browsers) but not expose that CBOR in the official spec.

3 Likes

WebAuthN isn’t part of the language, it’s part of HTML. Have you asked that specification?

While WebAuthN isn't part of the language, I just liked this CBOR. But it could be pratically almost the same as, but a bit more shorter than:

[['field1',10],['field2',10],['field3',10],]

(That's how a key-to-value map looks like in CBOR, except it's binary.)

CBOR has all the same limitations as JSON (e.g., no parent-child uplinking-downlinking), but it loses human readability and gains a little size advantage. It would probably see use as a replacement for JSON if the HTML and JS standards cooperated to make it happen.

Personally, I would love to see a format spec (binary or human readable, but I prefer human readable) for storing / loading nonserializable JavaScript object states. It's one of JavaScript's greatest weaknesses: Loading most useful structures into memory requires extravagant CPU cycles, not just copying to RAM. CBOR doesn't address that problem, unfortunately.

1 Like

FWIW, I am in the finishing stage with a CBOR encoder/decoder that (IMO) could fit in the ES universe. I'm not a JavaScript expert so bear with me if you look at the code :upside_down_face: However, the API may be worth a comment or two. I have stopped using JSON except when there is no other alternative.
https://github.com/cyberphone/cbor-js-api

This is a part of a multi-platform effort:https://github.com/cyberphone/cbor-everywhere

CBOR is probably not a terrible good replacement for JSON in browsers, while a no-brainer in Node.js since neither JSON nor XML offer deterministic encoding which is very useful for security related applications. Bidirectional diagnostic notation is also quite useful, it even supports comments (for input NB).

JSON nor XML offer deterministic encoding which is very useful for security related applications.

Could you expound on this. I assume, by "deterministic encoding", you mean that there's one and only one way to represent a piece of data in CBOR, unlike JSON where, e.g. there's different ways to add whitespace to the JSON without affecting the actual data it contains.

Why is this useful for security-related applications?

Good question! To sign data it must be identical for both the sender and receiver. Since JSON does not specify ordered maps you may run into interoperability issues and broken signatures. To solve that JSON needs to go through a canonicalization process. Although RFC8785 specifies a version of that, it never got IETF consensus.

Deterministic encoding OTOH is a solution which already has support in the CBOR base document, RFC8949, which CBOR.js builds on. In my take on the matter, deterministic encoding is always used, while decoding has some options for dealing with "legacy" CBOR.

The alternative is to put all data in a byte string and sign that. Although workable, it totally changes the document structure.

However, the core is still establishing a "base line" CBOR definition that can work with any high-end platform.

Not sure I fully understand the use case yet.

I tend to think of signing as something you do on an arbitrary message (chunk of bytes), so that the receiver can know that the sender really sent that message.

It sounds like using CBOR enables people to open up the message, parse it, re-encode it, then send the re-encoded version with confidence that the original signature would still work.

But, pardon my gap in understanding, why not just send the original signed message in its original form? Why are we trying to decide and re-encode these signed messages?

If the signature is a part of the message (enveloped), you need a way to extract it while keeping the (signed) rest intact. This is an example:

Current CBOR tools usually do not support deterministic encoding and thus fail on the reencoding.

To cope with that most solutions build on putting the data to be signed (wrapped in a "bstr" inside of a specifically crafted signature container, like COSE.

1 Like