Skip to content

Commit

Permalink
Add ContextLoader struct and parameter
Browse files Browse the repository at this point in the history
- First (optionally) use StaticLoader, and then second (optionally)
  check a set of custom-specified context objects.
- ContextLoader::default() gives behavior equivalent to StaticLoader.
  • Loading branch information
vdods authored May 18, 2022
1 parent bafe7a5 commit 6a94e2b
Show file tree
Hide file tree
Showing 16 changed files with 533 additions and 270 deletions.
22 changes: 12 additions & 10 deletions did-ethr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,34 +446,35 @@ mod tests {
issue_options.verification_method = Some(URI::String(did.to_string() + "#controller"));
}
eprintln!("vm {:?}", issue_options.verification_method);
let mut context_loader = ssi::jsonld::ContextLoader::default();
let vc_no_proof = vc.clone();
let proof = vc
.generate_proof(&key, &issue_options, &DIDEthr)
.generate_proof(&key, &issue_options, &DIDEthr, &mut context_loader)
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDEthr).await;
let verification_result = vc.verify(None, &DIDEthr, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer property is used for verification
let mut vc_bad_issuer = vc.clone();
vc_bad_issuer.issuer = Some(Issuer::URI(URI::String("did:example:bad".to_string())));
assert!(vc_bad_issuer.verify(None, &DIDEthr).await.errors.len() > 0);
assert!(vc_bad_issuer.verify(None, &DIDEthr, &mut context_loader).await.errors.len() > 0);

// Check that proof JWK must match proof verificationMethod
let mut vc_wrong_key = vc_no_proof.clone();
let other_key = JWK::generate_ed25519().unwrap();
use ssi::ldp::ProofSuite;
let proof_bad = ssi::ldp::Ed25519BLAKE2BDigestSize20Base58CheckEncodedSignature2021
.sign(&vc_no_proof, &issue_options, &DIDEthr, &other_key, None)
.sign(&vc_no_proof, &issue_options, &DIDEthr, &mut context_loader, &other_key, None)
.await
.unwrap();
vc_wrong_key.add_proof(proof_bad);
vc_wrong_key.validate().unwrap();
assert!(vc_wrong_key.verify(None, &DIDEthr).await.errors.len() > 0);
assert!(vc_wrong_key.verify(None, &DIDEthr, &mut context_loader).await.errors.len() > 0);

// Make it into a VP
use ssi::one_or_many::OneOrMany;
Expand All @@ -497,13 +498,13 @@ mod tests {
vp_issue_options.verification_method = Some(URI::String(did.to_string() + "#controller"));
vp_issue_options.proof_purpose = Some(ProofPurpose::Authentication);
let vp_proof = vp
.generate_proof(&key, &vp_issue_options, &DIDEthr)
.generate_proof(&key, &vp_issue_options, &DIDEthr, &mut context_loader)
.await
.unwrap();
vp.add_proof(vp_proof);
println!("VP: {}", serde_json::to_string_pretty(&vp).unwrap());
vp.validate().unwrap();
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDEthr).await;
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDEthr, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.is_empty());

Expand All @@ -518,22 +519,23 @@ mod tests {
},
_ => unreachable!(),
}
let vp_verification_result = vp1.verify(Some(vp_issue_options), &DIDEthr).await;
let vp_verification_result = vp1.verify(Some(vp_issue_options), &DIDEthr, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.len() >= 1);

// test that holder is verified
let mut vp2 = vp.clone();
vp2.holder = Some(URI::String("did:example:bad".to_string()));
assert!(vp2.verify(None, &DIDEthr).await.errors.len() > 0);
assert!(vp2.verify(None, &DIDEthr, &mut context_loader).await.errors.len() > 0);
}

#[tokio::test]
async fn credential_verify_eip712vm() {
use ssi::vc::Credential;
let vc: Credential = serde_json::from_str(include_str!("../tests/vc.jsonld")).unwrap();
eprintln!("vc {:?}", vc);
let verification_result = vc.verify(None, &DIDEthr).await;
let mut context_loader = ssi::jsonld::ContextLoader::default();
let verification_result = vc.verify(None, &DIDEthr, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());
}
Expand Down
21 changes: 12 additions & 9 deletions did-key/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,22 +508,23 @@ mod tests {
let did = DIDKey.generate(&Source::Key(&key)).unwrap();
let verification_method = get_verification_method(&did, &DIDKey).await.unwrap();
let mut issue_options = LinkedDataProofOptions::default();
let mut context_loader = ssi::jsonld::ContextLoader::default();
vc.issuer = Some(Issuer::URI(URI::String(did.clone())));
issue_options.verification_method = Some(URI::String(verification_method));
let proof = vc
.generate_proof(&key, &issue_options, &DIDKey)
.generate_proof(&key, &issue_options, &DIDKey, &mut context_loader)
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDKey).await;
let verification_result = vc.verify(None, &DIDKey, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer is verified
vc.issuer = Some(Issuer::URI(URI::String("did:example:bad".to_string())));
assert!(vc.verify(None, &DIDKey).await.errors.len() > 0);
assert!(vc.verify(None, &DIDKey, &mut context_loader).await.errors.len() > 0);
}

#[async_std::test]
Expand All @@ -547,21 +548,22 @@ mod tests {

let verification_method = get_verification_method(&did, &DIDKey).await.unwrap();
let mut issue_options = LinkedDataProofOptions::default();
let mut context_loader = ssi::jsonld::ContextLoader::default();
issue_options.verification_method = Some(URI::String(verification_method));
let proof = vc
.generate_proof(&key, &issue_options, &DIDKey)
.generate_proof(&key, &issue_options, &DIDKey, &mut context_loader)
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDKey).await;
let verification_result = vc.verify(None, &DIDKey, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer is verified
vc.issuer = Some(Issuer::URI(URI::String("did:example:bad".to_string())));
assert!(vc.verify(None, &DIDKey).await.errors.len() > 0);
assert!(vc.verify(None, &DIDKey, &mut context_loader).await.errors.len() > 0);
}

#[async_std::test]
Expand All @@ -585,20 +587,21 @@ mod tests {

let verification_method = get_verification_method(&did, &DIDKey).await.unwrap();
let mut issue_options = LinkedDataProofOptions::default();
let mut context_loader = ssi::jsonld::ContextLoader::default();
issue_options.verification_method = Some(URI::String(verification_method));
let proof = vc
.generate_proof(&key, &issue_options, &DIDKey)
.generate_proof(&key, &issue_options, &DIDKey, &mut context_loader)
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDKey).await;
let verification_result = vc.verify(None, &DIDKey, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer is verified
vc.issuer = Some(Issuer::URI(URI::String("did:example:bad".to_string())));
assert!(vc.verify(None, &DIDKey).await.errors.len() > 0);
assert!(vc.verify(None, &DIDKey, &mut context_loader).await.errors.len() > 0);
}
}
47 changes: 25 additions & 22 deletions did-pkh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,43 +917,44 @@ mod tests {
..Default::default()
};
eprintln!("vm {:?}", issue_options.verification_method);
let mut context_loader = ssi::jsonld::ContextLoader::default();
let vc_no_proof = vc.clone();
/*
let proof = vc.generate_proof(&key, &issue_options).await.unwrap();
*/
// Sign with proof suite directly because there is not currently a way to do it
// for Eip712Signature2021 in did-pkh otherwise.
let proof = proof_suite
.sign(&vc, &issue_options, &DIDPKH, &key, None)
.sign(&vc, &issue_options, &DIDPKH, &mut context_loader, &key, None)
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
println!("VC: {}", serde_json::to_string_pretty(&vc).unwrap());
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDPKH).await;
let verification_result = vc.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer property is used for verification
let mut vc_bad_issuer = vc.clone();
vc_bad_issuer.issuer = Some(Issuer::URI(URI::String("did:pkh:example:bad".to_string())));
assert!(vc_bad_issuer.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vc_bad_issuer.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);

// Check that proof JWK must match proof verificationMethod
let mut vc_wrong_key = vc_no_proof.clone();
let proof_bad = proof_suite
.sign(&vc_no_proof, &issue_options, &DIDPKH, &wrong_key, None)
.sign(&vc_no_proof, &issue_options, &DIDPKH, &mut context_loader, &wrong_key, None)
.await
.unwrap();
vc_wrong_key.add_proof(proof_bad);
vc_wrong_key.validate().unwrap();
assert!(vc_wrong_key.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vc_wrong_key.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);

// Mess with proof signature to make verify fail
let mut vc_fuzzed = vc.clone();
fuzz_proof_value(&mut vc_fuzzed.proof);
let vp_verification_result = vc_fuzzed.verify(None, &DIDPKH).await;
let vp_verification_result = vc_fuzzed.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.len() >= 1);

Expand All @@ -978,27 +979,27 @@ mod tests {
vp_issue_options.eip712_domain = vp_eip712_domain_opt;
// let vp_proof = vp.generate_proof(&key, &vp_issue_options).await.unwrap();
let vp_proof = proof_suite
.sign(&vp, &vp_issue_options, &DIDPKH, &key, None)
.sign(&vp, &vp_issue_options, &DIDPKH, &mut context_loader, &key, None)
.await
.unwrap();
vp.add_proof(vp_proof);
println!("VP: {}", serde_json::to_string_pretty(&vp).unwrap());
vp.validate().unwrap();
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDPKH).await;
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.is_empty());

// Mess with proof signature to make verify fail
let mut vp_fuzzed = vp.clone();
fuzz_proof_value(&mut vp_fuzzed.proof);
let vp_verification_result = vp_fuzzed.verify(Some(vp_issue_options), &DIDPKH).await;
let vp_verification_result = vp_fuzzed.verify(Some(vp_issue_options), &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.len() >= 1);

// Test that holder is verified
let mut vp2 = vp.clone();
vp2.holder = Some(URI::String("did:pkh:example:bad".to_string()));
assert!(vp2.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vp2.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);
}

async fn credential_prepare_complete_verify_did_pkh_tz(
Expand Down Expand Up @@ -1030,9 +1031,10 @@ mod tests {
..Default::default()
};
eprintln!("vm {:?}", issue_options.verification_method);
let mut context_loader = ssi::jsonld::ContextLoader::default();
let vc_no_proof = vc.clone();
let prep = proof_suite
.prepare(&vc, &issue_options, &DIDPKH, &key, None)
.prepare(&vc, &issue_options, &DIDPKH, &mut context_loader, &key, None)
.await
.unwrap();

Expand All @@ -1044,29 +1046,29 @@ mod tests {
println!("{}", serde_json::to_string_pretty(&proof).unwrap());
vc.add_proof(proof);
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDPKH).await;
let verification_result = vc.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());

// test that issuer property is used for verification
let mut vc_bad_issuer = vc.clone();
vc_bad_issuer.issuer = Some(Issuer::URI(URI::String("did:pkh:example:bad".to_string())));
assert!(vc_bad_issuer.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vc_bad_issuer.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);

// Check that proof JWK must match proof verificationMethod
let mut vc_wrong_key = vc_no_proof.clone();
let proof_bad = proof_suite
.sign(&vc_no_proof, &issue_options, &DIDPKH, &wrong_key, None)
.sign(&vc_no_proof, &issue_options, &DIDPKH, &mut context_loader, &wrong_key, None)
.await
.unwrap();
vc_wrong_key.add_proof(proof_bad);
vc_wrong_key.validate().unwrap();
assert!(vc_wrong_key.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vc_wrong_key.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);

// Mess with proof signature to make verify fail
let mut vc_fuzzed = vc.clone();
fuzz_proof_value(&mut vc_fuzzed.proof);
let vp_verification_result = vc_fuzzed.verify(None, &DIDPKH).await;
let vp_verification_result = vc_fuzzed.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.len() >= 1);

Expand All @@ -1090,29 +1092,29 @@ mod tests {
vp_issue_options.proof_purpose = Some(ProofPurpose::Authentication);

let prep = proof_suite
.prepare(&vp, &vp_issue_options, &DIDPKH, &key, None)
.prepare(&vp, &vp_issue_options, &DIDPKH, &mut context_loader, &key, None)
.await
.unwrap();
let sig = sign_tezos(&prep, algorithm, &key);
let vp_proof = proof_suite.complete(prep, &sig).await.unwrap();
vp.add_proof(vp_proof);
println!("VP: {}", serde_json::to_string_pretty(&vp).unwrap());
vp.validate().unwrap();
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDPKH).await;
let vp_verification_result = vp.verify(Some(vp_issue_options.clone()), &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.is_empty());

// Mess with proof signature to make verify fail
let mut vp_fuzzed = vp.clone();
fuzz_proof_value(&mut vp_fuzzed.proof);
let vp_verification_result = vp_fuzzed.verify(Some(vp_issue_options), &DIDPKH).await;
let vp_verification_result = vp_fuzzed.verify(Some(vp_issue_options), &DIDPKH, &mut context_loader).await;
println!("{:#?}", vp_verification_result);
assert!(vp_verification_result.errors.len() >= 1);

// Test that holder is verified
let mut vp2 = vp.clone();
vp2.holder = Some(URI::String("did:pkh:example:bad".to_string()));
assert!(vp2.verify(None, &DIDPKH).await.errors.len() > 0);
assert!(vp2.verify(None, &DIDPKH, &mut context_loader).await.errors.len() > 0);
}

fn sign_tezos(prep: &ssi::ldp::ProofPreparation, algorithm: Algorithm, key: &JWK) -> String {
Expand Down Expand Up @@ -1433,15 +1435,16 @@ mod tests {
async fn test_verify_vc(vc_str: &str, num_warnings: usize) {
let mut vc = ssi::vc::Credential::from_json_unsigned(vc_str).unwrap();
vc.validate().unwrap();
let verification_result = vc.verify(None, &DIDPKH).await;
let mut context_loader = ssi::jsonld::ContextLoader::default();
let verification_result = vc.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.is_empty());
assert_eq!(verification_result.warnings.len(), num_warnings);
// Negative test: tamper with the VC and watch verification fail.
let mut map = std::collections::HashMap::new();
map.insert("foo".to_string(), serde_json::json!("bar"));
vc.property_set = Some(map);
let verification_result = vc.verify(None, &DIDPKH).await;
let verification_result = vc.verify(None, &DIDPKH, &mut context_loader).await;
println!("{:#?}", verification_result);
assert!(verification_result.errors.len() > 0);
}
Expand Down
Loading

0 comments on commit 6a94e2b

Please sign in to comment.