diff --git a/src/verifier.rs b/src/verifier.rs index 9b92e9a..31963f2 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -73,6 +73,12 @@ impl SDJWTVerifier { verifier.verified_claims = verifier.extract_sd_claims()?; if let (Some(expected_aud), Some(expected_nonce)) = (&expected_aud, &expected_nonce) { + let sign_alg = verifier.sd_jwt_engine.unverified_input_key_binding_jwt + .as_ref() + .and_then(|value| { + SDJWTCommon::decode_header_and_get_sign_algorithm(&value) + }); + verifier.verify_key_binding_jwt( expected_aud.to_owned(), expected_nonce.to_owned(), @@ -391,6 +397,17 @@ mod tests { const PRIVATE_ISSUER_ED25519_PEM: &str = "-----BEGIN PRIVATE KEY-----\nMFECAQEwBQYDK2VwBCIEIF93k6rxZ8W38cm0rOwfGdH+YY3k10hP+7gd0falPLg0\ngSEAdW31QyWzfed4EPcw1rYuUa1QU+fXEL0HhdAfYZRkihc=\n-----END PRIVATE KEY-----\n"; const PUBLIC_ISSUER_ED25519_PEM: &str = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAdW31QyWzfed4EPcw1rYuUa1QU+fXEL0HhdAfYZRkihc=\n-----END PUBLIC KEY-----\n"; + // EdDSA (Ed25519) + const HOLDER_KEY_ED25519: &str = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIOeIDnHHMoPCUTiq206gR+FdCdNtc31SzF1nKX31hvhd\n-----END PRIVATE KEY-----"; + + const HOLDER_JWK_KEY_ED25519: &str = r#"{ + "alg": "EdDSA", + "crv": "Ed25519", + "kid": "52128f2e-900e-414e-81c3-0b5f86f0f7b3", + "kty": "OKP", + "x": "24QLWXJ18wtbg3k_MDGhGM17Xh39UftuxbwJZzRLzkA" + }"#; + #[test] fn verify_full_presentation() { let user_claims = json!({ @@ -728,4 +745,75 @@ mod tests { .verified_claims; assert_eq!(user_claims, verified_claims); } + #[test] + fn verify_presentation_when_sd_jwt_uses_es256_and_key_binding_uses_eddsa() { + + let user_claims = json!({ + "address": { + "street_address": "Schulstr. 12", + "locality": "Schulpforta", + "region": "Sachsen-Anhalt", + "country": "DE" + }, + "exp": 1883000000, + "iat": 1683000000, + "iss": "https://example.com/issuer", + "sub": "6c5c0a49-b589-431d-bae7-219122a9ec2c", + + }); + + let private_issuer_bytes = PRIVATE_ISSUER_PEM.as_bytes(); + let issuer_key = EncodingKey::from_ec_pem(private_issuer_bytes).unwrap(); + + let mut issuer = SDJWTIssuer::new(issuer_key, Some("ES256".to_string())); + + let sd_jwt = issuer.issue_sd_jwt( + user_claims.clone(), + ClaimsForSelectiveDisclosureStrategy::AllLevels, + Some(serde_json::from_str(HOLDER_JWK_KEY_ED25519).unwrap()), + false, + SDJWTSerializationFormat::JSON, // Changed to Json format + ).unwrap(); + + let private_holder_bytes = HOLDER_KEY_ED25519.as_bytes(); + let holder_key = EncodingKey::from_ed_pem(private_holder_bytes).unwrap(); + + let nonce = Some(String::from("testNonce")); + let aud = Some(String::from("testAud")); + + let mut holder = SDJWTHolder::new(sd_jwt.clone(), SDJWTSerializationFormat::JSON).unwrap(); // Changed to Json format + let presentation = holder.create_presentation( + user_claims.as_object().unwrap().clone(), + nonce.clone(), + aud.clone(), + Some(holder_key), + Some("EdDSA".to_string()) + ) + .unwrap(); + let verified_claims = SDJWTVerifier::new( + presentation, + Box::new(|_, _| { + let public_issuer_bytes = PUBLIC_ISSUER_PEM.as_bytes(); + DecodingKey::from_ec_pem(public_issuer_bytes).unwrap() + }), + aud.clone(), + nonce.clone(), + SDJWTSerializationFormat::JSON, // Changed to Json format + ) + .unwrap() + .verified_claims; + + let claims_to_check = json!({ + "iss": user_claims["iss"].clone(), + "iat": user_claims["iat"].clone(), + "exp": user_claims["exp"].clone(), + "cnf": { + "jwk": serde_json::from_str::(HOLDER_JWK_KEY_ED25519).unwrap(), + }, + "sub": user_claims["sub"].clone(), + "address": user_claims["address"].clone(), + }); + + assert_eq!(claims_to_check, verified_claims); + } }