Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SD-JWT for VC should use JWSHelper to verify the issuer JWT #316

Open
Zicchio opened this issue Jan 2, 2025 · 0 comments
Open

SD-JWT for VC should use JWSHelper to verify the issuer JWT #316

Zicchio opened this issue Jan 2, 2025 · 0 comments
Assignees
Milestone

Comments

@Zicchio
Copy link
Collaborator

Zicchio commented Jan 2, 2025

Currently, the SD-JWT for VC module tries to recover the issuer public key of the SD-JWT.
(1) First, the module search for a valid key indentifier from the jwt header (kid, x5c, trust_chain, etc).

def get_signing_key(self) -> ECKey | RSAKey | dict | KeyIdentifier_T:
return extract_key_identifier(self.sdjwt.issuer_jwt.header)

(2) then it tries to match the identifier with the available public keys whitelisted from the trust evaluation mehcanism, here
def find_vp_token_key(token_parser: VpTokenParser, key_source: TrustEvaluator) -> JWK:
"""
:param token_parser: the token parser instance.
:type token_parser: VpTokenParser
:param key_source: the key source instance.
:type key_source: TrustEvaluator
:raises KidNotFoundError: if no key is found.
:raises NotImplementedError: if the key is not in a comptible format.
:returns: a JWK instance.
:rtype: JWK
"""
issuer = token_parser.get_issuer_name()
trusted_pub_keys = key_source.get_public_keys(issuer)
verification_key = token_parser.get_signing_key()
if isinstance(verification_key, str):
return find_jwk_by_kid(verification_key, trusted_pub_keys)
if isinstance(verification_key, dict):
raise NotImplementedError("TODO: matching of public key (ex. from x5c) with keys from trust source")
raise Exception(f"invalid state: key with type {type(verification_key)}")

(3) Finally, after a candidate key is identified, it is then used for the issuer jwt verification, here
def verify_signature(self, public_key: ECKey | RSAKey | dict ) -> None:
return self.sdjwt.verify_issuer_jwt_signature(public_key)

However, after PR #315, the flow above has been replicated and stabilized in the JWSHelper class, which now will extract (or match) the valid verifying key form the token header with one of the whitelisted set provided in the class constructor.

def _select_verifying_key(self, header: dict) -> dict | None:
available_keys = [key.to_dict() for key in self.jwks]
# case 1: can be found by header
if "kid" in header:
if (verifying_key := find_jwk_by_kid(available_keys, header["kid"])):
return verifying_key
# case 2: the token is self contained, and the verification key matches one of the key in the whitelist
if (self_contained_claims_key_pair := find_self_contained_key(header)):
# check if the self contained key matches a trusted jwk
candidate_key = self_contained_claims_key_pair[0]
if (verifying_key := find_jwk_by_thumbprint(available_keys, candidate_key.thumbprint)):
return verifying_key
# case 3: if only one key and there is no header claim that can identitfy any key, than that MUST
# be the only valid CANDIDATE key for signature verification
if len(self.jwks) == 1:
return self.jwks[0].to_dict()
return None

As such, the SD-JWT for VC module should be refactored to use the new JWSHelper in order to remove the duplicated code and responsability concerning the identification of the issuer public key and its usage for token verification.

For history and completeness: this issue here described is linked with #305 (comment) and a refactoring to use JWSHelper would also solve the the problems declared in that comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

No branches or pull requests

3 participants