diff --git a/oid4vc-core/Cargo.toml b/oid4vc-core/Cargo.toml index a74a7a2e..681ed0bf 100644 --- a/oid4vc-core/Cargo.toml +++ b/oid4vc-core/Cargo.toml @@ -22,3 +22,9 @@ serde_urlencoded = "0.7.1" derive_more = "0.99.16" identity_credential.workspace = true futures = "0.3" + +[dev-dependencies] +ed25519-dalek = "1.0.1" +rand = "0.7" +lazy_static = "1.4.0" +derivative = "2.2.0" diff --git a/oid4vc-core/src/jwt.rs b/oid4vc-core/src/jwt.rs index 63a0a144..fdc8c025 100644 --- a/oid4vc-core/src/jwt.rs +++ b/oid4vc-core/src/jwt.rs @@ -75,14 +75,14 @@ where Ok(base64_url::encode(serde_json::to_vec(value)?.as_slice())) } -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::{ -// test_utils::{MockSubject, MockVerifier}, -// IdToken, Verify, -// }; -// use serde_json::json; +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + test_utils::{MockVerifier, TestSubject}, + Verify, + }; + use serde_json::{json, Value}; #[tokio::test] async fn test_encode() { @@ -97,26 +97,21 @@ where let subject = TestSubject::new("did:test:123".to_string(), "key_id".to_string()).unwrap(); let encoded = encode(Arc::new(subject), claims).unwrap(); -// }); -// let subject = MockSubject::new("did:mock:123".to_string(), "key_id".to_string()).unwrap(); -// let encoded = encode(Arc::new(subject), claims).await.unwrap(); + let verifier = MockVerifier::new(); + let (kid, algorithm) = extract_header(&encoded).unwrap(); + let public_key = verifier.public_key(&kid).await.unwrap(); + let decoded: Value = decode(&encoded, public_key, algorithm).unwrap(); -// let verifier = MockVerifier::new(); -// let (kid, algorithm) = extract_header(&encoded).unwrap(); -// let public_key = verifier.public_key(&kid).await.unwrap(); -// let decoded: IdToken = decode(&encoded, public_key, algorithm).unwrap(); - -// assert_eq!( -// decoded, -// IdToken::builder() -// .iss("did:example:123".to_string()) -// .sub("did:example:123".to_string()) -// .aud("did:example:456".to_string()) -// .exp(9223372036854775807i64) -// .iat(1593436422) -// .nonce("nonce".to_string()) -// .build() -// .unwrap() -// ) -// } -// } + assert_eq!( + decoded, + json!({ + "iss": "did:example:123", + "sub": "did:example:123", + "aud": "did:example:456", + "exp": 9223372036854775807i64, + "iat": 1593436422, + "nonce": "nonce", + }) + ) + } +} diff --git a/oid4vc-core/src/lib.rs b/oid4vc-core/src/lib.rs index 0f4f8a3d..e7a2b1d9 100644 --- a/oid4vc-core/src/lib.rs +++ b/oid4vc-core/src/lib.rs @@ -17,6 +17,9 @@ pub use rfc7519_claims::RFC7519Claims; use serde::Serialize; pub use subject_syntax_type::{DidMethod, SubjectSyntaxType}; +#[cfg(test)] +mod test_utils; + #[macro_export] macro_rules! builder_fn { ($name:ident, $ty:ty) => { diff --git a/oid4vc-core/src/test_utils.rs b/oid4vc-core/src/test_utils.rs new file mode 100644 index 00000000..97c948f2 --- /dev/null +++ b/oid4vc-core/src/test_utils.rs @@ -0,0 +1,68 @@ +use crate::{Sign, Subject, Verify}; +use anyhow::Result; +use async_trait::async_trait; +use derivative::{self, Derivative}; +use ed25519_dalek::{Keypair, Signature, Signer}; +use lazy_static::lazy_static; +use rand::rngs::OsRng; + +// Keypair for mocking purposes. +lazy_static! { + pub static ref TEST_KEYPAIR: Keypair = Keypair::generate(&mut OsRng); +} + +#[derive(Derivative)] +#[derivative(Default)] +pub struct TestSubject { + #[derivative(Default(value = "did_url::DID::parse(\"did:test:123\").unwrap()"))] + pub did: did_url::DID, + pub key_id: String, +} + +impl TestSubject { + pub fn new(did: String, key_id: String) -> Result { + Ok(TestSubject { + did: did_url::DID::parse(did)?, + key_id, + }) + } +} + +impl Sign for TestSubject { + fn key_id(&self) -> Option { + Some(self.key_id.clone()) + } + + fn sign(&self, message: &str) -> Result> { + let signature: Signature = TEST_KEYPAIR.sign(message.as_bytes()); + Ok(signature.to_bytes().to_vec()) + } +} + +#[async_trait] +impl Verify for TestSubject { + async fn public_key(&self, _kid: &str) -> Result> { + Ok(TEST_KEYPAIR.public.to_bytes().to_vec()) + } +} + +impl Subject for TestSubject { + fn identifier(&self) -> Result { + Ok(self.did.to_string()) + } +} + +pub struct MockVerifier; + +impl MockVerifier { + pub fn new() -> Self { + MockVerifier {} + } +} + +#[async_trait] +impl Verify for MockVerifier { + async fn public_key(&self, _kid: &str) -> Result> { + Ok(TEST_KEYPAIR.public.to_bytes().to_vec()) + } +} diff --git a/oid4vp/tests/examples/credentials/jwt_vc.json b/oid4vp/tests/examples/credentials/jwt_vc.json index 42944ee0..ec364f77 100644 --- a/oid4vp/tests/examples/credentials/jwt_vc.json +++ b/oid4vp/tests/examples/credentials/jwt_vc.json @@ -24,4 +24,4 @@ } } } -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/pd_ac_vc.json b/oid4vp/tests/examples/request/pd_ac_vc.json index 568176f7..7a4fc26e 100644 --- a/oid4vp/tests/examples/request/pd_ac_vc.json +++ b/oid4vp/tests/examples/request/pd_ac_vc.json @@ -25,4 +25,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/pd_ac_vc_sd.json b/oid4vp/tests/examples/request/pd_ac_vc_sd.json index b5483360..df26db69 100644 --- a/oid4vp/tests/examples/request/pd_ac_vc_sd.json +++ b/oid4vp/tests/examples/request/pd_ac_vc_sd.json @@ -1,39 +1,39 @@ { - "id": "example_vc_ac_sd", - "input_descriptors": [ - { - "id": "id_credential", - "format": { - "ac_vc": { - "proof_type": [ - "CLSignature2019" - ] - } - }, - "constraints": { - "limit_disclosure": "required", - "fields": [ - { - "path": [ - "$.schema_id" - ], - "filter": { - "type": "string", - "const": "did:indy:idu:test:3QowxFtwciWceMFr7WbwnM:2:BasicScheme:0\\.1" - } - }, - { - "path": [ - "$.values.first_name" - ] - }, - { - "path": [ - "$.values.last_name" - ] - } - ] - } - } - ] - } \ No newline at end of file + "id": "example_vc_ac_sd", + "input_descriptors": [ + { + "id": "id_credential", + "format": { + "ac_vc": { + "proof_type": [ + "CLSignature2019" + ] + } + }, + "constraints": { + "limit_disclosure": "required", + "fields": [ + { + "path": [ + "$.schema_id" + ], + "filter": { + "type": "string", + "const": "did:indy:idu:test:3QowxFtwciWceMFr7WbwnM:2:BasicScheme:0\\.1" + } + }, + { + "path": [ + "$.values.first_name" + ] + }, + { + "path": [ + "$.values.last_name" + ] + } + ] + } + } + ] +} diff --git a/oid4vp/tests/examples/request/pd_jwt_vc.json b/oid4vp/tests/examples/request/pd_jwt_vc.json index 7492cace..2abc2fef 100644 --- a/oid4vp/tests/examples/request/pd_jwt_vc.json +++ b/oid4vp/tests/examples/request/pd_jwt_vc.json @@ -27,4 +27,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/pd_ldp_vc.json b/oid4vp/tests/examples/request/pd_ldp_vc.json index 9a09cb4b..ecb0702a 100644 --- a/oid4vp/tests/examples/request/pd_ldp_vc.json +++ b/oid4vp/tests/examples/request/pd_ldp_vc.json @@ -27,4 +27,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/pd_mdl_iso_cbor.json b/oid4vp/tests/examples/request/pd_mdl_iso_cbor.json index 5860b59c..b459f663 100644 --- a/oid4vp/tests/examples/request/pd_mdl_iso_cbor.json +++ b/oid4vp/tests/examples/request/pd_mdl_iso_cbor.json @@ -54,4 +54,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/vp_token_type_and_claims.json b/oid4vp/tests/examples/request/vp_token_type_and_claims.json index 4061120c..ce6b4da0 100644 --- a/oid4vp/tests/examples/request/vp_token_type_and_claims.json +++ b/oid4vp/tests/examples/request/vp_token_type_and_claims.json @@ -41,4 +41,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/request/vp_token_type_only.json b/oid4vp/tests/examples/request/vp_token_type_only.json index 11579959..f1a74b1e 100644 --- a/oid4vp/tests/examples/request/vp_token_type_only.json +++ b/oid4vp/tests/examples/request/vp_token_type_only.json @@ -25,4 +25,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/presentation_submission.json b/oid4vp/tests/examples/response/presentation_submission.json index f0ddfa2f..6761f279 100644 --- a/oid4vp/tests/examples/response/presentation_submission.json +++ b/oid4vp/tests/examples/response/presentation_submission.json @@ -12,4 +12,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/presentation_submission_multiple_vps.json b/oid4vp/tests/examples/response/presentation_submission_multiple_vps.json index 30c0128d..e9e95d36 100644 --- a/oid4vp/tests/examples/response/presentation_submission_multiple_vps.json +++ b/oid4vp/tests/examples/response/presentation_submission_multiple_vps.json @@ -21,4 +21,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/ps_ac_vc_sd.json b/oid4vp/tests/examples/response/ps_ac_vc_sd.json index 59eee37c..1f209413 100644 --- a/oid4vp/tests/examples/response/ps_ac_vc_sd.json +++ b/oid4vp/tests/examples/response/ps_ac_vc_sd.json @@ -12,4 +12,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/ps_jwt_vc.json b/oid4vp/tests/examples/response/ps_jwt_vc.json index bb16f172..fb018c8d 100644 --- a/oid4vp/tests/examples/response/ps_jwt_vc.json +++ b/oid4vp/tests/examples/response/ps_jwt_vc.json @@ -2,14 +2,14 @@ "definition_id": "example_jwt_vc", "id": "example_jwt_vc_presentation_submission", "descriptor_map": [ - { - "id": "id_credential", - "path": "$", - "format": "jwt_vp_json", - "path_nested": { - "path": "$.vp.verifiableCredential[0]", - "format": "jwt_vc_json" + { + "id": "id_credential", + "path": "$", + "format": "jwt_vp_json", + "path_nested": { + "path": "$.vp.verifiableCredential[0]", + "format": "jwt_vc_json" + } } - } ] - } \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/ps_ldp_vc.json b/oid4vp/tests/examples/response/ps_ldp_vc.json index a859d56d..40cc14f9 100644 --- a/oid4vp/tests/examples/response/ps_ldp_vc.json +++ b/oid4vp/tests/examples/response/ps_ldp_vc.json @@ -12,4 +12,4 @@ } } ] -} \ No newline at end of file +} diff --git a/oid4vp/tests/examples/response/ps_mdl_iso_cbor.json b/oid4vp/tests/examples/response/ps_mdl_iso_cbor.json index 4d0e6c8f..7435928b 100644 --- a/oid4vp/tests/examples/response/ps_mdl_iso_cbor.json +++ b/oid4vp/tests/examples/response/ps_mdl_iso_cbor.json @@ -8,4 +8,4 @@ "path": "$" } ] -} \ No newline at end of file +}