From 9945b242197623e093d0ab311577c4cdcd8a565b Mon Sep 17 00:00:00 2001 From: azizmukhtorjonov Date: Tue, 10 Sep 2024 16:20:39 +0500 Subject: [PATCH 1/5] Fix bug in verification of presentation with key binding that uses different algorithm. Resolves #33 Signed-off-by: Aziz Mukhtorjonov --- src/verifier.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/verifier.rs b/src/verifier.rs index e737212..43580e5 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -69,6 +69,7 @@ impl SDJWTVerifier { verifier.verified_claims = verifier.extract_sd_claims()?; if let (Some(expected_aud), Some(expected_nonce)) = (&expected_aud, &expected_nonce) { + let sign_alg = crate::SDJWTCommon::decode_header_and_get_sign_algorithm(&verifier.sd_jwt_engine.unverified_input_key_binding_jwt.clone().unwrap().to_string()); verifier.verify_key_binding_jwt( expected_aud.to_owned(), expected_nonce.to_owned(), @@ -387,6 +388,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!({ @@ -724,4 +736,63 @@ mod tests { .verified_claims; assert_eq!(user_claims, verified_claims); } + #[test] + fn verify_es256_and_ed25519_algorithms_signings() { + + 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; + assert_eq!(user_claims, verified_claims); + } } From 64f787eeb2f6e0c93fad14831e17eab6a7898176 Mon Sep 17 00:00:00 2001 From: azizmukhtorjonov Date: Tue, 10 Sep 2024 16:21:08 +0500 Subject: [PATCH 2/5] Fix bug in verification of presentation with key binding that uses different algorithm. Resolves #33 Signed-off-by: Aziz Mukhtorjonov --- src/verifier.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/verifier.rs b/src/verifier.rs index 43580e5..4163808 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -793,6 +793,18 @@ mod tests { ) .unwrap() .verified_claims; - assert_eq!(user_claims, 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).expect("Valid JSON"), + }, + "sub": user_claims["sub"].clone(), + "address": user_claims["address"].clone(), + }); + + assert_eq!(claims_to_check, verified_claims); } } From 0e278f35a459c0ccb308437c0adbb6258db2e01a Mon Sep 17 00:00:00 2001 From: Aziz Mukhtorjonov Date: Tue, 10 Sep 2024 18:48:28 +0500 Subject: [PATCH 3/5] Fix json formatting, change name of test function & change expect handling to unwrap; Issue #33 Signed-off-by: Aziz Mukhtorjonov --- src/verifier.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/verifier.rs b/src/verifier.rs index 4163808..5624e80 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -69,7 +69,13 @@ impl SDJWTVerifier { verifier.verified_claims = verifier.extract_sd_claims()?; if let (Some(expected_aud), Some(expected_nonce)) = (&expected_aud, &expected_nonce) { - let sign_alg = crate::SDJWTCommon::decode_header_and_get_sign_algorithm(&verifier.sd_jwt_engine.unverified_input_key_binding_jwt.clone().unwrap().to_string()); + let sign_alg = verifier.sd_jwt_engine.unverified_input_key_binding_jwt + .clone() + .map(|value| value.to_string()) + .and_then(|value| { + SDJWTCommon::decode_header_and_get_sign_algorithm(&value) + } ); + verifier.verify_key_binding_jwt( expected_aud.to_owned(), expected_nonce.to_owned(), @@ -397,7 +403,7 @@ mod tests { "kid": "52128f2e-900e-414e-81c3-0b5f86f0f7b3", "kty": "OKP", "x": "24QLWXJ18wtbg3k_MDGhGM17Xh39UftuxbwJZzRLzkA" -}"#; + }"#; #[test] fn verify_full_presentation() { @@ -737,7 +743,7 @@ mod tests { assert_eq!(user_claims, verified_claims); } #[test] - fn verify_es256_and_ed25519_algorithms_signings() { + fn verify_when_sd_jwt_es256_key_binding_eddsa() { let user_claims = json!({ "address": { @@ -799,7 +805,7 @@ mod tests { "iat": user_claims["iat"].clone(), "exp": user_claims["exp"].clone(), "cnf": { - "jwk": serde_json::from_str::(HOLDER_JWK_KEY_ED25519).expect("Valid JSON"), + "jwk": serde_json::from_str::(HOLDER_JWK_KEY_ED25519).unwrap(), }, "sub": user_claims["sub"].clone(), "address": user_claims["address"].clone(), From 53ef9b84bdc5a759497f6029aa4066124379db64 Mon Sep 17 00:00:00 2001 From: Aziz Mukhtorjonov Date: Wed, 11 Sep 2024 10:29:18 +0500 Subject: [PATCH 4/5] Change test function name, fix lint. Issue #33 Signed-off-by: Aziz Mukhtorjonov --- src/verifier.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/verifier.rs b/src/verifier.rs index 5624e80..cc3c36d 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -74,7 +74,7 @@ impl SDJWTVerifier { .map(|value| value.to_string()) .and_then(|value| { SDJWTCommon::decode_header_and_get_sign_algorithm(&value) - } ); + }); verifier.verify_key_binding_jwt( expected_aud.to_owned(), @@ -743,7 +743,7 @@ mod tests { assert_eq!(user_claims, verified_claims); } #[test] - fn verify_when_sd_jwt_es256_key_binding_eddsa() { + fn verify_presentation_when_sd_jwt_uses_es256_and_key_binding_uses_eddsa() { let user_claims = json!({ "address": { From aebb4c5c28110c9e706798f867064b2a2e0b39fa Mon Sep 17 00:00:00 2001 From: Aziz Mukhtorjonov Date: Thu, 3 Oct 2024 11:49:04 +0500 Subject: [PATCH 5/5] issue-33: remove cloning & use references instead Signed-off-by: Aziz Mukhtorjonov --- src/verifier.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/verifier.rs b/src/verifier.rs index cc3c36d..fb92934 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -70,8 +70,7 @@ impl SDJWTVerifier { if let (Some(expected_aud), Some(expected_nonce)) = (&expected_aud, &expected_nonce) { let sign_alg = verifier.sd_jwt_engine.unverified_input_key_binding_jwt - .clone() - .map(|value| value.to_string()) + .as_ref() .and_then(|value| { SDJWTCommon::decode_header_and_get_sign_algorithm(&value) });