Cbor
A Java library for CBOR, COSE, CWT and mdoc
Install / Use
/learn @authlete/CborREADME
Java Library for CBOR, COSE, CWT and mdoc
Overview
This is a Java library for CBOR (Concise Binary Object Representation), COSE (CBOR Object Signing and Encryption), CWT (CBOR Web Token) and mdoc ([ISO/IEC 18013-5:2021][ISO_IEC_18013_5_2021]).
The current implementation supports the features below. More features will be added as the need arises.
- [x] CBOR
- [x] Token Status List
- [x] COSE
- [x] Basic Components
- [x] Signature
- [x]
ES256 - [x]
ES384 - [x]
ES512 - [x]
EdDSA - [ ] ?
- [x]
- [ ] Encryption
- [ ] MAC
- [x] CWT
- [x] Tag Processor
- [x] CWT Claims Set
- [x] CWT Key Proof
- [ ] Status List Token
- [x] mdoc
License
Apache License, Version 2.0
Maven
<dependency>
<groupId>com.authlete</groupId>
<artifactId>cbor</artifactId>
<version>${cbor.version}</version>
</dependency>
Check the CHANGES.md file to know the latest version.
Source Code
<code>https://github.com/authlete/cbor</code>
JavaDoc
<code>https://authlete.github.io/cbor/index.html</code>
Standard Specifications
The following is a non-exhaustive list of standard specifications related to CBOR. The list does not necessarily mean that this library supports all of them.
IETF RFC
- [RFC 7049][RFC_7049] Concise Binary Object Representation (CBOR) | obsoleted by [RFC 8949][RFC_8949]
- [RFC 8152][RFC_8152] CBOR Object Signing and Encryption (COSE) | obsoleted by [RFC 9052][RFC_9052], [RFC 9053][RFC_9053]
- [RFC 8230][RFC_8230] Using RSA Algorithms with CBOR Object Signing and Encryption (COSE) Messages
- [RFC 8392][RFC_8392] CBOR Web Token (CWT)
- [RFC 8610][RFC_8610] Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures
- [RFC 8613][RFC_8613] Object Security for Constrained RESTful Environments (OSCORE)
- [RFC 8742][RFC_8742] Concise Binary Object Representation (CBOR) Sequences
- [RFC 8746][RFC_8746] Concise Binary Object Representation (CBOR) Tags for Typed Arrays
- [RFC 8943][RFC_8943] Concise Binary Object Representation (CBOR) Tags for Date
- [RFC 8949][RFC_8949] Concise Binary Object Representation (CBOR)
- [RFC 9052][RFC_9052] CBOR Object Signing and Encryption (COSE): Structures and Process
- [RFC 9053][RFC_9053] CBOR Object Signing and Encryption (COSE): Initial Algorithms
- [RFC 9090][RFC_9090] Concise Binary Object Representation (CBOR) Tags for Object Identifiers
- [RFC 9338][RFC_9338] CBOR Object Signing and Encryption (COSE): Countersignatures
- [RFC 9360][RFC_9360] CBOR Object Signing and Encryption (COSE): Header Parameters for Carrying and Referencing X.509 Certificates
- WG DRAFT: [Token Status List (TSL)][IETF_WG_DRAFT_TSL]
IANA Assignments
- IANA: [Concise Binary Object Representation (CBOR) Simple Values][IANA_cbor_simple_values]
- IANA: [Concise Binary Object Representation (CBOR) Tags][IANA_cbor_tags]
- IANA: [CBOR Object Signing and Encryption (COSE)][IANA_cose]
- IANA: [CBOR Web Token (CWT) Claims][IANA_cwt]
ISO/IEC
- [ISO/IEC 18013-5:2021][ISO_IEC_18013_5_2021] Personal identification - ISO-compliant driving licence, Part 5: Mobile driving licence (mDL) application
OpenID
- [OpenID for Verifiable Credential Issuance][OID4VCI]
Description
CBOR Reading
A byte sequence of CBOR data items is parsed to instances of common Java classes by going through the steps below in the shown order.
- a byte sequence (
InputStreamorbytearray) CBORTokenizerCBORDecoderCBORParser
Developers may use the CBORTokenizer class and the CBORDecoder class
directly, but the simplest way is to use the CBORParser class.
The usage of the CBORParser class is simple. It's just to create an instance
and call the next() method. The following code is an example to read a CBOR
data item that represents a text string "a".
// === String ===
// CBOR data item representing "a".
//
// major = 3 ; text string
// info = 1 ; length
//
byte[] input = { (byte)0x61, (byte)0x61 };
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be a String instance.
assertEquals("a", object);
Integers
Unsigned integers (major type = 0), negative integers (major type = 1), and
bignums (tag number = 2 or 3; [RFC 8949, Section 3.4.3. Bignums][RFC_8949_bignums])
are converted to instances of Integer, Long or BigInteger. Which Java
class is chosen depends on the actual value. Using the tag for bignums does
not necessarily result in that BigInteger is chosen. Conversely, if the
number represented using the major type 0 is greater than Long.MAX_VALUE,
BigInteger is chosen.
The following are examples to parse integers.
// === Integer ===
// CBOR data item representing 100.
//
// major = 0 ; unsigned integer
// info = 24 ; followed by 1 byte
//
byte[] input = { (byte)0x18, (byte)0x64 };
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be an Integer instance.
assertEquals(Integer.valueOf(100), object);
// === Long ===
// CBOR data item representing 1000000000000.
//
// major = 0 ; unsigned integer
// info = 27 ; followed by 8 bytes
//
byte[] input = {
(byte)0x1b, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0xe8, (byte)0xd4, (byte)0xa5, (byte)0x10,
(byte)0x00
};
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be a Long instance.
assertEquals(Long.valueOf(1000000000000L), object);
// === BigInteger ===
// CBOR data items representing 18446744073709551616.
//
// major = 6 ; tag
// info = 2 ; tag number 2, bignum (RFC 8949 Section 3.4.3)
//
// major = 2 ; byte string
// info = 9 ; length
//
byte[] input = {
(byte)0xC2, (byte)0x49, (byte)0x01, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00
};
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be a BigInteger instance.
assertEquals(new BigInteger("18446744073709551616"), object);
Floating-Point Numbers
Half-precision floating-point numbers (major type = 7, additional info = 25)
and single-precision floating-point numbers (major type = 7, additional info
= 26) are converted to Float instances. As Java does not natively support
half-precision floating-point numbers, CBOR half-precision floating-point
numbers become single-precision ones after conversion.
// === Float ===
// CBOR data item representing -0.625f in the IEEE 754
// floating-point half-precision format.
//
// major = 7 ; floating point
// info = 25 ; half precision
//
byte[] input = { (byte)0xF9, (byte)0xB9, (byte)0x00 };
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be a Float instance.
assertEquals(Float.valueOf(-0.625f), object);
On the other hand, double-precision numbers (major type 7, additional info = 27)
are converted to Double instances.
// === Double ==
// CBOR data item representing 1.1 in the IEEE 754
// floating-point double-precision format.
//
// major = 7 ; floating point
// info = 27 ; double precision
//
byte[] input = {
(byte)0xFB, (byte)0x3F, (byte)0xF1, (byte)0x99,
(byte)0x99, (byte)0x99, (byte)0x99, (byte)0x99,
(byte)0x9A
};
Boolean
false (major type = 7, additional info = 20) and true (major type = 7,
additional info = 21) are converted to Boolean.FALSE and Boolean.TRUE,
respectively.
// === Boolean ===
// CBOR data item representing true.
//
// major = 7 ; simple value
// info = 21 ; true
//
byte[] input = { (byte)0xF5 };
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be the existing Boolean instance.
assertSame(Boolean.TRUE, object);
Byte Arrays
Byte strings (major type = 2) are converted to byte[] instances.
// === byte[] ===
//
// CBOR data item representing h'01020304'.
//
// major = 2 ; byte string
// info = 4 ; length
//
byte[] input = {
(byte)0x44, (byte)0x01, (byte)0x02, (byte)0x03,
(byte)0x04
};
// Expected result.
byte[] expected = {
(byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04
};
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should be a byte array.
assertSame(byte[].class, object.getClass());
assertArrayEquals(expected, (byte[])object);
Arrays
Arrays (major type = 4) are converted to instances of List<Object>.
// === Collection ===
// CBOR data items representing [1, 2, 3].
byte[] input = {
(byte)0x83, (byte)0x01, (byte)0x02, (byte)0x03
};
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should implement the List interface.
assertTrue(object instanceof List);
List<Object> list = (List<Object>)object;
assertEquals(1, list.get(0));
assertEquals(2, list.get(1));
assertEquals(3, list.get(2));
Maps
Maps (major type = 5) are converted to instances of Map<Object, Object>.
// === Map ===
// CBOR data items representing {"a": 1, "b": [2, 3]}.
byte[] input = {
(byte)0xA2, (byte)0x61, (byte)0x61, (byte)0x01,
(byte)0x61, (byte)0x62, (byte)0x82, (byte)0x02,
(byte)0x03
};
// Parse the CBOR data item.
Object object = new CBORParser(input).next();
// The object should implement the Map interface.
assertTrue(object instanceof Map);
Map<Object, Object> map = (Map<Object, Object>)object;
// "a": 1
assertEquals(1, map.get("a"));
// "b": [2, 3]
List<Object> sublist = (List<Object>)map.get("b");
assertEquals(2, sublist.get(0));
assertEquals(3, sublist.get(1));
Other Types
Simple values (major type = 7, additional info <= 24) are converted to
Integer
