-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 🎸 verify signed proof blocks (#91)
- Loading branch information
1 parent
bca629c
commit 7cb7499
Showing
12 changed files
with
1,428 additions
and
452 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
src/verifiers/signedProof/openAttestationSignedProof.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { verificationBuilder } from "../verificationBuilder"; | ||
import { openAttestationSignedProof } from "./openAttestationSignedProof"; | ||
import { documentSignedProofValid } from "../../../test/fixtures/v2/documentSignedProofValid"; | ||
import { documentSignedProofInvalidProofType } from "../../../test/fixtures/v2/documentSignedProofInvalidProofType"; | ||
import { documentSignedProofInvalidSignature } from "../../../test/fixtures/v2/documentSignedProofInvalidSignature"; | ||
import { documentMainnetValidWithCertificateStore } from "../../../test/fixtures/v2/documentMainnetValidWithCertificateStore"; | ||
|
||
const verify = verificationBuilder([openAttestationSignedProof]); | ||
|
||
describe("OpenAttestationSignedProof", () => { | ||
describe("SKIPPED", () => { | ||
it("should return a valid SKIPPED fragment when document does not have a proof a block", async () => { | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore | ||
// @ts-ignore error is valid, inoring for test purpose | ||
const fragment = await verify(documentMainnetValidWithCertificateStore, { | ||
network: "ropsten", | ||
}); | ||
expect(fragment).toStrictEqual([ | ||
{ | ||
name: "OpenAttestationSignedProof", | ||
type: "DOCUMENT_STATUS", | ||
reason: { | ||
code: 4, | ||
codeString: "SKIPPED", | ||
message: "Document does not have a proof block", | ||
}, | ||
status: "SKIPPED", | ||
}, | ||
]); | ||
}); | ||
}); | ||
describe("v2", () => { | ||
it("should return a valid fragment when document has valid signed proof", async () => { | ||
const fragment = await verify(documentSignedProofValid, { | ||
network: "ropsten", | ||
}); | ||
expect(fragment).toStrictEqual([ | ||
{ | ||
name: "OpenAttestationSignedProof", | ||
type: "DOCUMENT_STATUS", | ||
status: "VALID", | ||
}, | ||
]); | ||
}); | ||
it("should return an invalid fragment when document has an invalid proof signature", async () => { | ||
const fragment = await verify(documentSignedProofInvalidSignature, { | ||
network: "ropsten", | ||
}); | ||
expect(fragment).toStrictEqual([ | ||
{ | ||
name: "OpenAttestationSignedProof", | ||
type: "DOCUMENT_STATUS", | ||
reason: { | ||
code: 1, | ||
codeString: "DOCUMENT_PROOF_INVALID", | ||
message: "Certificate proof is invalid", | ||
}, | ||
status: "INVALID", | ||
}, | ||
]); | ||
}); | ||
it("should return an invalid fragment when document proof uses an unsupported proof type", async () => { | ||
const fragment = await verify(documentSignedProofInvalidProofType, { | ||
network: "ropsten", | ||
}); | ||
expect(fragment).toStrictEqual([ | ||
{ | ||
name: "OpenAttestationSignedProof", | ||
type: "DOCUMENT_STATUS", | ||
data: new Error(`Proof type: notSupported is not supported.`), | ||
reason: { | ||
code: 2, | ||
codeString: "DOCUMENT_PROOF_ERROR", | ||
message: `Proof type: notSupported is not supported.`, | ||
}, | ||
status: "ERROR", | ||
}, | ||
]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import * as ethers from "ethers"; | ||
import { DocumentsToVerify, isSignedWrappedDocument, Verifier } from "../../types/core"; | ||
import { OpenAttestationDocumentSignedCode } from "../../types/error"; | ||
|
||
const name = "OpenAttestationSignedProof"; | ||
const type = "DOCUMENT_STATUS"; | ||
|
||
export const openAttestationSignedProof: Verifier<DocumentsToVerify> = { | ||
skip: () => { | ||
return Promise.resolve({ | ||
status: "SKIPPED", | ||
type, | ||
name, | ||
reason: { | ||
code: OpenAttestationDocumentSignedCode.SKIPPED, | ||
codeString: OpenAttestationDocumentSignedCode[OpenAttestationDocumentSignedCode.SKIPPED], | ||
message: `Document does not have a proof block`, | ||
}, | ||
}); | ||
}, | ||
test: (document) => { | ||
return isSignedWrappedDocument(document); | ||
}, | ||
verify: async (document) => { | ||
try { | ||
if (!isSignedWrappedDocument(document)) throw new Error(`No proof was found in document.`); // Optional param, silence undefined type error | ||
// Note that proof.verificationMethod currently only supports a publicKey, no URLs ie. DIDs | ||
const { proof, signature } = document; | ||
let proofValid = false; | ||
|
||
if (proof.type === "EcdsaSecp256k1Signature2019") { | ||
// Existing targetHash is being signed | ||
const msg = signature.targetHash; | ||
const recoverAddress = ethers.utils.verifyMessage(msg, proof.signature); | ||
proofValid = recoverAddress.toLowerCase() === proof.verificationMethod.toLowerCase(); | ||
} else { | ||
throw new Error(`Proof type: ${proof.type} is not supported.`); | ||
} | ||
if (proofValid) { | ||
const status = "VALID"; | ||
return { name, type, status }; | ||
} else { | ||
const status = "INVALID"; | ||
const message = "Certificate proof is invalid"; | ||
const reason = { | ||
code: OpenAttestationDocumentSignedCode.DOCUMENT_PROOF_INVALID, | ||
codeString: OpenAttestationDocumentSignedCode[OpenAttestationDocumentSignedCode.DOCUMENT_PROOF_INVALID], | ||
message, | ||
}; | ||
return { name, type, status, reason }; | ||
} | ||
} catch (e) { | ||
const data = e; | ||
const { message } = e; | ||
const status = "ERROR"; | ||
const reason = { | ||
code: OpenAttestationDocumentSignedCode.DOCUMENT_PROOF_ERROR, | ||
codeString: OpenAttestationDocumentSignedCode[OpenAttestationDocumentSignedCode.DOCUMENT_PROOF_ERROR], | ||
message, | ||
}; | ||
return { name, type, data, reason, status }; | ||
} | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.