-
Notifications
You must be signed in to change notification settings - Fork 131
Description
Question about CBOR encoding of PublicKeyCredentialDescriptor.id in test_exclude_credentials_max
Description
Hello,
I am currently facing an issue while executing the following test:
tests/device/test_client.py::test_exclude_credentials_max
On the FIDO side, the device returns INVALID_CBOR.
After investigating, the issue appears to be related to the encoding of the 3rd key (0x03) of the CBOR APDU — specifically the allowList, which is defined as:
Array of PublicKeyCredentialDescriptor
On the applet side, I am expecting the id field inside PublicKeyCredentialDescriptor to be encoded strictly as CBOR byte string (major type 2).
However, in this specific test case, I noticed that the id value is encoded as a CBOR array, which causes the applet to reject the request and return INVALID_CBOR.
This seems to be the only test that encodes the id field in this way.
🔹 Example 1 — Failing Scenario (test_exclude_credentials_max)
A6 # map(6)
01 # unsigned(1)
6B # text(11)
6578616D706C652E636F6D # "[example.com](http://example.com/)"
02 # unsigned(2)
58 20 # bytes(32)
0000000000000000000000000000000000000000000000000000000000000000 # "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
03 # unsigned(3)
97 # array(23)
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0) # The Field which is expected as byte encoding
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
A2 # map(2)
62 # text(2)
6964 # "id"
80 # array(0)
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
05 # unsigned(5)
A1 # map(1)
62 # text(2)
7570 # "up"
F4 # primitive(20)
06 # unsigned(6)
58 20 # bytes(32)
5BFDAA00DD8B49DB9CFDC9671B9D5C045909A127C57F59E3548DA8A593AC6F4A # "[\xFD\xAA\u0000\u074BIۜ\xFD\xC9g\e\x9D\\\u0004Y\t\xA1'\xC5\u007FY\xE3T\x8D\xA8\xA5\x93\xACoJ"
07 # unsigned(7)
02 # unsigned(2)
🔹 Example 2 — Passing Scenario (Reference Test)
A6 # map(6)
01 # unsigned(1)
6B # text(11)
6578616D706C652E636F6D # "[example.com](http://example.com/)"
02 # unsigned(2)
58 20 # bytes(32)
0000000000000000000000000000000000000000000000000000000000000000 # "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
03 # unsigned(3)
81 # array(1)
A2 # map(2)
62 # text(2)
6964 # "id"
58 60 # bytes(96) #Here is encoded as bytes data CBOR
3EC9BCEC825A84CF6F364073A8B6622921D1890CF2E6931D8E8B84C1E9E8AD0EE68B200237FD0FC4659136C6AE9953D1931F10C945DC72657E829B6CD043AA082F9CEBBFD78FCAE6BDBA707348368F0575E32097366104A8E0BF06F597A5BE98 # ">ɼ\xEC\x82Z\x84\xCFo6@s\xA8\xB6b)!щ\f\xF2\xE6\x93\u001D\x8E\x8B\x84\xC1\xE9\xE8\xAD\u000E\xE6\x8B \u00027\xFD\u000F\xC4e\x916Ʈ\x99Sѓ\u001F\u0010\xC9E\xDCre~\x82\x9Bl\xD0C\xAA\b/\x9C\xEB\xBF\u05CF\xCA潺psH6\x8F\u0005u\xE3 \x976a\u0004\xA8\xE0\xBF\u0006\xF5\x97\xA5\xBE\x98"
64 # text(4)
74797065 # "type"
6A # text(10)
7075626C69632D6B6579 # "public-key"
05 # unsigned(5)
A1 # map(1)
62 # text(2)
7570 # "up"
F4 # primitive(20)
06 # unsigned(6)
58 20 # bytes(32)
8B4DEA1BC0FCF32D4FE33F844ED0C65F355800CD386C2B654C2E97409F4C35C9 # "\x8BM\xEA\e\xC0\xFC\xF3-O\xE3?\x84N\xD0\xC6_5X\u0000\xCD8l+eL.\x97@\x9FL5\xC9"
07 # unsigned(7)
02 # unsigned(2)
Question
Is the purpose of this test scenario to intentionally verify that authenticators correctly reject non–byte-string encodings of the id field?
From my understanding of the FIDO2 / CTAP specification, the id field in PublicKeyCredentialDescriptor should be a byte sequence. However, the specification does not explicitly clarify whether other CBOR data types are allowed or whether it must strictly be a CBOR byte string.
So the core question is:
Should PublicKeyCredentialDescriptor.id be encoded strictly as a CBOR byte string (major type 2),
or is it expected to accept other CBOR data types (e.g., array) as valid encodings?
Conclusion
At this stage, the behavior appears to be a matter of interpretation.
It remains a disputable case whether the id must strictly be CBOR byte string only, or whether other data encodings are acceptable according to the intended compliance level of the test.
Clarification on the expected behavior would be greatly appreciated.
Thank you.