Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

feat: adds support for providing a proofDocument with multiple proofs #82

Merged
merged 1 commit into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion __tests__/deriveProof.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ import {
testSignedDocument,
customLoader,
testSignedVcDocument,
testRevealVcDocument
testRevealVcDocument,
testSignedDocumentMultiProofs,
testSignedDocumentMultiDifProofs,
testSignedDocumentEd25519
} from "./__fixtures__";

import { BbsBlsSignatureProof2020, deriveProof } from "../src/index";

import jsigs from "jsonld-signatures";

describe("BbsBlsSignatureProof2020", () => {
it("should derive proof", async () => {
const result = await deriveProof(testSignedDocument, testRevealDocument, {
Expand Down Expand Up @@ -49,4 +54,77 @@ describe("BbsBlsSignatureProof2020", () => {
);
expect(result).toBeDefined();
});

it("should derive proofs from a document featuring multiple supporting proofs", async () => {
const result = await deriveProof(
testSignedDocumentMultiProofs,
testRevealDocument,
{
suite: new BbsBlsSignatureProof2020(),
documentLoader: customLoader
}
);
expect(result).toBeDefined();
expect(result.proof.length).toBe(2);
});

it("should derive proofs from a document featuring multiple different proofs with at least 1 supporting proof", async () => {
const result = await deriveProof(
testSignedDocumentMultiDifProofs,
testRevealDocument,
{
suite: new BbsBlsSignatureProof2020(),
documentLoader: customLoader
}
);
expect(result).toBeDefined();

// this returns a document with only a single proof so it should be an object rather than an array
expect(Array.isArray(result.proof)).toBe(false);
});

it("should derive proofs from multiple proof documents and be able to verify them using jsonld-signatures library", async () => {
const result = await deriveProof(
testSignedDocumentMultiProofs,
testRevealDocument,
{
suite: new BbsBlsSignatureProof2020(),
documentLoader: customLoader
}
);

const derivedProofVerified = await jsigs.verify(result, {
suite: new BbsBlsSignatureProof2020(),
purpose: new jsigs.purposes.AssertionProofPurpose(),
documentLoader: customLoader
});

expect(result).toBeDefined();
expect(result.proof.length).toBe(2);
expect(derivedProofVerified.verified).toBeTruthy();
});

it("should throw an error when proofDocument is the wrong type", async () => {
await expect(
deriveProof(
[testSignedDocument, testSignedDocument],
testRevealDocument,
{
suite: new BbsBlsSignatureProof2020(),
documentLoader: customLoader
}
)
).rejects.toThrowError("proofDocument should be an object not an array.");
});

it("should throw an error when proofDocument doesn't include a BBSBlsSignatureProof2020", async () => {
await expect(
deriveProof(testSignedDocumentEd25519, testRevealDocument, {
suite: new BbsBlsSignatureProof2020(),
documentLoader: customLoader
})
).rejects.toThrowError(
"There were not any BBSBlsSignatureProof2020 proofs provided that can be used to derive a proof."
);
});
});
58 changes: 50 additions & 8 deletions src/deriveProof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,69 @@ export const deriveProof = async (
throw new TypeError('"options.suite" is required.');
}

if (Array.isArray(proofDocument)) {
throw new TypeError("proofDocument should be an object not an array.");
}

const { proofs, document } = await getProofs({
document: proofDocument,
proofType: suite.supportedDeriveProofType,
documentLoader,
expansionMap
});

const result = await suite.deriveProof({
if (proofs.length === 0) {
throw new Error(
"There were not any BBSBlsSignatureProof2020 proofs provided that can be used to derive a proof."
);
}
let derivedProof;

derivedProof = await suite.deriveProof({
document,
proof: proofs[0],
revealDocument,
documentLoader,
expansionMap
});

if (proofs.length > 1) {
// convert the proof property value from object ot array of objects
derivedProof = { ...derivedProof, proof: [derivedProof.proof] };

// drop the first proof because it's already been processed
proofs.splice(0, 1);

// add all the additional proofs to the derivedProof document
for (const proof of proofs) {
const additionalDerivedProofValue = await suite.deriveProof({
document,
proof,
revealDocument,
documentLoader,
expansionMap
});
derivedProof.proof.push(additionalDerivedProofValue.proof);
}
}

if (!skipProofCompaction) {
/* eslint-disable prefer-const */
let expandedProof: any = {
[SECURITY_PROOF_URL]: { "@graph": result.proof }
[SECURITY_PROOF_URL]: {
"@graph": derivedProof.proof
}
};

// account for type-scoped `proof` definition by getting document types
const { types, alias } = await getTypeInfo(result.document, {
const { types, alias } = await getTypeInfo(derivedProof.document, {
documentLoader,
expansionMap
});

expandedProof["@type"] = types;

const ctx = jsonld.getValues(result.document, "@context");
const ctx = jsonld.getValues(derivedProof.document, "@context");

const compactProof = await jsonld.compact(expandedProof, ctx, {
documentLoader,
Expand All @@ -74,13 +107,22 @@ export const deriveProof = async (
delete compactProof[alias];
delete compactProof["@context"];

/**
tplooker marked this conversation as resolved.
Show resolved Hide resolved
* removes the @included tag when multiple proofs exist because the
* @included tag messes up the canonicalized bytes leading to a bad
* signature that won't verify.
**/
if (compactProof.proof["@included"]) {
compactProof.proof = compactProof.proof["@included"];
}

// add proof to document
const key = Object.keys(compactProof)[0];
jsonld.addValue(result.document, key, compactProof[key]);
jsonld.addValue(derivedProof.document, key, compactProof[key]);
} else {
delete result.proof["@context"];
jsonld.addValue(result.document, "proof", result.proof);
delete derivedProof.proof["@context"];
jsonld.addValue(derivedProof.document, "proof", derivedProof.proof);
}

return result.document;
return derivedProof.document;
};