-
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: didSignedDocumentStatus (#114)
* chore: scaffold for new verifier & refactor verifiers * wip * feat: didSignedDocumentStatus * fix: remove data * chore: added tests * Chore/did signed adam comment (#116) * chore: added changes from Adam's comment * fix: remove signer block Co-authored-by: Raymond Yeh <[email protected]> * fix: errors to return UNEXPECTED_ERROR instead of INVALID * feat: didIdentityProof (#120) * feat: didIdentityProof * chore: removed dns-did support in didIdentityProof * feat: dnsDidProof * chore: skipping issuers for dns did * chore: skipping test for issuers not using did in didIdentityProof * chore: throwing for v3 * fix: existing integration tests * chore: integration test for documents issued with DID * fix: comments to fix dnsproof * fix: rm TODO list * fix: lint * fix: comments Co-authored-by: Raymond Yeh <[email protected]> * feat: node cache for did resolution * fix: rm commitlint * feat: npm audit fix * feat: using getDnsDidRecords from dnsprove dep * feat: default verifier without top level DID * feat: updated to latest OA supporting DID signing (#124) Co-authored-by: Raymond Yeh <[email protected]> * fix: rm cloudflare test * fix: undo temp fix for dnsprove * fix: types for signed document * fix: using isSignedWrappedV2Document * fix: typed reasons and removed any * feat: better error message coding Co-authored-by: Raymond Yeh <[email protected]> BREAKING CHANGE: Removal of previous implementation of signed document
- Loading branch information
1 parent
b755c10
commit 424f4b1
Showing
46 changed files
with
3,439 additions
and
1,479 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export class CodedError extends Error { | ||
code: number; | ||
|
||
codeString: string; | ||
|
||
constructor(message: string, code: number, codeString: string) { | ||
super(message); | ||
this.code = code; | ||
this.codeString = codeString; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export const INFURA_API_KEY = "bb46da3f80e040e8ab73c0a9ff365d18"; | ||
export const INFURA_API_KEY = process.env.INFURA_API_KEY || "bb46da3f80e040e8ab73c0a9ff365d18"; |
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,29 @@ | ||
import { Resolver, DIDDocument } from "did-resolver"; | ||
import { getResolver as ethrGetResolver } from "ethr-did-resolver"; | ||
import { getResolver as webGetResolver } from "web-did-resolver"; | ||
import NodeCache from "node-cache"; | ||
import { INFURA_API_KEY } from "../config"; | ||
|
||
const providerConfig = { | ||
networks: [{ name: "mainnet", rpcUrl: `https://mainnet.infura.io/v3/${INFURA_API_KEY}` }], | ||
}; | ||
|
||
const didResolutionCache = new NodeCache({ stdTTL: 5 * 60 }); // 5 min | ||
|
||
export const resolver = new Resolver({ | ||
...ethrGetResolver(providerConfig), | ||
...webGetResolver(), | ||
}); | ||
|
||
export const resolve = async (didUrl: string): Promise<DIDDocument> => { | ||
const cachedResult = didResolutionCache.get<DIDDocument>(didUrl); | ||
if (cachedResult) return cachedResult; | ||
const did = await resolver.resolve(didUrl); | ||
didResolutionCache.set(didUrl, did); | ||
return did; | ||
}; | ||
|
||
export const getPublicKey = async (did: string, key: string) => { | ||
const { publicKey } = await resolve(did); | ||
return publicKey.find((k) => k.id.toLowerCase() === key.toLowerCase()); | ||
}; |
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,97 @@ | ||
import { PublicKey } from "did-resolver"; | ||
import { utils } from "ethers"; | ||
import { Proof, v2 } from "@govtechsg/open-attestation"; | ||
import { getPublicKey } from "./resolver"; | ||
import { Reason, OpenAttestationSignatureCode } from "../types/error"; | ||
import { CodedError } from "../common/error"; | ||
|
||
export interface DidVerificationStatus { | ||
verified: boolean; | ||
did: string; | ||
reason?: Reason; | ||
} | ||
|
||
interface VerifySignature { | ||
did: string; | ||
signature: string; | ||
merkleRoot: string; | ||
publicKey: PublicKey; | ||
} | ||
|
||
export const verifySecp256k1VerificationKey2018 = ({ | ||
did, | ||
publicKey, | ||
merkleRoot, | ||
signature, | ||
}: VerifySignature): DidVerificationStatus => { | ||
const messageBytes = utils.arrayify(merkleRoot); | ||
const { ethereumAddress } = publicKey; | ||
if (!ethereumAddress) { | ||
return { | ||
did, | ||
verified: false, | ||
reason: { | ||
code: OpenAttestationSignatureCode.KEY_MISSING, | ||
codeString: OpenAttestationSignatureCode[OpenAttestationSignatureCode.KEY_MISSING], | ||
message: `ethereumAddress not found on public key ${JSON.stringify(publicKey)}`, | ||
}, | ||
}; | ||
} | ||
|
||
return { | ||
did, | ||
verified: utils.verifyMessage(messageBytes, signature).toLowerCase() === ethereumAddress.toLowerCase(), | ||
}; | ||
}; | ||
|
||
export const verifySignature = async ({ | ||
merkleRoot, | ||
identityProof, | ||
proof, | ||
did, | ||
}: { | ||
merkleRoot: string; | ||
identityProof?: v2.IdentityProof; | ||
proof: Proof[]; | ||
did?: string; | ||
}): Promise<DidVerificationStatus> => { | ||
if (!identityProof?.key) | ||
throw new CodedError( | ||
"Key is not present", | ||
OpenAttestationSignatureCode.MALFORMED_IDENTITY_PROOF, | ||
"MALFORMED_IDENTITY_PROOF" | ||
); | ||
if (!did) throw new CodedError("DID is not present", OpenAttestationSignatureCode.DID_MISSING, "DID_MISSING"); | ||
const { key } = identityProof; | ||
const publicKey = await getPublicKey(did, key); | ||
if (!publicKey) | ||
throw new CodedError( | ||
`No public key found on DID document for the DID ${did} and key ${key}`, | ||
OpenAttestationSignatureCode.KEY_NOT_IN_DID, | ||
"KEY_NOT_IN_DID" | ||
); | ||
|
||
const correspondingProof = proof.find((p) => p.verificationMethod.toLowerCase() === key.toLowerCase()); | ||
if (!correspondingProof) | ||
throw new CodedError( | ||
`Proof not found for ${key}`, | ||
OpenAttestationSignatureCode.CORRESPONDING_PROOF_MISSING, | ||
"CORRESPONDING_PROOF_MISSING" | ||
); | ||
|
||
switch (publicKey.type) { | ||
case "Secp256k1VerificationKey2018": | ||
return verifySecp256k1VerificationKey2018({ | ||
did, | ||
publicKey, | ||
merkleRoot, | ||
signature: correspondingProof.signature, | ||
}); | ||
default: | ||
throw new CodedError( | ||
`Signature type ${publicKey.type} is currently not support`, | ||
OpenAttestationSignatureCode.UNSUPPORTED_KEY_TYPE, | ||
"UNSUPPORTED_KEY_TYPE" | ||
); | ||
} | ||
}; |
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
6 changes: 3 additions & 3 deletions
6
...erifiers/hash/openAttestationHash.test.ts → ...ntegrity/hash/openAttestationHash.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
4 changes: 2 additions & 2 deletions
4
src/verifiers/hash/openAttestationHash.ts → ...mentIntegrity/hash/openAttestationHash.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
Oops, something went wrong.