public async Task SignAndVerifyDocument() { var aliceKey = new Ed25519VerificationKey2018(Mock.Alice_Keys.VerificationMethod.First() as JObject); var signedDocument = await LdSignatures.SignAsync( Mock.ExampleDoc, new ProofOptions { Suite = new JcsEd25519Signature2020 { Signer = aliceKey, VerificationMethod = aliceKey.Id }, Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader }); var verified = await LdSignatures.VerifyAsync( document: signedDocument, options: new ProofOptions { Suite = new JcsEd25519Signature2020 { Signer = aliceKey, VerificationMethod = aliceKey.Id }, Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader }); Assert.NotNull(verified); }
public async Task SignCreateProofAndVerifyVaccination() { var unsignedDocument = Utilities.LoadJson("Data/vaccination-certificate-unsigned.jsonld"); var verificationMethod = new Bls12381G2Key2020(Utilities.LoadJson("Data/did_example_489398593_test.json")); var signedDocument = await LdSignatures.SignAsync(unsignedDocument, new ProofOptions { Suite = new BbsBlsSignature2020 { KeyPair = verificationMethod.ToBlsKeyPair(), VerificationMethod = "did:example:489398593#test" }, Purpose = new AssertionMethodPurpose() }); var revealDocument = Utilities.LoadJson("Data/vaccination-certificate-frame.jsonld"); var derivedDocument = await LdSignatures.SignAsync(signedDocument, new ProofOptions { Suite = new BbsBlsSignatureProof2020 { RevealDocument = revealDocument }, Purpose = new AssertionMethodPurpose() }); var result = await LdSignatures.VerifyAsync(derivedDocument, new ProofOptions { Suite = new BbsBlsSignatureProof2020(), Purpose = new AssertionMethodPurpose() }); Assert.NotNull(result); Assert.Equal("did:example:489398593", result.Controller); }
public async Task SignSampleDocument() { // an example document to sign var document = JObject.Parse(@"{ 'id': 'Alice' }"); // signer key var key = Ed25519VerificationKey2018.Generate(); // create proof var signedDocument = await LdSignatures.SignAsync( document, new ProofOptions { Suite = new Ed25519Signature2018 { Signer = key, VerificationMethod = key.Id }, Purpose = new AssertionMethodPurpose() }); Console.WriteLine(signedDocument.ToString(Formatting.Indented)); }
public async Task VerifySignedVerifiableCredential() { var document = Utilities.LoadJson("Data/test_signed_vc.json"); var result = await LdSignatures.VerifyAsync(document, new ProofOptions { Suite = new BbsBlsSignature2020(), Purpose = new AssertionMethodPurpose() }); result.Should().NotBeNull(); }
public async Task ShouldNotVerifyBadDocument() { var document = Utilities.LoadJson("Data/test_bad_signed_document.json"); var actual = LdSignatures.VerifyAsync(document, new ProofOptions { Suite = new BbsBlsSignature2020(), Purpose = new AssertionMethodPurpose() }); await Assert.ThrowsAsync <BbsException>(() => actual); }
public async Task VerifyPartialDerivedProofFromVc() { var document = Utilities.LoadJson("Data/test_partial_proof_vc_document.json"); var result = await LdSignatures.VerifyAsync(document, new ProofOptions { Suite = new BbsBlsSignatureProof2020(), Purpose = new AssertionMethodPurpose() }); Assert.NotNull(result); Assert.Equal("did:example:489398593", result.Controller); }
public async Task VerifySignedDocumentIncorrectPurposeThrows() { var cap = Mock.ExampleDocAlphaInvocation; await Assert.ThrowsAsync <ProofValidationException>(() => LdSignatures.VerifyAsync( document: cap, options: new ProofOptions { Suite = new Ed25519Signature2018(), Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader })); }
public async Task ShouldNotVerifyModifiedSignedDocument() { var document = Utilities.LoadJson("Data/test_signed_document.json"); document["email"] = "*****@*****.**"; var actual = LdSignatures.VerifyAsync(document, new ProofOptions { Suite = new BbsBlsSignature2020(), Purpose = new AssertionMethodPurpose() }); await Assert.ThrowsAsync <Exception>(() => actual); }
public async Task ShouldNotVerifyAdditionalUnsignedStatement() { var document = Utilities.LoadJson("Data/test_signed_document.json"); document["unsignedClaim"] = "oops"; var actual = LdSignatures.VerifyAsync(document, new ProofOptions { Suite = new BbsBlsSignature2020(), Purpose = new AssertionMethodPurpose() }); await Assert.ThrowsAsync <Exception>(() => actual); }
public async Task SignMockSuite() { var doc = Utilities.LoadJson("TestData/example-doc.json"); var data = await LdSignatures.SignAsync(doc, new ProofOptions { Suite = new MockSuite { VerificationMethod = "did:example:alice" }, Purpose = new AssertionMethodPurpose() }); Assert.NotNull(data); Assert.NotNull(data["proof"]); }
public async Task VerifySignedInvocationCap() { var cap = Mock.ExampleDocAlphaInvocation; var result = await LdSignatures.VerifyAsync( document: cap, options: new ProofOptions { Suite = new Ed25519Signature2018(), Purpose = new CapabilityInvocation(new PurposeOptions { ExpectedTarget = Mock.RootCapAlpha.Id }), DocumentLoader = Mock.DocumentLoader }); Assert.NotNull(result); }
public async Task SignVerifiableCredential() { var keyPair = BlsKeyPair.GenerateG2(); var document = Utilities.LoadJson("Data/test_vc.json"); var signedDocument = await LdSignatures.SignAsync(document, new ProofOptions { Suite = new BbsBlsSignature2020 { KeyPair = keyPair, VerificationMethod = "did:example:alice#key-1" }, Purpose = new AssertionMethodPurpose() }); signedDocument.Should().NotBeNull(); signedDocument["proof"].Should().NotBeNull(); signedDocument["proof"]["proofValue"].Should().NotBeNull(); }
public async Task Test1() { var doc = Utilities.LoadJson("TestData/example-doc.json"); var signedDoc = await LdSignatures.SignAsync(doc, new ProofOptions { Suite = new MockSuite { VerificationMethod = "did:example:bob" }, Purpose = new CapabilityInvocation() { Controller = "did:example:bob", Options = new PurposeOptions { Capability = "http://example/mock" } } }); }
public async Task SignDocumentRevealAll() { var revealDocument = Utilities.LoadJson("Data/test_reveal_all_document.json"); var signedDocument = Utilities.LoadJson("Data/test_signed_document.json"); var verificationMethod = new Bls12381G2Key2020(Utilities.LoadJson("Data/did_example_489398593_test.json")); var derivedDocument = await LdSignatures.SignAsync(signedDocument, new ProofOptions { Suite = new BbsBlsSignatureProof2020 { RevealDocument = revealDocument, VerificationMethod = verificationMethod.Id }, Purpose = new AssertionMethodPurpose() }); derivedDocument.Should().NotBeNull(); derivedDocument["proof"].Should().NotBeNull(); derivedDocument["proof"]["proofValue"].Should().NotBeNull(); }
public async Task SignDocumentRevealSome() { var revealDocument = Utilities.LoadJson("Data/test_vc_reveal_document.json"); var unsignedDocument = Utilities.LoadJson("Data/test_vc.json"); var verificationMethod = new Bls12381G2Key2020(Utilities.LoadJson("Data/did_example_489398593_test.json")); var signedDocument = await LdSignatures.SignAsync(unsignedDocument, new ProofOptions { Suite = new BbsBlsSignature2020 { KeyPair = verificationMethod.ToBlsKeyPair(), VerificationMethod = "did:example:489398593#test" }, Purpose = new AssertionMethodPurpose() }); var derivedDocument = await LdSignatures.SignAsync(signedDocument, new ProofOptions { Suite = new BbsBlsSignatureProof2020 { RevealDocument = revealDocument }, Purpose = new AssertionMethodPurpose() }); derivedDocument.Should().NotBeNull(); derivedDocument["proof"].Should().NotBeNull(); derivedDocument["proof"]["proofValue"].Should().NotBeNull(); var verifyDerived = await LdSignatures.VerifyAsync(derivedDocument, new ProofOptions { Suite = new BbsBlsSignatureProof2020(), Purpose = new AssertionMethodPurpose() }); Assert.NotNull(verifyDerived); Assert.Equal(verifyDerived.Controller, verificationMethod.Controller); }
public async Task SignDocument() { var aliceKey = new Ed25519VerificationKey2018(Mock.Alice_Keys.VerificationMethod.First() as JObject); var signedDocument = await LdSignatures.SignAsync( Mock.ExampleDoc, new ProofOptions { Suite = new JcsEd25519Signature2020 { Signer = aliceKey, VerificationMethod = aliceKey.Id }, Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader }); Assert.NotNull(signedDocument); Assert.NotNull(signedDocument["proof"]); Assert.Equal("assertionMethod", signedDocument["proof"]?["proofPurpose"]); Assert.NotNull(signedDocument["proof"]?["signatureValue"]); Assert.Equal(aliceKey.Id, signedDocument["proof"]?["verificationMethod"]); }
public async Task VerifyProofRandomKey() { var signer = new Ed25519VerificationKey2018(Mock.Diana_Keys.VerificationMethod.First() as JObject); var document = new DidDocument { Id = signer.Controller }; var signedDocument = await LdSignatures.SignAsync( document, new ProofOptions { Suite = new Ed25519Signature2018 { Signer = signer, VerificationMethod = signer.Id }, Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader }); signedDocument["@context"] = new JArray(new[] { Constants.DID_V1_URL, Constants.SECURITY_CONTEXT_V2_URL }); var result = await LdSignatures.VerifyAsync(signedDocument, new ProofOptions { Suite = new Ed25519Signature2018(), Purpose = new AssertionMethodPurpose(), DocumentLoader = Mock.DocumentLoader }); Assert.NotNull(result); }
/// <summary> /// Verifies the capability chain, if any, attached to the given capability. /// </summary> /// <param name="capability"></param> /// <returns></returns> public static async Task <JToken> VerifyCapabilityChain(JToken capability, PurposeOptions purposeOptions, JsonLdProcessorOptions options = null) { /* Verification process is: * 1. Fetch capability if only its ID was passed. * 1.1. Ensure `capabilityAction` is allowed. * 2. Get the capability delegation chain for the capability. * 3. Validate the capability delegation chain. * 4. Verify the root capability: * 4.1. Check the expected target, if one was specified. * 4.2. Ensure that the caveats are met on the root capability. * 4.3. Ensure root capability is expected and has no invocation target. * 5. If `excludeGivenCapability` is not true, then we need to verify the * capability delegation proof on `capability`, so add it to the chain to * get processed below. * 6. For each capability `cap` in the chain, verify the capability delegation * proof on `cap`. This will validate everything else for `cap` including * that caveats are met. * * Note: We start verifying a capability from its root of trust (the * beginning or head of the capability chain) as this approach limits an * attacker's ability to waste our time and effort traversing from the tail * to the head. */ // 1. Fetch capability if only its ID was passed. capability = await FetchInSecurityContextAsync(capability, false, options); //capability = new CapabilityDelegation(cap as JObject); // TODO: Add allowed action validation // 2. Get the capability delegation chain for the capability. var capabilityChain = GetCapabilityChain(capability); // 3. Validate the capability delegation chain. ValidateCapabilityChain(capability, capabilityChain); // 4. Verify root capability (note: it must *always* be dereferenced since // it does not need to have a delegation proof to vouch for its authenticity // ... dereferencing it prevents adversaries from submitting an invalid // root capability that is accepted): var isRoot = !capabilityChain.Any(); var rootCapability = isRoot ? capability : capabilityChain.First(); capabilityChain = capabilityChain.Skip(1).ToArray(); rootCapability = await Utils.FetchInSecurityContextAsync(rootCapability, isRoot, null); // 4.1. Check the expected target, if one was specified. if (purposeOptions.ExpectedTarget != null) { var target = GetTarget(rootCapability); if (target != purposeOptions.ExpectedTarget) { throw new Exception($"Expected target ({purposeOptions.ExpectedTarget}) does not match " + $"root capability target({target})."); } } // 4.2. Ensure that the caveats are met on the root capability. // TODO: Add caveats // 4.3. Ensure root capability is expected and has no invocation target. // run root capability checks (note that these will only be run once // because the `verifiedParentCapability` parameter stops recursion // from happening below) // ensure that the invocation target matches the root capability or, // if `expectedRootCapability` is present, that it matches that if (purposeOptions.ExpectedRootCapability != null) { if (purposeOptions.ExpectedRootCapability != rootCapability["id"].Value <string>()) { throw new Exception($"Expected root capability ({purposeOptions.ExpectedRootCapability}) does not " + $"match actual root capability({rootCapability["id"]})."); } } else if (GetTarget(rootCapability) != rootCapability["id"].Value <string>()) { throw new Exception("The root capability must not specify a different " + "invocation target."); } // root capability now verified var verifiedParentCapability = rootCapability; // if verifying a delegation proof and we're at the root, exit early if (isRoot) { return(verifiedParentCapability); } // create a document loader that will use properly embedded capabilities var documentLoader = new CachingDocumentLoader(Array.Empty <IDocumentResolver>()); var next = capabilityChain; while (next.Any()) { // the only capability that may be embedded (if the zcap is valid) is // the last one in the chain, if it is embedded, add it to `dlMap` and // recurse into its chain and loop to collect all embedded zcaps var cap = next.Last(); if (!(cap is JObject)) { break; } if (cap["@context"] == null) { // the capabilities in the chain are already in the security context // if no context has been specified cap["@context"] = Constants.SECURITY_CONTEXT_V2_URL; } // Transforms the `capability` into the security context (the native // context this code uses) so we can process it cleanly and then // verifies the capability delegation proof on `capability`. This allows // capabilities to be expressed using custom contexts. cap = await FetchInSecurityContextAsync(cap, false, options); documentLoader.AddCached(cap["id"].Value <string>(), cap as JObject); next = GetCapabilityChain(cap); } options.DocumentLoader = documentLoader.Load; // 5. If `excludeGivenCapability` is not true, then we need to verify the // capability delegation proof on `capability`, so add it to the chain to // get processed below. If an `inspectCapabilityChain` handler has been // provided, the verify results are required on all capabilities. // TODO: Add support for `excludeGivenCapability` // 6. For each capability `cap` in the chain, verify the capability // delegation proof on `cap`. This will validate everything else for // `cap` including that caveats are met. // note that `verifiedParentCapability` will prevent repetitive checking // of the same segments of the chain (once a parent is verified, its chain // is not checked again when checking its children) for (int i = 0; i < capabilityChain.Count(); i++) { var cap = capabilityChain.ElementAt(i); cap = await FetchInSecurityContextAsync(cap, false, options); var verifyResult = LdSignatures.VerifyAsync(cap, new ProofOptions { Suite = purposeOptions.Suite, Purpose = new CapabilityDelegationProofPurpose { Options = new PurposeOptions { ExpectedTarget = purposeOptions.ExpectedTarget, ExpectedRootCapability = purposeOptions.ExpectedRootCapability }, VerifiedParentCapability = verifiedParentCapability }, DocumentLoader = documentLoader, CompactProof = false }); } return(null); }