Skip to content

HashCalculator Class

Computes the detached-signature hashes an ID Token carries for values delivered beside it: at_hash for an access token and c_hash for an authorization code.

C#
public static class HashCalculator

Inheritance System.Object → HashCalculator

Remarks

OpenID Connect Core 1.0 gives one recipe for all of them, in section 3.2.2.9 for at_hash and section 3.3.2.10 for c_hash: hash the ASCII octets of the value with the algorithm JWA pairs with the alg of the ID Token's own JOSE header, take the left-most half of the digest, and base64url-encode it. The point of the construction is to bind the ID Token to the value: an attacker who swaps the code or the access token for one of their own is caught, because the signed ID Token still carries the hash of the original. Which is why the issuing and the verifying side must compute it identically - they live in different packages, and this is the single place both take it from.

Methods

HashCalculator.Compute(string, string) Method

Returns the base64url-encoded left-most half of value's digest, or null when signingAlgorithm has no hash paired with it.

C#
public static string? Compute(string signingAlgorithm, string value);

Parameters

signingAlgorithm System.String

The alg from the ID Token's JOSE header.

value System.String

The access token, authorization code or state to bind.

Returns

System.String

Remarks

The pairing is by digest size rather than by signature family, because every JWS algorithm name ends in the size of the hash it uses: RS256, PS256, ES256 and HS256 all pair with SHA-256, and so on up. ES512 is the one that looks irregular and is not - it signs with SHA-512, matching its name rather than its P-521 curve. A null result is a real answer, not a failure to compute: none has no digest, and neither does an algorithm this library does not recognise. The two sides then part ways, which is why the decision is left here to the caller - an issuer omits the claim, while a client MUST refuse to treat the binding as satisfied, since "no hash was computable" and "the hash matched" would otherwise look the same to it.