Skip to content

Commit

Permalink
Merge pull request #6 from singpass/release/0.1.0
Browse files Browse the repository at this point in the history
Add in VP and VC verification for did:key
  • Loading branch information
yuejun92 authored Sep 22, 2023
2 parents b61efe2 + a2a9bd7 commit 873daff
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.1.0 22 Sept 2023:

- Add in VP and VC verification for did:key to ensure VC did:key matches with VP did:key

## 0.0.8 11 Sep 2023:

- Add getExpirationStatus function
Expand Down
15 changes: 13 additions & 2 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const invalidVC = require("./stub/invalidVC.json");
const revokedVC = require("./stub/revokedVC.json");
const verifyresult = require("./stub/result.json");
const signedVP2018 = require("./stub/signedVP2018.json");
const didKeyInvalidVP2018 = require("./stub/didKeyInvalidVP2018.json");
const invalidVP = require("./stub/invalidVP.json");
const verifyPresentationResult2018 = require("./stub/resultPresentation2018.json");
const signedSDVC = require("./stub/signedSelectiveDisclosedVC.json");
Expand Down Expand Up @@ -97,13 +98,23 @@ describe("Test VC verifier", () => {
expect(result.verified).toStrictEqual(true);
}, 5000);

it("should validate expirationStatus as expired", async () => {
it("should validate expirationStatus as expired (true)", async () => {
const result = MyInfoVcVerifier.getExpirationStatus(expiredVC);
expect(result).toStrictEqual(true);
});

it("should validate expirationStatus as not expired", async () => {
it("should validate expirationStatus as not expired (false)", async () => {
const result = MyInfoVcVerifier.getExpirationStatus(notExpiredVC);
expect(result).toStrictEqual(false);
});

it("should verify did:key verificationStatus as matches (true)", async () => {
const result = MyInfoVcVerifier.verifyPresentationAndCredentialDidKey(signedVP2018);
expect(result).toStrictEqual(true);
});

it("should verify did:key verificationStatus as does not matches (false)", async () => {
const result = MyInfoVcVerifier.verifyPresentationAndCredentialDidKey(didKeyInvalidVP2018);
expect(result).toStrictEqual(false);
});
});
99 changes: 99 additions & 0 deletions __tests__/stub/didKeyInvalidVP2018.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"id": "did:key:z6MkfJVf63AcEoiL9CJJ2r76eZL3dS9QugWk5cDWCYp9raYx#vp-15cfeb06-c893-4a88-b2fd-2c6122db69d7",
"type": ["VerifiablePresentation"],
"holder": "did:key:z6MkfJVf63AcEoiL9CJJ2r76eZL3dS9QugWk5cDWCYp9raYx",
"verifiableCredential": [
{
"@context": [
"https://w3id.org/security/bbs/v1",
"https://www.w3.org/2018/credentials/v1",
"https://stg.issuer.myinfo.gov.sg/myinfo/schema/age/v1",
"https://w3id.org/vc/status-list/2021/v1"
],
"id": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/credentials/b2086515-619c-427c-b707-84f238764eac",
"type": ["VerifiableCredential", "AgeCredential"],
"issuer": "did:web:stg.issuer.myinfo.gov.sg:myinfo202304-01",
"credentialSubject": {
"AtLeast18YearsOld": true,
"AtLeast21YearsOld": true,
"type": ["Age"],
"id": "did:key:z6MkisZuWTqwmE4XxnSRkGibr5hkLCqVkdvcpMpTRViLtJ9s"
},
"name": "Age",
"description": "Age Over Indicators",
"expirationDate": "2025-08-21T06:51:34Z",
"credentialStatus": {
"id": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/status/1#10267",
"type": "StatusList2021Entry",
"statusListIndex": "10267",
"statusListCredential": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/status/1"
},
"issuanceDate": "2023-08-21T07:05:15Z",
"proof": {
"created": "2023-08-21T07:05:15Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:web:stg.issuer.myinfo.gov.sg:myinfo202304-01#21402a47-6416-4b95-b180-dff0e1f44d67",
"type": "BbsBlsSignatureProof2020",
"nonce": "KIr/YTYd9HGtHoHe4Nms3PjhxtjiW+xhVYrTcDgOqoc=",
"proofValue": "ABMH//+jbjXQAjbCiOj5Oh6lxFnP45WC4N675Xe8abpOzdN5h1zhxkFlNbas965ep5fqHIG3JGWmlaAe7jL9RqNHNSi5vPaOcnjIu0zHZA4dT9z98viovnPQG8GRoQWNCQllxS+lzW0ucRHG9ruNApHzOv+ESkoPU4/tBbZtm9HPQ8u00N/edXHC7HtkVSJzXSfFwe4AAAB0s+hWBhiH7v3AMi36Is6MvOHz55ZK5l9c8cjbkBqAXl0qt+mh5IACj7wlAeMgCNc8AAAAAhyzTjmFL9cRSLUkXsBAAGbdpZrQqDC1ehc35uonjj8SQv/JgYhlzO/c3e9JMWMj1GuMESzO/H2Slq22d/jFxwyPgKGEQ4I7S7sDrELuIsj3oINYz2e10uOBfDeSPCeAxGhcyG3Myy1mxRFwH50beHUAAAACPPmYj1uOXKtJAlu+FIt3J6q3ibYJ9+rcFXVPapwI8lQqPF7cpSwAE6A9kZbazXH46NkUV1KKec4Uz2l2wLagAg=="
}
},
{
"@context": [
"https://w3id.org/security/bbs/v1",
"https://www.w3.org/2018/credentials/v1",
"https://stg.issuer.myinfo.gov.sg/myinfo/schema/personal/v1",
"https://w3id.org/vc/status-list/2021/v1"
],
"id": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/credentials/0ba368dd-f58a-4455-846f-365382ade416",
"type": ["VerifiableCredential", "PersonalCredential"],
"issuer": "did:web:stg.issuer.myinfo.gov.sg:myinfo202304-01",
"credentialSubject": {
"uinfin": "S8703396A",
"name": "User S8703396A",
"aliasname": "",
"hanyupinyinname": "",
"hanyupinyinaliasname": "",
"marriedname": "",
"sex": "MALE",
"race": "AMERICAN",
"dob": "1990-04-19",
"residentialstatus": "CITIZEN",
"nationality": "GUINEAN",
"birthcountry": "UNITED STATES",
"regadd": {
"country": "SINGAPORE",
"postal": "609774"
},
"type": ["Personal"],
"id": "did:key:z6MkisZuWTqwmE4XxnSRkGibr5hkLCqVkdvcpMpTRViLtJ9s"
},
"name": "Personal",
"description": "Basic Details of Personal Profile",
"expirationDate": "2025-08-21T06:51:34Z",
"credentialStatus": {
"id": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/status/1#10268",
"type": "StatusList2021Entry",
"statusListIndex": "10268",
"statusListCredential": "https://stg.issuer.myinfo.gov.sg/myinfo202304-01/status/1"
},
"issuanceDate": "2023-08-21T07:05:20Z",
"proof": {
"created": "2023-08-21T07:05:20Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:web:stg.issuer.myinfo.gov.sg:myinfo202304-01#21402a47-6416-4b95-b180-dff0e1f44d67",
"type": "BbsBlsSignatureProof2020",
"nonce": "MfQWYAz9Ha+3ygEUmhlOkmdnAHyiskxvTI7Fc2fT2ac=",
"proofValue": "ACoAp//8fP+Y9rrEm2me6HlQOHtU7A1g6cR6Bvx31BXV4fbHtYFhhN1fTszqrlGwvERxYUTW8+eMJxa+7lmdfO3qXchUAQDHM/yiw8Tmy6bi4xnr/2WJCgmf/2GXWSEiOHrRRD0xgD2qlej+qs/X9v+VJ1vJxQMYaXUmTel5Zl9IZ8M3/F/oJ9tY+41MBa1gNkF/wKljshwAAAB0qkEdjkws3IUCtxdrNszurU0fzkoL2ataW/reLCMLHjtEqAuFEPO4JHOCPfYdlm0DAAAAAkp9+vIiTC4uvkIEIHHhVf2KZk1jtbo+U0poBHlOwzoNESJH1Q+70PdcEjIEWVfUGEBz0rAQinE6ueI6OQ10AjSRJvL/zjzpfzX7nLvXsK8UfmHkR2HHCaVF6kSRSsdkzNNycBdlenGE1Wy7jTac7NUAAAAMYJ2Y1euh+HilfjQjgl3gMKHAQBUmUg6Dy6TUaBYab8UP1/LGyOwRWveiPZcJJadp5sIeZsfrAZZ2hSVL6DMDoWsLqKn2BkKJpUhSgaMtPcwdE7PhGst/GPWk/kTgJzNfHnI5w3xFUM0mvhM8guSKY+xK9Bs/rTXTItiM/+k8K9ZS3jmsE3JhgKs+xmLQYX29AeVUJGHOLhWE2yqXnCUE/lJ2te5o2FvDh9VPm/4EwpZY4R0SF1esqW0MlCjle657Q6AvK+sGO73ECxxilTP3SCXnLFSMrn/2ov1c6mA9iL5Yo/p8CwP731mTLd+3vUVZTreK87WVmlQuAMQA5Lm3PyPGDEeAIBlbpdVyZs6w8hlOAYzMHXj5wyrNNf5Pbz/lXNxtZhH99jAdGyL+SQU0RiUiz7mV9kTlcLRQxqocQhhwevc1PkF8O2Y8gdLlGXR+NiHEOX39hvY0E2BccpnnmzOnTNUZOGCORU7CsZDz1YdkKCrFpFy7w6blF5D99saq"
}
}
],
"proof": {
"type": "Ed25519Signature2018",
"created": "2023-08-22T06:47:00Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:key:z6MkfJVf63AcEoiL9CJJ2r76eZL3dS9QugWk5cDWCYp9raYx#z6MkfJVf63AcEoiL9CJJ2r76eZL3dS9QugWk5cDWCYp9raYx",
"jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..pTydH1ytitQ_FiblmcgsqZC0vxjNp-GpQNbruCO9d9dPC1xUGYoWjitAv0St8zyJgmJ_aFcvXnGuAANIaZJGCw"
}
}
24 changes: 24 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ MyInfoVcVerifier.verifyPresentation = async function (presentation, customDocume
let documentLoader = await getDocumentLoader(customDocuments);
let suite = [new jsonldSignatures.suites.Ed25519Signature2018()];

if (!this.verifyPresentationAndCredentialDidKey(presentation)) {
return {
verified: false,
};
}

const result = await jsonldSignatures.verify(presentation, {
suite: suite,
purpose: new jsonldSignatures.purposes.AssertionProofPurpose(),
Expand All @@ -228,6 +234,24 @@ MyInfoVcVerifier.verifyPresentation = async function (presentation, customDocume
return result;
};

/**
* [Verify Presentation and Credential Did Key]
* @param {Object} Verifiable Presentation object [signed verifiable presentation]
* @return {Boolean} [Did Key Verification Status] TRUE - did:key matches, FALSE - did:key does not match
*/
MyInfoVcVerifier.verifyPresentationAndCredentialDidKey = (presentation) => {
let vpVerificationMethod = presentation.proof.verificationMethod;
let vpDidKey = vpVerificationMethod.split("#")[0];

for (let vc of presentation.verifiableCredential) {
if (vc.credentialSubject.id !== vpDidKey) {
return false;
}
}

return true;
};

/**
* [Check Revoke Status]
* @param {Object} encoded [the verified encoded list]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "myinfo-vc-verifier",
"version": "0.0.8",
"version": "0.1.0",
"description": "This package provides the functionality to verify a verifiable credential using @mattrglobal jsonld-signatures-bbs.",
"main": "index.js",
"scripts": {
Expand Down

0 comments on commit 873daff

Please sign in to comment.