Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: align against W3C VC 2.0 test suite and complete unit tests #272

Merged
merged 108 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
bfed44e
chore: npm install jsonld & joi
HJunyuan Mar 14, 2024
36c9bca
chore: add vc 2.0 context url and store as cache
HJunyuan Mar 14, 2024
ef74d88
fix: align validation with vc 2.0 test suite
HJunyuan Mar 14, 2024
a80a7da
fix: set additionalProperties to false due to AJV false positive
HJunyuan Mar 20, 2024
f44bb88
fix: allow additional properties in credentialStatus
HJunyuan Mar 20, 2024
db0a940
fix: include error details instead of console log
HJunyuan Mar 20, 2024
966e7f6
test: update v4 alpha test fixtures
HJunyuan Mar 20, 2024
69cf931
lint: ignore unused argument options
HJunyuan Mar 20, 2024
2aa66d7
chore: upgrade jest and ts-jest
HJunyuan Mar 27, 2024
6e007d2
fix: segmentation fault when using default nodeDocumentLoader()
HJunyuan Mar 27, 2024
cd1cf66
fix: use scoped context types
HJunyuan Mar 27, 2024
75aec4a
test: no more auto-correct for @context based on vc 2.0 test suite
HJunyuan Mar 27, 2024
8e07b33
fix: digest should handle falsy values correctly
HJunyuan Apr 17, 2024
d82ac6c
fix: rename to renderMethod.templateName
HJunyuan Apr 17, 2024
de0dc70
fix: make renderMethod an array
HJunyuan Apr 17, 2024
10c305a
fix: remove json schema validation in v4.0 wrap
HJunyuan Apr 17, 2024
c86d710
test: update v4.0 fixtures
HJunyuan Apr 19, 2024
e6fbb6b
fix: digest test
Apr 19, 2024
6e6f808
fix: make renderMethod.templateName required in v4.0 json schema
HJunyuan Apr 19, 2024
bc48b98
fix: migrate to zod for input vc data model validation
HJunyuan Apr 22, 2024
d3aafc2
wip: oa v4 types
HJunyuan Apr 24, 2024
b102ee9
refactor: prefer string union
phanshiyu Apr 24, 2024
e693b92
refactor: reference constant tuple instead
phanshiyu Apr 24, 2024
c4c91fe
refactor: finalTypes follows pattern of finalContexts
phanshiyu Apr 24, 2024
5ff08a3
refactor: document -> raw document for clarity
phanshiyu Apr 24, 2024
23af438
fix: rawDocument should not be used directly for digest and salting
phanshiyu Apr 24, 2024
5cc50cf
fix: remove asserting to string to let the literal infer properly
phanshiyu Apr 24, 2024
e7e4c72
fix: typings
phanshiyu Apr 24, 2024
27e6e8e
refactor: move assertion earlier
phanshiyu Apr 24, 2024
2bc4066
refactor: assert oa vc than try vc
phanshiyu Apr 24, 2024
5fa7561
fix: refer to new oa vc type in digest and verify
phanshiyu Apr 24, 2024
9ce1255
fix: refer to new oa vc typings
phanshiyu Apr 24, 2024
e6bff07
fix: refer to new oa vc typings
phanshiyu Apr 24, 2024
a259eac
fix: refer to new oa vc typings
phanshiyu Apr 24, 2024
8dfd6af
refactor: improve naming consistency
phanshiyu Apr 24, 2024
9fce84a
fix: typing, should be looser
phanshiyu Apr 24, 2024
d409c68
fix: a union b does not override a props with b props
phanshiyu Apr 24, 2024
e30c8e8
fix: added assertion type to prevent accident extension to base type
phanshiyu Apr 25, 2024
194f19e
refactor: wording
phanshiyu Apr 25, 2024
cd34a7d
refactor: better readability for wrapped types
phanshiyu Apr 25, 2024
d3baf69
refactor: move things within file and some renaming
phanshiyu Apr 25, 2024
3bdc13e
refactor: improve naming of variables
phanshiyu Apr 25, 2024
db12f50
fix: use new typings
phanshiyu Apr 25, 2024
22df165
fix: passthroughs needed to allow extension, added name and render me…
phanshiyu Apr 25, 2024
fc0ce61
test: added a guard test which is currently failing
phanshiyu Apr 25, 2024
8f42178
refactor: merged data model with types and renamed VC type
phanshiyu Apr 25, 2024
3187237
refactor: improve helper fn naming
phanshiyu Apr 25, 2024
0f3d311
fix: use extend instead of and since it results in dup errors, remove…
phanshiyu Apr 26, 2024
3c40ebc
test: update snapshot
phanshiyu Apr 26, 2024
946ae63
fix: was using the wrong document for the check
phanshiyu Apr 26, 2024
d8c4694
test: added tests for wrapped only document
phanshiyu Apr 26, 2024
c5a5c96
fix: diagnose to use new guards
phanshiyu Apr 26, 2024
9561fbe
fix: path
phanshiyu Apr 26, 2024
aa66692
chore: remove vscode
phanshiyu Apr 26, 2024
9b1900e
chore: ignore vscode settings
phanshiyu Apr 26, 2024
ff57b1c
chore: remove experimental version guard
phanshiyu Apr 26, 2024
6245038
fix: add back the missing wrapDocuments that was accidentally removed
phanshiyu Apr 26, 2024
4d965a4
fix: replace back original implementation of getMerkleRoot
phanshiyu Apr 26, 2024
5b5ecea
fix: make our own real types stricter
phanshiyu Apr 26, 2024
a99584a
fix: diagnose did not handle raw v4
phanshiyu Apr 26, 2024
a8219ee
refactor: remove useless renaming
phanshiyu Apr 26, 2024
26fa265
fix: object object in test case
phanshiyu Apr 26, 2024
d6ff500
refactor: improve type safety of wrap document v4
phanshiyu Apr 26, 2024
43dd837
chore: remove to make way for auto generated fixtures
phanshiyu Apr 26, 2024
5b19bc9
chore: auto generate v4 fixtures
phanshiyu Apr 26, 2024
a14f73c
fix: could not generated nested dir
phanshiyu Apr 26, 2024
d27c9ef
test: add wrap unit tests
phanshiyu Apr 27, 2024
abbbf27
test: extra assertion for proof
phanshiyu Apr 27, 2024
f761d1f
fix: salt test
phanshiyu Apr 27, 2024
5452590
fix: allow resigning and validate proof before using
phanshiyu Apr 27, 2024
8eb6e9a
fix: v4 sign tests
phanshiyu Apr 27, 2024
2ab7b11
chore: add batch wrapped document fixture. freeze all documents befor…
phanshiyu Apr 27, 2024
b8530ff
fix: obfuscate typing was loses the initial input typing
phanshiyu Apr 28, 2024
c484c7c
fix: should not allow obfuscate to produce non compliant v4 wrapped d…
phanshiyu Apr 28, 2024
2ed39fc
fix: partially fix obfuscate test
phanshiyu Apr 28, 2024
bc2bdc0
fix: it is more accurate that credentials subject after obfuscastion …
phanshiyu Apr 28, 2024
ac4ca37
fix: clean up digest test
phanshiyu Apr 29, 2024
6c7fa73
feat: support attachments
phanshiyu Apr 29, 2024
90ac57c
fix: digestMultibase shd be optional, added descriptions to fields
phanshiyu Apr 29, 2024
7f6dd75
refactor: remove renderMethod from w3c model and force it to be expor…
phanshiyu Apr 29, 2024
defbb39
chore: improve guard test to use direct output of our fns as test case
phanshiyu Apr 29, 2024
3734c93
fix: allow attachment item to be empty so that obfuscation of a singl…
phanshiyu Apr 29, 2024
7332907
refactor: improve typing
phanshiyu Apr 29, 2024
f674eb6
fix: partial fix of obfuscate test
phanshiyu Apr 29, 2024
5a29fe5
wip: draft of changes to address issues raised
phanshiyu Apr 30, 2024
9c293af
fix: wrongly returned object for boolean
phanshiyu Apr 30, 2024
70ff03f
fix: shd not allow new empty objects after obfuscation or removing ar…
phanshiyu May 1, 2024
692dbab
chore: update fixtures
phanshiyu May 1, 2024
79f3c67
fix: digest should not include proof
phanshiyu May 1, 2024
429e8ce
fix: skip finding leaf nodes to hash if document without proof is empty
phanshiyu May 1, 2024
3d48bb8
refactor: improve naming
phanshiyu May 1, 2024
c28879b
fix: broken tests
phanshiyu May 1, 2024
77ad5b3
fix: revert target bump
phanshiyu May 1, 2024
9d7a4d5
fix: all obfuscate tests
phanshiyu May 2, 2024
6216a4e
fix: verify should treat salt not found error as invalid
phanshiyu May 2, 2024
d5d7f4f
fix: partial fix of verify tests, added bunch of todos
phanshiyu May 2, 2024
5eec7a2
chore: add batched signed documents
phanshiyu May 2, 2024
82a28a0
fix: complete verify tests
phanshiyu May 2, 2024
b36426e
refactor: typo remove redundant top describe
phanshiyu May 2, 2024
2c0df7d
fix: fixtures and test it will break on update
phanshiyu May 2, 2024
1f0ddc1
refactor: improve error message to provide more guidance
phanshiyu May 2, 2024
45cb43c
Merge pull request #277 from Open-Attestation/fix/oa-v4-digest-and-ob…
phanshiyu May 2, 2024
1e5b23d
fix: array items cannot be undefined
phanshiyu May 2, 2024
9f0ba1f
chore: commit generated fixtures and allow ci tests to catch any drifts
phanshiyu May 2, 2024
aadf793
chore: added remedy action if fixture test fails
phanshiyu May 2, 2024
1e8a1e6
chore: remove lint for all generated files
phanshiyu May 2, 2024
fb3ad28
fix: v4 e2e
phanshiyu May 2, 2024
1285c8e
refactor: improve error types and exporting
phanshiyu May 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules
coverage
dist
src/__generated__
__generated__
vc-test-suite
*.d.ts
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"func-names": ["error", "as-needed"],
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ yarn.lock
*.iml
/public
/vc-test-suite
/.vscode
1,439 changes: 785 additions & 654 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
"test:vc": "scripts/runVcTest.sh",
"lint": "eslint . --ext .ts,.json --max-warnings 0",
"lint:fix": "npm run lint -- --fix",
"generate-v4-fixtures": "npx ts-node scripts/generateV4JsonFixtures.ts",
"publish:schema": "./scripts/publishSchema.sh",
"postinstall": "node scripts/postInstall"
"postinstall": "node scripts/postInstall; npm run generate-v4-fixtures"
},
"files": [
"/dist",
Expand All @@ -42,7 +43,7 @@
"@types/debug": "^4.1.7",
"@types/jest": "^29.5.3",
"@types/js-base64": "^3.3.1",
"@types/jsonld": "^1.5.6",
"@types/jsonld": "^1.5.13",
"@types/lodash": "^4.14.171",
"@types/qrcode": "^1.4.1",
"@types/uuid": "^8.3.1",
Expand All @@ -58,16 +59,16 @@
"eslint-plugin-jest": "^24.4.0",
"eslint-plugin-prettier": "^3.4.0",
"git-cz": "^4.7.6",
"jest": "^29.6.2",
"jest": "^29.7.0",
"jest-watch-typeahead": "^2.2.2",
"prettier": "^2.3.2",
"qrcode": "^1.5.1",
"quicktype": "^15.0.260",
"rollup": "^2.56.2",
"rollup-plugin-commonjs": "^10.1.0",
"semantic-release": "^21.1.1",
"ts-jest": "^29.1.1",
"ts-node": "^9.1.1",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.1.6"
},
"dependencies": {
Expand All @@ -80,10 +81,12 @@
"flatley": "^5.2.0",
"js-base64": "^3.6.1",
"js-sha3": "^0.8.0",
"jsonld": "^8.3.2",
"lodash": "^4.17.21",
"runtypes": "^6.3.2",
"uuid": "^8.3.2",
"validator": "^13.7.0"
"validator": "^13.7.0",
"zod": "^3.22.4"
},
"directories": {
"test": "test"
Expand Down
18 changes: 18 additions & 0 deletions scripts/generateV4JsonFixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fs from "fs";
import path from "path";
import * as V4_FIXTURES from "../src/4.0/fixtures";

const OUTPUT_DIR = path.resolve("./test/fixtures/v4/__generated__");

// make sure the output directory exists
if (fs.existsSync(OUTPUT_DIR)) {
fs.rmSync(OUTPUT_DIR, { recursive: true });
}
fs.mkdirSync(OUTPUT_DIR, { recursive: true });

for (const [key, value] of Object.entries(V4_FIXTURES)) {
fs.writeFileSync(
path.join(OUTPUT_DIR, key.replace(/_/g, "-").toLowerCase() + ".json"),
JSON.stringify(value, null, 2)
);
}
5 changes: 0 additions & 5 deletions scripts/postInstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ if (fs.existsSync(quicktype) && process.env.npm_config_production !== "true") {
quicktype +
" -s schema -o src/__generated__/schema.3.0.ts -t OpenAttestationDocument --just-types src/3.0/schema/schema.json --no-date-times"
);
console.log('"Creating types from src/4.0/schema/schema.json"');
execSync(
quicktype +
" -s schema -o src/__generated__/schema.4.0.ts -t OpenAttestationDocument --just-types src/4.0/schema/schema.json --no-date-times"
);
} else {
console.log("Not running quicktype");
}
4 changes: 0 additions & 4 deletions scripts/publishSchema.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,3 @@ cp src/2.0/schema/schema.json public/2.0/schema.json
# Copy 3.0 schema to public folder
mkdir -p public/3.0/
cp src/3.0/schema/schema.json public/3.0/schema.json

# Copy 4.0 schema to public folder
mkdir -p public/4.0/
cp src/4.0/schema/schema.json public/4.0/schema.json
3 changes: 2 additions & 1 deletion src/3.0/digest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { OpenAttestationDocument } from "../__generated__/schema.3.0";
export const digestCredential = (document: OpenAttestationDocument, salts: Salt[], obfuscatedData: string[]) => {
// Prepare array of hashes from visible data
const hashedUnhashedDataArray = salts
.filter((salt) => get(document, salt.path))
// Explictly allow falsy values (e.g. false, 0, etc.) as they can exist in the document
.filter((salt) => get(document, salt.path) !== undefined)
.map((salt) => {
return keccak256(JSON.stringify({ [salt.path]: `${salt.value}:${get(document, salt.path)}` }));
});
Expand Down
255 changes: 162 additions & 93 deletions src/4.0/__tests__/digest.test.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,175 @@
import { cloneDeep } from "lodash";
import { digestCredential } from "../digest";
import { WrappedDocument } from "../../4.0/types";
import { obfuscateVerifiableCredential } from "../obfuscate";
import { decodeSalt } from "../salt";
import sample from "../../../test/fixtures/v4/did-wrapped.json";
import { SIGNED_WRAPPED_DOCUMENT_DID as ROOT_CREDENTIAL } from "../fixtures";
import { V4SignedWrappedDocument } from "../types";
import { obfuscateVerifiableCredential } from "../obfuscate";

const verifiableCredential = sample as WrappedDocument;
// Digest will change whenever sample document is regenerated
const credentialRoot = "adb16863b9b92f1f46d67f518f853092404dc1322ffb61b45a831ee113f4ea99";
// All obfuscated documents are generated from the ROOT_CREDENTIAL
const ROOT_CREDENTIAL_TARGET_HASH = ROOT_CREDENTIAL.proof.targetHash;

const { proof, ...credential } = verifiableCredential;
describe("V4 digestCredential", () => {
test("given all testobfuscated documents are generated from the ROOT_CREDENTIAL, ROOT_CREDENTIAL_TARGET_HASH should match snapshot", () => {
expect(ROOT_CREDENTIAL_TARGET_HASH).toMatchInlineSnapshot(
`"dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa"`
);
});

describe("digest v4.0", () => {
describe("digestCredential", () => {
test("digests a document with all visible content correctly", () => {
const clonedCredential = cloneDeep(credential);
test("given a document with ALL FIELDS VISIBLE, should digest and match the root credential's target hash", () => {
expect(ROOT_CREDENTIAL.credentialSubject).toMatchInlineSnapshot(`
{
"id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42",
"licenses": [
{
"class": "3",
"description": "Motor cars with unladen weight <= 3000kg",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
{
"class": "3A",
"description": "Motor cars with unladen weight <= 3000kg",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
],
"name": "John Doe",
"type": [
"DriversLicense",
],
}
`);
expect(ROOT_CREDENTIAL.proof.privacy.obfuscated).toMatchInlineSnapshot(`[]`);

const digest = digestCredential(clonedCredential, decodeSalt(proof.salts), []);
expect(digest).toBe(credentialRoot);
});
test("digests a document when one single element is obfuscated", () => {
const obfuscatedVerifiableCredential = obfuscateVerifiableCredential(verifiableCredential, "issuer.id");
const digest = digestCredential(
obfuscatedVerifiableCredential,
decodeSalt(obfuscatedVerifiableCredential.proof.salts),
obfuscatedVerifiableCredential.proof.privacy.obfuscated
);
const digest = digestCredential(ROOT_CREDENTIAL, decodeSalt(ROOT_CREDENTIAL.proof.salts), []);
expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH);
});

expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toMatchInlineSnapshot(`
[
"016c17fefa241351dc2950cfbeaef8281b0bc71e1ee445d890e9c37622fa0318",
]
test("given a document with ONE element obfuscated, should digest and match the root credential's target hash", () => {
const OBFUSCATED_WRAPPED_DOCUMENT = obfuscateVerifiableCredential(ROOT_CREDENTIAL, "credentialSubject.id");
expect(OBFUSCATED_WRAPPED_DOCUMENT.credentialSubject).toMatchInlineSnapshot(`
{
"licenses": [
{
"class": "3",
"description": "Motor cars with unladen weight <= 3000kg",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
{
"class": "3A",
"description": "Motor cars with unladen weight <= 3000kg",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
],
"name": "John Doe",
"type": [
"DriversLicense",
],
}
`);
expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toHaveLength(1);
expect(digest).toBe(credentialRoot);
});
test("digests a document when multiple element are obfuscated", () => {
const obfuscatedVerifiableCredential = obfuscateVerifiableCredential(verifiableCredential, [
"credentialSubject.id",
"credentialSubject.name",
"credentialSubject.licenses.0.description",
]);
const digest = digestCredential(
obfuscatedVerifiableCredential,
decodeSalt(obfuscatedVerifiableCredential.proof.salts),
obfuscatedVerifiableCredential.proof.privacy.obfuscated
);
expect(OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated).toMatchInlineSnapshot(`
[
"410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7",
]
`);

expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toMatchInlineSnapshot(`
[
"84c8662d07d3b98b7b9b58687a04fd6ff5a90e91f63e70c2399755721630b370",
"4390ee551a3ef3bebaad99c85738b3ebd96932343fb22a59865764125b79565c",
"026dbfc89aaa98005d2f25b0b274a972f1dc5c351d22270eba9d80422dd9850f",
]
`);
expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toHaveLength(3);
expect(digest).toBe(credentialRoot);
});
test("digests a document with no visible content correctly", () => {
const obfuscatedVerifiableCredential = obfuscateVerifiableCredential(
verifiableCredential,
Object.keys(verifiableCredential).filter((k) => k != "proof")
);
const digest = digestCredential(
obfuscatedVerifiableCredential,
decodeSalt(obfuscatedVerifiableCredential.proof.salts),
obfuscatedVerifiableCredential.proof.privacy.obfuscated
);
const digest = digestCredential(
OBFUSCATED_WRAPPED_DOCUMENT,
decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts),
OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated
);
expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH);
expect(digest).toBe(OBFUSCATED_WRAPPED_DOCUMENT.proof.targetHash);
});

expect(obfuscatedVerifiableCredential).toStrictEqual({ proof: obfuscatedVerifiableCredential.proof });
expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toMatchInlineSnapshot(`
[
"f0798858da35807f0e5ae1a253722da6eb073abfad039151a18355d71e18f232",
"867ae2f030d04745d384969efe67b9fdfeea3236aa6b5f10d2bdbfb495a1ecb3",
"671da469c4211222ef05dcfc4fb795b6d774f5a1fc9f1397fab7ff6eba58e5db",
"b92f17321f80808f90ee5c1b089fad1b8ad2ff63e8d4d4ba923e50d0996aba75",
"21d7f40f46a97e9480b48739b560fba4cfe6d2f1b6bf14e3bdf7c9d765590a9a",
"4b13961eed15c275d3b8c11c4d40d8f956ffa8f1361b36058da28349c155d193",
"016c17fefa241351dc2950cfbeaef8281b0bc71e1ee445d890e9c37622fa0318",
"c5796036b237228ddc64bab40cd34200cb8d9dc4574c8a9a7cdda2350d77bdf9",
"b031b7f3cc154783acc36cbdc524bb7d8e4f4093785d25c1000a15c49e0ce58b",
"0913c1f68e821d8b4b07c9406419f083cd326c989bf433ccd13c242fdf834497",
"0c9bbd46994b92637562fef0df5a95eb4549a0198923c66693b547311635455a",
"5dff1a92a0cae0a5d50530968ff06c2baea9d3ac11b415268d98728ff13a4aa6",
"363e3a4656d4b586d1855a4cc22e56b4b446a357f2c76bdc777df6596d22e7e3",
"13e4d679f8cc43a69c7fbc37cd6339ee3864eeaca137687b6c7cff07309f6f98",
"5d027cec038e4f0fbb684da654f12999b973e20788801e13e063f642228d56a5",
"6d8b020b1ef826ce5e05fb034f4d2b9c4ed5bc4d4a0d697a6ec9f6c249970cb0",
"97bbd9a5415e96e1f5f61879e1bdef14db6868304ab3b681c6bbb82e0ecd21b3",
"84c8662d07d3b98b7b9b58687a04fd6ff5a90e91f63e70c2399755721630b370",
"c96b471fec27d76d3b5e1c479ccf690bca845ba78bc2b6b28abd52f9defcf491",
"4390ee551a3ef3bebaad99c85738b3ebd96932343fb22a59865764125b79565c",
"6d38b0c91fa83fd141a20098b121eca264dcf8c20e6bd97d13b9a5e8924026c2",
"026dbfc89aaa98005d2f25b0b274a972f1dc5c351d22270eba9d80422dd9850f",
"5bc0eb80d28496cfe3ed416b91fada582f097bbdaaedcff5aa5e393c8f8be726",
"6fb9f93f2b42bb70a67e6ad5cb22f72083d9d3bf98776e83a470c82800770623",
"aa4414e7a955a034998fd1221c80a2ef77c30c26a7b15fe15b7c2716811bb3d9",
"fba6d49a55387b611fb4dedf401630d3adb1d377e17ba051524a09795ee734ae",
]
test("given a document with THREE elements obfuscated, should digest and match the root credential's target hash", () => {
const OBFUSCATED_WRAPPED_DOCUMENT = obfuscateVerifiableCredential(ROOT_CREDENTIAL, [
"credentialSubject.id",
"credentialSubject.name",
"credentialSubject.licenses[0].description",
]);
expect(OBFUSCATED_WRAPPED_DOCUMENT.credentialSubject).toMatchInlineSnapshot(`
{
"licenses": [
{
"class": "3",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
{
"class": "3A",
"description": "Motor cars with unladen weight <= 3000kg",
"effectiveDate": "2013-05-16T00:00:00+08:00",
},
],
"type": [
"DriversLicense",
],
}
`);
expect(obfuscatedVerifiableCredential.proof.privacy.obfuscated).toHaveLength(26);
expect(digest).toBe(credentialRoot);
});
expect(OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated).toMatchInlineSnapshot(`
[
"410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7",
"21f8a6f2f464ff14afbc52e4dcb965d7891a7c63fd37eb93f8f98477dcdfc7f9",
"228eb6b469ca3a475238455f11125b7edc826c6dc3ae727d023d1eb71d0e60d6",
]
`);

const digest = digestCredential(
OBFUSCATED_WRAPPED_DOCUMENT,
decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts),
OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated
);
expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH);
expect(digest).toBe(OBFUSCATED_WRAPPED_DOCUMENT.proof.targetHash);
});

test("given a document with NO VISIBLE FIELDS, should digest and match the root credential's target hash", () => {
// this has to be manually generated, since obfuscateVerifiableCredential does not allow obfuscating fields that
// result in a non compliant V4 OA document
const OBFUSCATED_WRAPPED_DOCUMENT = {
// no visible fields
proof: {
type: "OpenAttestationMerkleProofSignature2018",
proofPurpose: "assertionMethod",
targetHash: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa",
proofs: [],
merkleRoot: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa",
salts: "W10=",
privacy: {
obfuscated: [
"0fd4ac5ade244ee2fe47437ea43cd142479540b878fffc86662600fce4d47ef5",
"0cc6e4c50bb090af720d224a9bd73be4c0d72831fc701907339693cdcb34ede3",
"d2afadbec39872577eae0d5e4ea3b590608cab744f214a2f703f65a5b41683cb",
"569b596d71fb145e9c87be1b301da3cbc89cfc104627f6dd95c8123f7974e9c6",
"5dee7aa2b48b9a5edae5042459c7c3eeaa8c5b13132b1477641c727a89471b36",
"2a1ff14be659821afa68edc245f67b9e25331b450715b41348ed2405334d5abd",
"0f1d172b5352464121dffc550e16f64b8019637e39768c506fd2e517a0da305d",
"ff4eeed1d7bb70aef646d46dc75b3408cf019e0daeaf2ef0313974690d8beef2",
"2a4e9fd43be0221af2f02a6b959edf704b630559268a0b2a657fe046e282fbb8",
"bbdf2b05cc0bd2a64fc3483211806e2f863bea05fba81f63092ec07c4ee8ebd9",
"bd9acf6bef05f94720f0fa9c5540bb9db7d6370c39e2bbbee31e408842985dae",
"410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7",
"32a55f464387e37df8f74cf3de6a8e04626e19c2f4d5ec8931aee4b866329fb8",
"21f8a6f2f464ff14afbc52e4dcb965d7891a7c63fd37eb93f8f98477dcdfc7f9",
"6bc7b2350b59b02a44d2593ee7538590114544bc3a39fe9564ee49b387c883c4",
"228eb6b469ca3a475238455f11125b7edc826c6dc3ae727d023d1eb71d0e60d6",
"d6e7027dd62b265e83aaf306f095446efab2677e940a0fbb118cc91dd8226fdb",
"da26ce90128b1cfd747218cad4c7e86b83f6ab236598ce18aecc3b10426b1b71",
"5edea35aa869577c2fd14159534b08da061a7833665cf1cc28f400474c26be01",
"d55b72f926f7adaa5ea4f271ffc2f574e4859b05c16042f5b604e52f044a11d0",
"dd69de699de90b82cfb658fc304ae4f3131e841d56fd68eb20e17af73613a4d3",
"280bc622006d5ec28a42096b57f15f8238df27762c3f754d56dcd89f3aa02c25",
"3d8bc5cbcd2826489cdc80a64d586a4d220d975bc2848aa535bd1e4f17dc619f",
],
},
key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller",
signature:
"0xa3ac9f73a7314c0aad47bad875921f5c88d2af9440d6c309fc2f93dbf43bd8235e84b744cb1ff1c09c214b559ce3bd6eb148c2f68c677cb8408d96e9b5411dfb1c",
},
} as unknown as V4SignedWrappedDocument;

const digest = digestCredential(
OBFUSCATED_WRAPPED_DOCUMENT,
decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts),
OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated
);
expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH);
});
});