Complete documentation for the CBOR (Concise Binary Object Representation) PHP library.
- Installation & Quick Start
- Tags Reference - Complete guide to all supported CBOR tags
- Creating Custom Tags - How to implement your own tags
- API Reference
- Examples
CBOR (Concise Binary Object Representation) is a data format defined in RFC 8949 that provides a compact binary encoding for structured data. This PHP library provides a complete implementation for encoding and decoding CBOR data.
- Compact: Smaller than JSON for most data
- Fast: Efficient binary encoding and decoding
- Extensible: Support for tags provides semantic annotations
- Standardized: Well-defined specification with IANA registry
- Versatile: Supports all major data types including binary data
- IoT & Embedded Systems: Efficient data exchange with constrained devices
- WebAuthn/FIDO2: Authentication data encoding
- COSE: Cryptographic object signing and encryption
- CWT: CBOR Web Tokens (JWT alternative)
- CoAP: Constrained Application Protocol payloads
- API Communication: Binary alternative to JSON
CBOR defines 8 major types (0-7):
| Type | Description | PHP Classes |
|---|---|---|
| 0 | Unsigned Integer | UnsignedIntegerObject |
| 1 | Negative Integer | NegativeIntegerObject |
| 2 | Byte String | ByteStringObject, IndefiniteLengthByteStringObject |
| 3 | Text String | TextStringObject, IndefiniteLengthTextStringObject |
| 4 | Array | ListObject, IndefiniteLengthListObject |
| 5 | Map | MapObject, IndefiniteLengthMapObject |
| 6 | Tag | Tag subclasses (see Tags Documentation) |
| 7 | Simple/Float | TrueObject, FalseObject, NullObject, float objects |
CBORObject (interface)
├── AbstractCBORObject (abstract)
│ ├── UnsignedIntegerObject
│ ├── NegativeIntegerObject
│ ├── ByteStringObject
│ ├── IndefiniteLengthByteStringObject
│ ├── TextStringObject
│ ├── IndefiniteLengthTextStringObject
│ ├── ListObject
│ ├── IndefiniteLengthListObject
│ ├── MapObject
│ ├── IndefiniteLengthMapObject
│ ├── Tag (abstract)
│ │ ├── DatetimeTag
│ │ ├── TimestampTag
│ │ ├── DecimalFractionTag
│ │ ├── BigFloatTag
│ │ ├── ... (see Tags Reference)
│ │ └── GenericTag
│ └── OtherObject (abstract)
│ ├── TrueObject
│ ├── FalseObject
│ ├── NullObject
│ ├── UndefinedObject
│ ├── DoublePrecisionFloatObject
│ └── ...
Many CBOR objects implement the Normalizable interface, which provides a normalize() method to convert to native PHP types:
$text = TextStringObject::create('Hello');
$text->normalize(); // string: "Hello"
$int = UnsignedIntegerObject::create(42);
$int->normalize(); // string: "42"
$map = MapObject::create()
->add(TextStringObject::create('key'), UnsignedIntegerObject::create(100));
$map->normalize(); // array: ['key' => '100']All CBOR objects provide a static create() method:
// Integers
$uint = UnsignedIntegerObject::create(42);
$nint = NegativeIntegerObject::create(-42);
// Strings
$text = TextStringObject::create('Hello World');
$bytes = ByteStringObject::create('binary data');
// Collections
$list = ListObject::create([
UnsignedIntegerObject::create(1),
UnsignedIntegerObject::create(2),
]);
$map = MapObject::create()
->add(TextStringObject::create('name'), TextStringObject::create('Alice'))
->add(TextStringObject::create('age'), UnsignedIntegerObject::create(30));
// Tags
$timestamp = TimestampTag::create(UnsignedIntegerObject::create(time()));All objects implement __toString():
$object = TextStringObject::create('Hello');
$encoded = (string) $object;
// or
$encoded = $object->__toString();
echo bin2hex($encoded); // "6548656c6c6f"use CBOR\Decoder;
// Default decoder with all standard tags
$decoder = Decoder::create();
// Custom decoder with specific tags
use CBOR\Tag\TagManager;
use CBOR\OtherObject\OtherObjectManager;
$tagManager = TagManager::create()
->add(TimestampTag::class)
->add(DatetimeTag::class);
$otherObjectManager = OtherObjectManager::create()
->add(TrueObject::class)
->add(FalseObject::class)
->add(NullObject::class);
$decoder = Decoder::create($tagManager, $otherObjectManager);use CBOR\StringStream;
$binaryData = hex2bin('6548656c6c6f');
$stream = StringStream::create($binaryData);
$object = $decoder->decode($stream);
// Check type and extract value
if ($object instanceof TextStringObject) {
echo $object->getValue(); // "Hello"
echo $object->normalize(); // "Hello"
}$list = ListObject::create();
// Add items
$list->add(UnsignedIntegerObject::create(1));
$list->add(TextStringObject::create('two'));
// Access items
$first = $list->get(0);
$count = $list->count();
// Check existence
if ($list->has(1)) {
// ...
}
// Remove items
$list->remove(0);
// Array access
$list[0] = UnsignedIntegerObject::create(42);
$value = $list[0];
// Iteration
foreach ($list as $item) {
// ...
}
// Normalize to PHP array
$phpArray = $list->normalize();$map = MapObject::create();
// Add key-value pairs
$map->add(
TextStringObject::create('name'),
TextStringObject::create('Alice')
);
// Access values
$name = $map->get('name');
// Check existence
if ($map->has('name')) {
// ...
}
// Remove entries
$map->remove('name');
// Count entries
$count = $map->count();
// Iteration
foreach ($map as $item) {
$key = $item->getKey();
$value = $item->getValue();
}
// Normalize to PHP array
$phpArray = $map->normalize();See the comprehensive Tags Reference for detailed information.
// Create tagged values
$timestamp = TimestampTag::create(UnsignedIntegerObject::create(time()));
$decimal = DecimalFractionTag::createFromFloat(3.14159);
// Access wrapped value
$wrappedObject = $timestamp->getValue();
// Normalize to PHP types
$dateTime = $timestamp->normalize(); // DateTimeImmutable
$number = $decimal->normalize(); // "3.14159"See Tags Reference for comprehensive documentation on all supported tags, including:
- Date/Time tags (Tags 0, 1)
- Big number tags (Tags 2, 3)
- Fractional number tags (Tags 4, 5)
- Encoding tags (Tags 21, 22, 23, 33, 34)
- Semantic tags (Tags 32, 36)
- Special CBOR tags (Tags 24, 55799)
See Creating Custom Tags for a complete guide on implementing custom tag types for:
- Domain-specific data types
- Integration with other specifications (COSE, CWT, etc.)
- Custom validation and transformation logic
CBOR supports streaming with indefinite-length objects:
// Indefinite-length text string
$text = IndefiniteLengthTextStringObject::create()
->append('Hello')
->append(' ')
->append('World');
echo $text->getValue(); // "Hello World"
// Indefinite-length byte string
$bytes = IndefiniteLengthByteStringObject::create()
->append('part1')
->append('part2');
// Indefinite-length list
$list = IndefiniteLengthListObject::create()
->add(UnsignedIntegerObject::create(1))
->add(UnsignedIntegerObject::create(2));
// Indefinite-length map
$map = IndefiniteLengthMapObject::create()
->append(TextStringObject::create('key1'), UnsignedIntegerObject::create(1))
->append(TextStringObject::create('key2'), UnsignedIntegerObject::create(2));Implement the Stream interface for custom data sources:
use CBOR\Stream;
class FileStream implements Stream
{
private $handle;
private int $position = 0;
public function __construct(string $filepath)
{
$this->handle = fopen($filepath, 'rb');
}
public function read(int $length): string
{
$data = fread($this->handle, $length);
$this->position += strlen($data);
return $data;
}
public function getPosition(): int
{
return $this->position;
}
// ... implement remaining methods
}
// Use with decoder
$stream = new FileStream('/path/to/cbor/file.cbor');
$object = $decoder->decode($stream);$object = $decoder->decode($stream);
// Check major type
if ($object instanceof UnsignedIntegerObject) {
echo "Unsigned integer: " . $object->getValue();
}
// Check for tags
if ($object instanceof TimestampTag) {
echo "Timestamp: " . $object->normalize()->format('Y-m-d');
}
// Check for normalizable
if ($object instanceof Normalizable) {
$phpValue = $object->normalize();
}
// Pattern matching (PHP 8.0+)
$value = match (true) {
$object instanceof TextStringObject => $object->getValue(),
$object instanceof UnsignedIntegerObject => (int) $object->getValue(),
$object instanceof ListObject => $object->normalize(),
default => null,
};CBOR is used extensively in WebAuthn for credential data:
// Decode authenticator data
$authenticatorData = $decoder->decode(StringStream::create($binaryData));
if ($authenticatorData instanceof MapObject) {
$credentialId = $authenticatorData->get('credentialId');
$publicKey = $authenticatorData->get('publicKey');
// Process WebAuthn credential
}// Decode a COSE_Sign1 structure
$coseSign1 = $decoder->decode($stream);
if ($coseSign1 instanceof COSESign1Tag) {
$protected = $coseSign1->getProtectedHeaders();
$payload = $coseSign1->getPayload();
$signature = $coseSign1->getSignature();
// Verify signature
}// Encode sensor readings efficiently
$sensorData = MapObject::create()
->add(
TextStringObject::create('temperature'),
DecimalFractionTag::createFromFloat(23.5)
)
->add(
TextStringObject::create('humidity'),
UnsignedIntegerObject::create(65)
)
->add(
TextStringObject::create('timestamp'),
TimestampTag::create(UnsignedIntegerObject::create(time()))
);
$encoded = (string) $sensorData;
// Send over network (much smaller than JSON)// Convert PHP data to CBOR
function encodeToCBOR(array $data): string
{
$map = MapObject::create();
foreach ($data as $key => $value) {
$keyObj = TextStringObject::create($key);
$valueObj = match (gettype($value)) {
'string' => TextStringObject::create($value),
'integer' => UnsignedIntegerObject::create($value),
'array' => convertArrayToList($value),
default => throw new Exception('Unsupported type'),
};
$map->add($keyObj, $valueObj);
}
return (string) $map;
}
// Usage
$response = encodeToCBOR([
'status' => 'success',
'code' => 200,
'data' => ['item1', 'item2']
]);
header('Content-Type: application/cbor');
echo $response;- Reuse Decoders: Create decoder instances once and reuse
- Use Appropriate Types: Choose the smallest integer type that fits
- Batch Operations: Build collections incrementally rather than recreating
- Stream Large Data: Use indefinite-length objects for streaming
- Enable Extensions: Install
ext-gmporext-bcmathfor better performance
use InvalidArgumentException;
use RuntimeException;
try {
$decoder = Decoder::create();
$object = $decoder->decode($stream);
} catch (InvalidArgumentException $e) {
// Invalid CBOR structure or data
error_log('CBOR decoding error: ' . $e->getMessage());
} catch (RuntimeException $e) {
// Missing required extension
error_log('Runtime error: ' . $e->getMessage());
}// Get human-readable representation
var_dump($object);
// For maps and lists
foreach ($map as $item) {
echo sprintf(
"Key: %s, Value: %s\n",
$item->getKey()->normalize(),
$item->getValue()->normalize()
);
}
// Check encoded binary
$encoded = (string) $object;
echo 'Hex: ' . bin2hex($encoded) . "\n";
echo 'Length: ' . strlen($encoded) . " bytes\n";- CBOR Playground - Visualize CBOR data
- CBOR.io - Online encoder/decoder
- WebAuthn Framework - Uses CBOR for credentials
- PHP JOSE - Related JWT/JWE library
// Encoding
$text = TextStringObject::create('hello');
$int = UnsignedIntegerObject::create(42);
$list = ListObject::create([$text, $int]);
$map = MapObject::create()->add($text, $int);
$tagged = TimestampTag::create($int);
$encoded = (string) $map;
// Decoding
$decoder = Decoder::create();
$stream = StringStream::create($encoded);
$object = $decoder->decode($stream);
$phpValue = $object->normalize();
// Tags
$timestamp = TimestampTag::create(UnsignedIntegerObject::create(time()));
$decimal = DecimalFractionTag::createFromFloat(3.14);
$datetime = DatetimeTag::create(TextStringObject::create('2024-01-15T10:30:00Z'));