IKeyCustodian Interface
Host-implemented custodian for the external private keys the library never holds in process: they live in an
HSM, a cloud KMS, or a vault transit engine, and only the private operations cross the boundary. A key
published public-only routes its private operation here by kid: SIGNING for a signing key, and for a
decryption key an RSA/symmetric UNWRAP or an ECDH-ES AGREEMENT. The public operations - signature
verification, and wrapping a CEK with the recipient's public half - stay in process and never reach the
custodian. Wire it with AddCustodian and a placement call; a host with no external keys leaves it
unregistered.
public interface IKeyCustodianRemarks
Every private operation is addressed by kid, the custodian's handle for that exact key version,
identical to the published key's kid - there is no separate identifier and no mapping. The public
halves the library publishes come from GetKeyVersionsAsync(string, CancellationToken), which enumerates a named key's
versions so a rotation can overlap. The implementation never receives or returns private key material, and
only needs to implement the private operations its own keys require: a signing-only custodian leaves unwrap
and agree unreachable, and a decryption-only custodian leaves sign unreachable. Direct encryption (dir)
and password-based key management (PBES2) have no external form - the CEK is the secret itself, or is derived
from it by a password KDF - so they are never routed here and fail closed. Every operation is a round-trip to
the custodian, so the contract returns System.Threading.Tasks.Task<> throughout.
Methods
IKeyCustodian.AgreeKeyAsync(string, string, JsonWebKey, CancellationToken) Method
Performs the ECDH-ES key agreement between the recipient's static private key (held by the custodian) and the originator's ephemeral public key, returning the raw shared secret Z. The library runs the Concat KDF over Z and any AES key unwrap, so those steps never leave it.
System.Threading.Tasks.Task<byte[]> AgreeKeyAsync(string keyId, string algorithm, Abblix.Jwt.JsonWebKey ephemeralPublicKey, System.Threading.CancellationToken cancellationToken);Parameters
keyId System.String
The custodian's handle for the recipient key version.
algorithm System.String
The JWE alg value (ECDH-ES or an ECDH-ES+A*KW variant).
ephemeralPublicKey JsonWebKey
The originator's ephemeral public key from the epk header.
cancellationToken System.Threading.CancellationToken
Cancels the round-trip to the custodian.
Returns
System.Threading.Tasks.Task<System.Byte[]>
The raw ECDH shared secret Z (the agreement's field-sized X-coordinate).
IKeyCustodian.GetKeyVersionsAsync(string, CancellationToken) Method
Enumerates every current version of the key named keyName as its public half, each
carrying the version-specific kid that routes a private operation back to that exact version, plus
the custodian's creation time for that version. A custodian that does not version its keys yields a single
element; a version-aware custodian (Vault Transit, Azure Key Vault) yields every version, which a rotation
policy overlaps for zero-downtime key rollover. Called at publication time, so JWKS publishing and local
signature verification run against the returned public halves and never touch the custodian on the hot path.
System.Collections.Generic.IAsyncEnumerable<Abblix.Jwt.KeyVersion> GetKeyVersionsAsync(string keyName, System.Threading.CancellationToken cancellationToken);Parameters
keyName System.String
The custodian's name for the logical key whose versions to enumerate.
cancellationToken System.Threading.CancellationToken
Cancels the round-trip to the custodian.
Returns
System.Collections.Generic.IAsyncEnumerable<KeyVersion>
The key's versions, each a public-only KeyVersion.
IKeyCustodian.SignAsync(string, string, byte[], CancellationToken) Method
Signs data with a signing key held by the custodian, returning the signature in the JWS wire format for algorithm. Called for a signing key the library holds public-only.
System.Threading.Tasks.Task<byte[]> SignAsync(string keyId, string algorithm, byte[] data, System.Threading.CancellationToken cancellationToken);Parameters
keyId System.String
The custodian's handle for the signing key version.
algorithm System.String
The JWS algorithm identifier (e.g. RS256, ES256) the signature must use.
data System.Byte[]
The signing input bytes, BASE64URL(header) + '.' + BASE64URL(payload).
cancellationToken System.Threading.CancellationToken
Cancels the round-trip to the custodian.
Returns
System.Threading.Tasks.Task<System.Byte[]>
The raw signature bytes in JWS wire format for the algorithm.
IKeyCustodian.UnwrapKeyAsync(string, string, JsonWebTokenHeader, byte[], CancellationToken) Method
Recovers a Content Encryption Key: an RSA decryption (RSA-OAEP / RSA-OAEP-256 / RSA1_5) or a symmetric unwrap (AES-KW / AES-GCM-KW), selected by algorithm.
System.Threading.Tasks.Task<byte[]?> UnwrapKeyAsync(string keyId, string algorithm, Abblix.Jwt.JsonWebTokenHeader header, byte[] encryptedKey, System.Threading.CancellationToken cancellationToken);Parameters
keyId System.String
The custodian's handle for the recipient key version.
algorithm System.String
The JWE alg value identifying the key-management operation.
header JsonWebTokenHeader
The JWE header; AES-GCM-KW reads its iv / tag parameters from it.
encryptedKey System.Byte[]
The wrapped or RSA-encrypted CEK from the JWE Encrypted Key.
cancellationToken System.Threading.CancellationToken
Cancels the round-trip to the custodian.
Returns
System.Threading.Tasks.Task<System.Byte[]>
The recovered CEK, or null on any failure. Returning null rather than throwing keeps a
decryption failure indistinguishable from a wrong key, which the RFC 7516 §11.5 mitigation upstream
relies on to close the Bleichenbacher / padding-oracle side channel.