openid / openid/OpenID4VP

`x509_hash`: is the comparison on the string or the decoded bytes?

Open
#768 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Shell
Stars
112
Forks
38
Avg merge
12d 19h
Merged PRs (30d)
4

Description

Section 5.9.3 says of the x509_hash Client Identifier Prefix:

the original Client Identifier (the part without the x509_hash: prefix) MUST be a hash and match the hash of the leaf certificate passed with the request

and

The value of x509_hash is the base64url-encoded value of the SHA-256 hash of the DER-encoded X.509 certificate.

I could not find text saying whether "match the hash" means an exact comparison of the encoded string, or a comparison of bytes after decoding the identifier. Both readings satisfy the sentence, and they do not accept the same inputs.

A 32 byte digest encodes to 43 base64url characters. The first 42 carry 252 bits, so the 43rd carries the remaining 4 bits of the digest plus 2 bits that are not part of it. Canonical encoding sets those 2 bits to zero, but a decoder that discards them, which is the default behavior in several common runtimes, accepts three other final characters as the same digest. So a Wallet comparing decoded bytes accepts identifiers that a Wallet comparing strings rejects, for the same certificate.

The consequence does not stop at admission, because Section 14.11 forbids normalizing the value:

Wallets MUST always use the full Client Identifier, including the prefix if provided, within the context of the Wallet or its responses to identify the client. This refers in particular to places where the Client Identifier is used in [RFC6749] and in the presentation returned to the Verifier.

A Wallet that accepted a non-canonical identifier must therefore carry it into the presentation as the audience, unchanged. A Verifier that computes its own canonical value and compares strings will not recognize that audience and will reject a presentation it asked for.

The document does state comparison semantics elsewhere when it chooses to. For expected_origins, Appendix A.2 says values are

treated as a string, using simple string comparison, without any prior processing or interpretation

Whether that is the right rule for origins specifically is a separate question I am not raising here. The point is only that the comparison is stated at all, and nothing equivalent appears at x509_hash.

So: should a Wallet compute the base64url encoding of the certificate hash and compare strings exactly, or decode the identifier and compare bytes? And if the former, should a non-canonical encoding be rejected rather than merely failing to match?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read Section 5.9.3, Section 14.11, and Appendix A.2 together to compare the stated comparison and normalization rules. Resolve whether x509_hash uses exact canonical string comparison or decoded-byte comparison, and specify how non-canonical encodings are handled.

Written by the indexing model from the issue text.

Assessment

Domain
cryptography, documentation, security
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.