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

Add verifyAll and change the verify(verificationLevel, options) #104

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
102 changes: 100 additions & 2 deletions __test__/creds/VerifiableCredential.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ describe('Unit tests for Verifiable Credentials', () => {
done();
});

it('should fail verify() with maximum level of GRANTED if granted is invalid', async (done) => {
it('should fail verify() with maximum level of PROOFS if granted is invalid', async (done) => {
const name = new Claim.IdentityName({ givenNames: 'Joao', otherNames: 'Barbosa', familyNames: 'Santos' });
const dob = new Claim.IdentityDateOfBirth({ day: 20, month: 3, year: 1978 });
const cred = new VC('credential-cvc:Identity-v1', uuidv4(), null, [name, dob], '1');
Expand Down Expand Up @@ -795,7 +795,7 @@ describe('Unit tests for Verifiable Credentials', () => {


const verifyLevel = receivedCred.verify(VC.VERIFY_LEVELS.GRANTED, { requestorId, requestId });
expect(verifyLevel).toBeGreaterThanOrEqual(VC.VERIFY_LEVELS.ANCHOR); // Should be at least one level lower
expect(verifyLevel).toBeGreaterThanOrEqual(VC.VERIFY_LEVELS.PROOFS); // Should be at least one level lower

done();
});
Expand All @@ -811,6 +811,104 @@ describe('Unit tests for Verifiable Credentials', () => {
done();
});

it('should check all verifications with success', async (done) => {
const credentialContents = fs.readFileSync('__test__/creds/fixtures/VCPermanentAnchor.json', 'utf8');
const credentialJson = JSON.parse(credentialContents);
const cred = VC.fromJSON(credentialJson);

const subject = signAttestationSubject(cred.proof.anchor.subject, XPVT1, XPUB1);
const signedCred = VC.fromJSON(_.merge({}, cred, { proof: { anchor: { subject } } }));

expect(signedCred).toBeDefined();
expect(signedCred.proof.anchor).toBeDefined();

const requestorId = 'ANY_REQUESTOR_ID_12345';
const requestId = new Date().getTime(); // simulate an nonce ID
signedCred.grantUsageFor(requestorId, requestId, { pvtKey: XPVT1 });

expect(signedCred.granted).not.toBeNull();

const validation = await signedCred.verifyAll({ requestorId, requestId });
expect(validation).toBeTruthy();
done();
});

it('should check all verifications and fail - tampered grant', async (done) => {
const credentialContents = fs.readFileSync('__test__/creds/fixtures/VCPermanentAnchor.json', 'utf8');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that a require in test/creds/fixtures/VCPermanentAnchor.json is better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The anchor on this test is not checked. it fails before that.

const credentialJson = JSON.parse(credentialContents);
const cred = VC.fromJSON(credentialJson);

const subject = signAttestationSubject(cred.proof.anchor.subject, XPVT1, XPUB1);
const signedCred = VC.fromJSON(_.merge({}, cred, { proof: { anchor: { subject } } }));

expect(signedCred).toBeDefined();
expect(signedCred.proof.anchor).toBeDefined();

const requestorId = 'ANY_REQUESTOR_ID_12345';
const requestId = new Date().getTime(); // simulate an nonce ID
signedCred.grantUsageFor(requestorId, requestId, { pvtKey: XPVT1 });

expect(signedCred.granted).not.toBeNull();

// Tampering grant
// eslint-disable-next-line
signedCred.granted = '304502210085f6baceefcddefff535416df0eda6c9b8a01dcba592c599ec2c83cce7171dd802204473f5a15b3904dbf0fc309fe812fbf449948714938fb4871196d338ef38f1d1';


const validation = await signedCred.verifyAll({ requestorId, requestId });
expect(validation).toBeFalsy();
done();
});

it('should check all verifications and fail - tampered claims', async (done) => {
const credentialContents = fs.readFileSync('__test__/creds/fixtures/VCPermanentAnchor.json', 'utf8');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

const credentialJson = JSON.parse(credentialContents);
const cred = VC.fromJSON(credentialJson);

// Tampering claim
cred.claim.identity.name.givenNames = 'Jose';
const subject = signAttestationSubject(cred.proof.anchor.subject, XPVT1, XPUB1);
const signedCred = VC.fromJSON(_.merge({}, cred, { proof: { anchor: { subject } } }));

expect(signedCred).toBeDefined();
expect(signedCred.proof.anchor).toBeDefined();

const requestorId = 'ANY_REQUESTOR_ID_12345';
const requestId = new Date().getTime(); // simulate an nonce ID
signedCred.grantUsageFor(requestorId, requestId, { pvtKey: XPVT1 });

expect(signedCred.granted).not.toBeNull();

const validation = await signedCred.verifyAll({ requestorId, requestId });
expect(validation).toBeFalsy();
done();
});

it('should check all verifications and fail - anchor fails', async (done) => {
const credentialContents = fs.readFileSync('__test__/creds/fixtures/VCPermanentAnchor.json', 'utf8');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here as well

const credentialJson = JSON.parse(credentialContents);
const cred = VC.fromJSON(credentialJson);

const subject = signAttestationSubject(cred.proof.anchor.subject, XPVT1, XPUB1);
const signedCred = VC.fromJSON(_.merge({}, cred, { proof: { anchor: { subject } } }));

expect(signedCred).toBeDefined();
expect(signedCred.proof.anchor).toBeDefined();

const requestorId = 'ANY_REQUESTOR_ID_12345';
const requestId = new Date().getTime(); // simulate an nonce ID
signedCred.grantUsageFor(requestorId, requestId, { pvtKey: XPVT1 });

expect(signedCred.granted).not.toBeNull();

// Mock verifyAttestation to return false
signedCred.verifyAttestation = () => Promise.resolve(false);

const validation = await signedCred.verifyAll({ requestorId, requestId });
expect(validation).toBeFalsy();
done();
});

it.skip('should fail the check that the anchor exists on the chain', async (done) => {
const credentialContents = fs.readFileSync('__test__/creds/fixtures/VCTempAnchor.json', 'utf8');
const credentialJson = JSON.parse(credentialContents);
Expand Down
16 changes: 11 additions & 5 deletions src/creds/VerifiableCredential.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,10 @@ function VerifiableCredentialBaseConstructor(identifier, issuer, expiryIn, ucas,

/**
* Verify the Credential and return a verification level.
*
* VERIFY_LEVELS.ANCHOR and VERIFY_LEVELS.BLOCKCHAIN are not checked with this function,
* user async verifyAll():bool to test all levels including VERIFY_LEVELS.ANCHOR & VERIFY_LEVELS.BLOCKCHAIN
*
* @return Any of VC.VERIFY_LEVELS
*/
this.verify = (higherVerifyLevel, options) => {
Expand All @@ -476,17 +480,19 @@ function VerifiableCredentialBaseConstructor(identifier, issuer, expiryIn, ucas,

// Test next level
if (verifiedlevel === VERIFY_LEVELS.PROOFS
&& hVerifyLevel >= VERIFY_LEVELS.ANCHOR
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct that verify(leve) can now verify everything up to Anchor but not including Anchor? If so this should be probably documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are correct needs better documentation

&& this.verifyAttestation()) verifiedlevel = VERIFY_LEVELS.ANCHOR;

// Test next level
if (verifiedlevel === VERIFY_LEVELS.ANCHOR
&& hVerifyLevel >= VERIFY_LEVELS.GRANTED
&& this.verifyGrant(requestorId, requestId, keyName)) verifiedlevel = VERIFY_LEVELS.GRANTED;

return verifiedlevel;
};

this.verifyAll = async (options) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet... Only proposing it :-)

const verifiedlevel = this.verify(VERIFY_LEVELS.GRANTED, options);
const anchored = await this.verifyAttestation();

return ((verifiedlevel === VERIFY_LEVELS.GRANTED) && anchored);
};

/**
* This method checks if the signature matches for the root of the Merkle Tree
* @return true or false for the validation
Expand Down