Reading headers¶
cbor-php carries the two header buckets; RFC 9052 decides what they mean. Cose\Structure\CoseHeaders
applies the second part to any COSE message:
use Cose\Structure\CoseHeaders;
$headers = CoseHeaders::fromMessage($coseSign1); // any CBOR\Tag\Cose*Tag
$headers->getProtectedHeaderParameter(1); // ?CBORObject, protected bucket only
$headers->getUnprotectedHeaderParameter(4); // ?CBORObject, unprotected bucket only
$headers->getHeaderParameter(1); // ?CBORObject, protected first, then unprotected
$headers->getProtectedHeaderAsMap(); // MapObject, decoded and checked
What it enforces¶
Why the raw MapObject accessors are not enough:
- A label is an integer or a text string
(§1.5), and the two are different labels.
cbor-php normalizes the integer
1, the text string"1"and the byte stringh'31'to the same map offset, so$map->has(1)answerstruefor all three.getProtectedHeaderParameter(1)matches the type as well, and only the integer1is the algorithm parameter. - A byte-string key is not a label at all and makes the header malformed.
- The zero-length protected header is accepted
(§3: "Recipients MUST accept both a
zero-length byte string and a zero-length map encoded in a byte string"), and trailing bytes inside
the protected bucket are not: the CDDL
bstr .cbor header_mapholds exactly one item. - The protected bucket wins a combined lookup, because that is the value the signature or the MAC commits to.
For a per-signer or per-recipient bucket, CoseSignature and CoseRecipient expose the same lookups; see
COSE_Sign and COSE_Encrypt; for a header map
you assembled yourself, use CoseHeaders::of($protectedBytes, $unprotectedMap).
Cose\Structure\HeaderMapHelper holds the same rules as static functions, including encodeProtected()
and assertTagNumber().
The nesting bound¶
The protected header is decoded with a decoder bounded to
CoseHeaders::DEFAULT_PROTECTED_HEADER_MAX_DEPTH (32) levels of nesting. Pass your own Decoder when a
header carries custom CBOR tags, or a different $maxDepth when 32 is not the right bound:
use CBOR\Decoder;
use CBOR\OtherObject\OtherObjectManager;
use CBOR\Tag\TagManager;
$customDecoder = Decoder::create(
TagManager::create()->add(MyCustomTag::class),
OtherObjectManager::create(),
32
);
$headers = CoseHeaders::fromMessage($coseSign1, $customDecoder);
The parameters with a rule of their own¶
Some header parameters come with a rule that a raw lookup cannot apply, and have a typed accessor: typ
and CWT Claims are described with CBOR Web Tokens, the
X.509 parameters in X.509 header parameters, the hash envelope parameters
in Hash envelope, the countersignature labels in
Countersignatures, the receipts, vds and vdp parameters in
Receipts, and the ECDH and HKDF parameters of a COSE_recipient in
Key management.