-
Notifications
You must be signed in to change notification settings - Fork 0
CBOR Encoding_Decoding
- Introduction
- CBOR Implementation Overview
- Core Functions and Data Types
- Encoding Process
- Decoding Process
- Canonical CBOR Validation
- CTAP2 Message Serialization
- Performance Considerations
- Error Handling
- Security Implications
- Practical Examples
- Testing and Validation
The FIDO2 WebAuthn platform implements a minimal but comprehensive CBOR (Concise Binary Object Representation) library specifically tailored for CTAP2 (Client-to-Authenticator Protocol) message encoding and decoding. This implementation provides efficient binary serialization of FIDO2 protocol messages while maintaining strict adherence to the FIDO2 specification requirements.
CBOR serves as the primary wire format for communication between web browsers and FIDO2 authenticators, enabling compact and efficient transmission of cryptographic parameters, attestation data, and authentication responses. The implementation focuses on supporting only the subset of CBOR functionality required for FIDO2 CTAP2 operations, ensuring optimal performance and security.
The CBOR implementation consists of two main components: a lightweight encoder/decoder for basic CBOR operations and a specialized canonical encoder for FIDO2 compliance.
graph TB
subgraph "CBOR Implementation Architecture"
A[CBOR Encoder] --> D[Canonical Encoder]
B[CBOR Decoder] --> E[Strict Validation]
C[Type System] --> A
C --> B
subgraph "Supported Data Types"
F[Integers]
G[Booleans]
H[Strings]
I[Bytes]
J[Arrays]
K[Maps]
end
C --> F
C --> G
C --> H
C --> I
C --> J
C --> K
end
Diagram sources
- fido2/cbor.py
- server/server/decoder/encode.py
The implementation provides three primary functions for CBOR operations:
- encode(): Converts Python objects to CBOR byte strings
- decode(): Decodes CBOR byte strings to Python objects with strict validation
- decode_from(): Decodes CBOR from the start of a byte string with remainder handling
Section sources
- fido2/cbor.py
The CBOR implementation supports a comprehensive set of data types essential for FIDO2 CTAP2 operations:
| Data Type | CBOR Major Type | Description | Encoding Format |
|---|---|---|---|
| Integer | 0/1 | Unsigned and negative integers | Variable-length encoding (0-27) |
| Boolean | 7 | True/false values | Specialized byte codes (f4/f5) |
| String | 3 | UTF-8 encoded text | Length-prefixed UTF-8 bytes |
| Bytes | 2 | Binary data | Length-prefixed byte sequence |
| Array | 4 | Ordered sequences | Length-prefixed element list |
| Map | 5 | Key-value pairs | Length-prefixed key-value pairs |
The implementation defines a comprehensive type system using the CborType union:
classDiagram
class CborType {
<<union>>
+int
+bool
+str
+bytes
+Sequence~Any~
+Mapping~Any, Any~
}
class SerializerRegistry {
+dump_int(data, mt) bytes
+dump_bool(data) bytes
+dump_text(data) bytes
+dump_bytes(data) bytes
+dump_list(data) bytes
+dump_dict(data) bytes
}
class DeserializerRegistry {
+load_int(ai, data) Tuple[int, bytes]
+load_nint(ai, data) Tuple[int, bytes]
+load_bool(ai, data) Tuple[bool, bytes]
+load_text(ai, data) Tuple[str, bytes]
+load_bytes(ai, data) Tuple[bytes, bytes]
+load_array(ai, data) Tuple[Sequence, bytes]
+load_map(ai, data) Tuple[Mapping, bytes]
}
CborType --> SerializerRegistry
CborType --> DeserializerRegistry
Diagram sources
- fido2/cbor.py
- fido2/cbor.py
Section sources
- fido2/cbor.py
Integer encoding employs variable-length representation based on value magnitude:
flowchart TD
A[Integer Input] --> B{Value Range Check}
B --> |0-23| C[Single Byte: 0x00-0x17]
B --> |24-255| D[Two Bytes: 0x18 + value]
B --> |256-65535| E[Three Bytes: 0x19 + big-endian 2 bytes]
B --> |65536-4294967295| F[Five Bytes: 0x1A + big-endian 4 bytes]
B --> |4294967296-18446744073709551615| G[Nine Bytes: 0x1B + big-endian 8 bytes]
H[Negative Integer] --> I[Complement Calculation]
I --> J[Major Type 1]
J --> B
Diagram sources
- fido2/cbor.py
The implementation enforces canonical key ordering for dictionary encoding:
sequenceDiagram
participant Input as Input Dictionary
participant Encoder as Dictionary Encoder
participant Sorter as Key Sorter
participant Output as CBOR Output
Input->>Encoder : {key1 : value1, key2 : value2}
Encoder->>Encoder : encode keys/values
Encoder->>Sorter : sort by (length, lexicographic)
Sorter->>Encoder : sorted key-value pairs
Encoder->>Output : encode length + sorted pairs
Diagram sources
- fido2/cbor.py
Array encoding follows a straightforward pattern:
- Encode the array length as a CBOR integer
- Recursively encode each element
- Concatenate all encoded elements
Section sources
- fido2/cbor.py
The decoding process handles CBOR data streams with strict validation:
flowchart TD
A[CBOR Data Stream] --> B[Extract Major Type]
B --> C[Extract Additional Info]
C --> D{Major Type}
D --> |0| E[Positive Integer]
D --> |1| F[Negative Integer]
D --> |2| G[Byte String]
D --> |3| H[Text String]
D --> |4| I[Array]
D --> |5| J[Map]
D --> |7| K[Boolean/Null]
E --> L[Load Integer Value]
F --> M[Load Negative Integer]
G --> N[Load Bytes]
H --> O[Load Text]
I --> P[Load Array]
J --> Q[Load Map]
K --> R[Load Boolean]
L --> S[Return Value]
M --> S
N --> S
O --> S
P --> S
Q --> S
R --> S
Diagram sources
- fido2/cbor.py
The implementation provides strict validation that ensures:
- Complete consumption of input data
- Canonical CBOR structure compliance
- No extraneous data following the encoded object
Section sources
- fido2/cbor.py
Canonical CBOR validation ensures deterministic message serialization, which is crucial for:
- Cryptographic signature verification
- Message replay protection
- Consistent protocol behavior
- Security protocol compliance
sequenceDiagram
participant Client as Client
participant Validator as Canonical Validator
participant Authenticator as Authenticator
Client->>Validator : encode(message)
Validator->>Validator : canonicalize structure
Validator->>Client : canonical_cbor_bytes
Client->>Authenticator : send(canonical_cbor_bytes)
Authenticator->>Validator : decode(response)
Validator->>Validator : validate canonical form
Validator->>Authenticator : strict_validation_result
Diagram sources
- server/server/decoder/encode.py
The canonical encoder implements several critical validation features:
- Deterministic Key Ordering: Maps are encoded with keys sorted by length and lexicographic order
- Unique Key Enforcement: Detects and rejects duplicate keys
- Length-Prefix Validation: Ensures proper length encoding for all container types
- Type Consistency: Validates that encoded types match expected CBOR major types
Section sources
- server/server/decoder/encode.py
The CBOR implementation integrates seamlessly with the CTAP2 protocol through the Ctap2 class:
classDiagram
class Ctap2 {
+send_cbor(cmd, data) Mapping
+get_info() Info
-device CtapDevice
-strict_cbor bool
-max_msg_size int
}
class CtapDevice {
+call(cmd, data) bytes
+capabilities int
}
class Info {
+versions str[]
+extensions str[]
+aaguid Aaguid
+options dict~str, bool~
+max_msg_size int
+from_dict(data) Info
}
Ctap2 --> CtapDevice
Ctap2 --> Info
Ctap2 --> CBOR : uses
Diagram sources
- fido2/ctap2/base.py
- fido2/ctap2/base.py
CTAP2 commands follow a standardized structure using CBOR encoding:
sequenceDiagram
participant Browser as Web Browser
participant Authenticator as FIDO2 Authenticator
participant CBOR as CBOR Encoder/Decoder
Browser->>CBOR : encode(command_data)
CBOR->>CBOR : canonicalize_structure()
CBOR->>Browser : cbor_bytes
Browser->>Authenticator : send(0x10 + cbor_bytes)
Authenticator->>CBOR : decode(response_bytes)
CBOR->>CBOR : validate_canonical()
CBOR->>Authenticator : validated_response
Diagram sources
- fido2/ctap2/base.py
Section sources
- fido2/ctap2/base.py
The CBOR implementation employs several optimization strategies for efficient operation:
- Minimal Memory Allocation: Uses efficient byte manipulation and avoids unnecessary copying
- Streaming Processing: Supports partial decoding for large messages
- Type-Specific Optimizations: Specialized handlers for frequently used types
-
Struct-Based Packing: Utilizes
struct.pack()for efficient binary encoding
| Operation | Complexity | Notes |
|---|---|---|
| Integer Encoding | O(1) | Constant time regardless of value size |
| String Encoding | O(n) | Linear with string length |
| Dictionary Encoding | O(n log n) | Dominated by sorting operation |
| Array Encoding | O(n) | Linear with number of elements |
| Decoding | O(n) | Linear with input size |
The implementation minimizes memory overhead through:
- Efficient byte array construction using concatenation
- Lazy evaluation of complex structures
- Minimal intermediate object creation
- Streaming support for large payloads
The CBOR implementation handles various error conditions:
flowchart TD
A[CBOR Operation] --> B{Error Type}
B --> |Invalid Format| C[ValueError]
B --> |Type Mismatch| D[TypeError]
B --> |Insufficient Data| E[IndexError]
B --> |Canonical Violation| F[ValueError]
B --> |Unsupported Type| G[ValueError]
C --> H[Error Handling]
D --> H
E --> H
F --> H
G --> H
H --> I[Graceful Degradation]
H --> J[Validation Failure]
Diagram sources
- fido2/cbor.py
The implementation provides robust error recovery:
- Lenient Decoding: Attempts fallback parsing for malformed data
- Partial Recovery: Extracts valid portions from corrupted messages
- Graceful Degradation: Continues operation with reduced functionality
- Detailed Error Reporting: Provides context for debugging
Section sources
- server/server/decoder/decode.py
The CBOR implementation addresses several security concerns:
- Message Integrity: Canonical validation prevents message manipulation
- Replay Protection: Deterministic encoding enables signature verification
- Format Confusion: Strict parsing prevents type confusion attacks
- Resource Exhaustion: Input validation limits memory allocation
The implementation enforces several security best practices:
- Strict Canonical Validation: Ensures deterministic message structure
- Input Sanitization: Validates all input parameters
- Memory Safety: Prevents buffer overflow vulnerabilities
- Type Safety: Enforces type checking for all operations
The implementation meets FIDO2 security requirements:
- Deterministic Encoding: Required for cryptographic signatures
- Canonical Validation: Mandatory for authenticator responses
- Secure Parsing: Prevents injection attacks
- Integrity Verification: Enables message authenticity checks
Encoding a simple CTAP2 command structure:
# Example structure: {1: "makeCredential", 2: {...}}
command_data = {
1: "makeCredential",
2: {
"rp": {"id": "example.com", "name": "Example Service"},
"user": {"id": b"user123", "name": "alice@example.com"}
}
}
# Encode using CBOR
encoded_bytes = cbor.encode(command_data)Encoding a credential creation request with extensions:
# Complex CTAP2 message with extensions
complex_request = {
1: "makeCredential",
2: {
"rp": {"id": "service.com", "name": "Secure Service"},
"user": {
"id": b"abcdef123456",
"name": "user@example.com",
"displayName": "Alice Smith"
},
"pubKeyCredParams": [
{"alg": -7, "type": "public-key"}, # ES256
{"alg": -257, "type": "public-key"} # RS256
]
},
3: {
"credBlob": b"\x01\x02\x03\x04",
"hmac-secret": True
}
}
# Canonical encoding for security
canonical_bytes = cbor.encode(complex_request)Decoding authenticator responses with validation:
# Receive authenticator response
response_bytes = authenticator_device.call(CTAPHID.CBOR, request_bytes)
# Decode with strict validation
try:
response_data = cbor.decode(response_bytes)
except ValueError as e:
# Handle canonical validation failure
logger.error(f"Invalid canonical CBOR: {e}")
# Attempt lenient decoding
response_data, _ = cbor.decode_from(response_bytes)Section sources
- fido2/ctap2/base.py
The CBOR implementation includes comprehensive testing:
graph TB
subgraph "Test Categories"
A[Unit Tests] --> B[Basic Encoding/Decoding]
A --> C[Edge Cases]
A --> D[Error Conditions]
E[Integration Tests] --> F[CTAP2 Protocol]
E --> G[Message Validation]
E --> H[Canonical Compliance]
I[FIDO Test Vectors] --> J[Standard Compliance]
I --> K[Reference Data]
I --> L[Interoperability]
end
Diagram sources
- tests/test_cbor.py
The implementation uses multiple validation approaches:
- FIDO Test Vectors: Validates against official test data
- Canonical Compliance: Ensures deterministic encoding
- Round-Trip Testing: Verifies encoding-decoding cycles
- Edge Case Testing: Covers boundary conditions
The testing framework ensures:
- Completeness: Covers all supported data types
- Correctness: Validates against reference implementations
- Robustness: Handles malformed input gracefully
- Performance: Monitors encoding/decoding speed
Section sources
- tests/test_cbor.py