CBOR and ASN.1 in Swift: Complete Guide to Binary Serialization
Introduction
When talking about data serialization, JSON largely dominates the web and mobile ecosystem. Yet, in critical domains like IoT, strong authentication (WebAuthn/FIDO2), digital certificates, or mobile identity (ISO 18013-5), two binary formats reign supreme: CBOR (Concise Binary Object Representation) and ASN.1 (Abstract Syntax Notation One).
This article guides you through these two essential standards for any Swift developer working on secure projects. You'll discover their structure, their differences, and most importantly how to implement them efficiently with the tools available in 2026.
๐ฏ What is CBOR?
CBOR (Concise Binary Object Representation), defined in RFC 8949, is a binary serialization format designed to be compact, fast to parse, and extensible without version negotiation.
Design Goals
CBOR was created with precise goals that distinguish it from other formats:
Code compactness: A CBOR encoder/decoder can be implemented in a few hundred lines of code, ideal for microcontrollers. Message compactness: Encoded data is significantly smaller than JSON. Self-description: Unlike Protocol Buffers, no schema is required to decode data. Extensibility: The tag system allows adding semantic types without breaking compatibility.
Main Use Cases
CBOR has become the reference format in several critical domains:
IoT and embedded systems: CoAP (Constrained Application Protocol) uses CBOR as its default payload format. WebAuthn and FIDO2: Security key attestations and assertions are encoded in CBOR. COSE (CBOR Object Signing and Encryption): Cryptographic standard defined in RFC 9052 and RFC 9053. Mobile Driver's License (mDL): The ISO 18013-5 standard uses CBOR to structure digital identity documents.
๐ข CBOR Structure: The 8 Major Types
CBOR organizes its data into 8 major types, identified by the 3 high-order bits of the first byte:
| Type | Name | Description |
|---|---|---|
0 | Unsigned Integer | Positive integer (0 to 2โถโด-1) |
1 | Negative Integer | Negative integer (-1 to -2โถโด) |
2 | Byte String | Raw binary data |
3 | Text String | UTF-8 string |
4 | Array | Ordered array |
5 | Map | Key/value dictionary |
6 | Tag | Semantic metadata |
7 | Simple/Float | Booleans, null, floats |
Variable-Length Encoding
CBOR uses smart encoding where small values occupy fewer bytes:
Semantic Tags
Tags (major type 6) add context to data. Some common tags:
| Tag | Meaning |
|---|---|
0 | ISO 8601 date/time |
1 | Unix timestamp |
2 | Positive bignum |
3 | Negative bignum |
24 | Encapsulated CBOR data |
55799 | Self-describing CBOR |
๐ Serialization Format Comparison
| Criterion | JSON | CBOR | MessagePack | Protocol Buffers |
|---|---|---|---|---|
Format | Text | Binary | Binary | Binary |
Schema required | No | No | No | Yes |
Typical size | 100% | 50-70% | 50-70% | 40-60% |
Parsing | Slow | Fast | Fast | Very fast |
Binary types | Base64 | Native | Native | Native |
Extensibility | Limited | Tags | Types | Versions |
iOS adoption | Native | Third-party libs | Third-party libs | Third-party libs |
๐ ๏ธ Swift Ecosystem Status
Apple does not provide a native framework for CBOR. Two open-source libraries dominate the ecosystem:
SwiftCBOR
SwiftCBOR offers a low-level API with direct manipulation of CBOR types.
Strengths: Lightweight, no dependencies, full control over encoding.
Weaknesses: No native Codable integration, verbose API for complex cases.
PotentCodables
PotentCodables provides a complete suite of encoders/decoders (CBOR, ASN.1, YAML, JSON) with Codable integration.
Strengths: Codable integration, ASN.1/DER support, consistent API.
Weaknesses: Heavier, transitive dependencies.
๐ Practical Implementation
Installation via Swift Package Manager
Basic Encoding and Decoding with SwiftCBOR
Codable Integration with PotentCodables
Custom Types with Numeric Keys (ISO 18013-5 style)
For protocols like mDL that use numeric keys rather than strings:
๐ COSE: CBOR Signing and Encryption
COSE_Sign1 Structure
The most common structure for single-signer signatures:
COSE Implementation with CryptoKit
๐ ASN.1: The Grandfather of Binary Serialization
Before CBOR, there was ASN.1 (Abstract Syntax Notation One). This standard from the 80s remains ubiquitous in cryptography: X.509 certificates, PKCS#8 keys, CMS signatures. Understanding ASN.1 is essential for anyone working with CryptoKit and key exchange formats.
What is ASN.1?
ASN.1 is a data description language, not an encoding format itself. It defines the structure, then encoding rules transform it into bytes:
BER (Basic Encoding Rules): Flexible encoding, multiple representations possible for the same data. DER (Distinguished Encoding Rules): Subset of BER, deterministic โ one representation per data. DER is used for certificates and signatures. PER, XER, JER: Other encodings (compact, XML, JSON) less common.
CBOR vs ASN.1: When to Use Which?
| Criterion | CBOR | ASN.1/DER |
|---|---|---|
Era | 2013 | 1984 |
Complexity | Simple | Complex |
Schema required | No | Yes (implicit) |
Main usage | IoT, WebAuthn, mDL | Certificates, PKI, CMS |
Parsing | Easy | Difficult |
Swift ecosystem | Limited | Very limited |
In practice: use CBOR for your new protocols, but you'll need to handle ASN.1 as soon as you touch certificates or key export.
TLV Structure (Tag-Length-Value)
ASN.1/DER uses a TLV structure similar to CBOR but more verbose:
Tags identify the type:
| Tag | Type | Description |
|---|---|---|
0x02 | INTEGER | Signed integer |
0x03 | BIT STRING | Bit string |
0x04 | OCTET STRING | Binary data |
0x05 | NULL | Null value |
0x06 | OBJECT IDENTIFIER | OID (algorithm identifier) |
0x0C | UTF8String | UTF-8 string |
0x13 | PrintableString | Restricted ASCII string |
0x17 | UTCTime | Date/time |
0x30 | SEQUENCE | Ordered structure |
0x31 | SET | Unordered set |
ASN.1 Implementation with PotentCodables
PotentCodables offers complete ASN.1 support via the PotentASN1 module. Encoding and decoding require defining a schema that describes the expected ASN.1 structure:
Encoding a Custom ASN.1 Structure
Let's create a structure to encapsulate a signature with its metadata:
Converting Between CBOR and ASN.1
Sometimes you need to convert data between the two formats โ for example, to integrate CBOR keys (COSE_Key) with X.509 certificates:
โก Performance and Best Practices
Typical Benchmarks
In an iOS context, here are the typical orders of magnitude:
| Operation | JSON | CBOR | Gain |
|---|---|---|---|
Encoding 1000 objects | 45ms | 28ms | 37% |
Decoding 1000 objects | 52ms | 31ms | 40% |
Payload size | 100KB | 62KB | 38% |
When to Use CBOR?
Recommended:
- IoT/embedded communication (CoAP, LwM2M)
- Authentication protocols (WebAuthn, FIDO2)
- Digital identity documents (mDL, EUDI Wallet)
- Intensive binary data exchange
- Bandwidth-constrained environments
Avoid:
- Classic REST APIs (native JSON is simpler)
- Frequent debugging (CBOR is less readable)
- Maximum interoperability required (JSON is more universal)
When to Use ASN.1?
Recommended:
- X.509 certificate manipulation
- Cryptographic key export/import
- Integration with existing PKI
- Legacy protocols (LDAP, SNMP, etc.)
Avoid:
- New protocols (prefer CBOR)
- Modern APIs (prefer JSON or CBOR)
Debugging CBOR: Diagnostic Notation
CBOR defines a diagnostic notation for debugging, similar to JSON but more explicit:
Unit Tests with Swift Testing
๐ฎ Perspectives: Identity Document Services
CBOR is at the heart of the digital identity revolution. The ISO 18013-5 standard defines the Mobile Driver's License (mDL), and the future EUDI (European Digital Identity) regulation builds on these same foundations.
In an upcoming article, we'll explore in detail the Identity Document Services introduced in iOS 26, and how Apple integrates these standards to enable identity verification directly from your applications.