UNPKG

@ew-did-registry/claims

Version:

The package exposes functionality needed to create, inspect, approve, and verify Private and Public claims

210 lines (187 loc) 6.74 kB
import { decrypt } from 'eciesjs'; import chai, { expect } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { Keys, KeyType } from '@ew-did-registry/keys'; import { Methods } from '@ew-did-registry/did'; import { Operator, EwSigner, compressedSecp256k1KeyLength, } from '@ew-did-registry/did-ethr-resolver'; import { DidStore } from '@ew-did-registry/did-ipfs-store'; import { DIDDocumentFull } from '@ew-did-registry/did-document'; import { DIDAttribute, Encoding, IUpdateData, KeyTags, ProviderSettings, ProviderTypes, PubKeyType, } from '@ew-did-registry/did-resolver-interface'; import { ChildProcess } from 'child_process'; import { ClaimsUser, IClaimsUser, IPrivateClaim, IProofClaim, ProofVerifier, } from '../src'; import { deployRegistry, shutdownIpfsCluster, spawnIpfsCluster, } from '../../../tests'; chai.use(chaiAsPromised); chai.should(); const claimData = { name: 'John', }; const providerSettings: ProviderSettings = { type: ProviderTypes.HTTP, }; describe('[CLAIMS PACKAGE/USER CLAIMS]', function () { this.timeout(0); const userKeys = new Keys(); const userAddress = userKeys.getAddress(); const userDid = `did:${Methods.Erc1056}:${userAddress}`; const user = EwSigner.fromPrivateKey(userKeys.privateKey, providerSettings); let userDoc: DIDDocumentFull; const issuerKeys = new Keys(); const issuerAddress = issuerKeys.getAddress(); const issuerDid = `did:${Methods.Erc1056}:${issuerAddress}`; const issuer = EwSigner.fromPrivateKey( issuerKeys.privateKey, providerSettings ); const hexPrefixKeys = new Keys(); const hexPrefixAddress = hexPrefixKeys.getAddress(); let userClaims: IClaimsUser; let store: DidStore; let registry: string; let cluster: ChildProcess; before(async () => { registry = await deployRegistry([ issuerAddress, userAddress, hexPrefixAddress, ]); console.log(`registry: ${registry}`); cluster = await spawnIpfsCluster(); store = new DidStore('http://localhost:8080'); userDoc = new DIDDocumentFull( userDid, new Operator(user, { address: registry }) ); userClaims = new ClaimsUser(user, userDoc, store); const issuerDoc = new DIDDocumentFull( issuerDid, new Operator(issuer, { address: registry }) ); await userDoc.create(); await issuerDoc.create(); }); after(async () => { shutdownIpfsCluster(cluster); }); it('createPublicClaim should create token with claim data', async () => { const publicData = { name: 'John', }; const token = await userClaims.createPublicClaim(publicData); const proofVerifier = new ProofVerifier(await userDoc.read()); expect(await proofVerifier.verifyAssertionProof(token)).not.null; const claim = (await userClaims.jwt.verify( token, userClaims.keys.publicKey )) as Record<string, unknown>; claim.should.deep.include({ did: userDid, signer: userDid, claimData: publicData, }); }); it('creates and verifies 100 claims', async () => { const claims: { token: string; data: object }[] = []; for (let i = 0; i < 100; i++) { const data = { name: 'John', lastName: 'Doe', index: i }; // eslint-disable-next-line no-await-in-loop claims.push({ token: await userClaims.createPublicClaim(data), data }); } // eslint-disable-next-line no-restricted-syntax for (const { token, data } of claims) { // eslint-disable-next-line no-await-in-loop userClaims.verifyClaimContent(token, data); const proofVerifier = new ProofVerifier(await userDoc.read()); expect(await proofVerifier.verifyAssertionProof(token)).not.null; } }); it('createPrivateToken should create token with data decryptable by issuer', async () => { const secret = '123'; const { token, saltedFields } = await userClaims.createPrivateClaim( { secret }, issuerDid ); const claim = userClaims.jwt.decode(token) as IPrivateClaim; const decrypted = decrypt( issuerKeys.privateKey, Buffer.from(claim.claimData.secret as string, 'hex') ); decrypted.toString().should.equal(saltedFields.secret); }); it('createProofClaim should return well formed proof claim', async () => { const claimUrl = 'http://test.com'; const proofData = { secret: { value: '123abc', encrypted: true } }; const token = await userClaims.createProofClaim(claimUrl, proofData); const claim = (await userClaims.jwt.verify( token, userClaims.keys.publicKey )) as IProofClaim; claim.should.include({ did: userDid, signer: userDid, claimUrl }); claim.should.have.nested .property('proofData.secret.value.h') .which.instanceOf(Array); claim.should.have.nested .property('proofData.secret.value.s') .which.instanceOf(Array); }); it('self signed claim should be verified', async () => { const claim = await userClaims.createPublicClaim(claimData); const url = await userClaims.publishPublicClaim(claim, claimData); return userClaims.verify(url).should.be.fulfilled; }); /** * publicKeyHex property of W3C security vocab does not have 0x prefix * However, historically, some keys were added to DID Documents with a 0x prefix * Therefore, the verification should be able to handle both. * https://w3c-ccg.github.io/security-vocab/#publicKeyHex * https://w3c-ccg.github.io/lds-ecdsa-secp256k1-2019/ * https://github.com/decentralized-identity/ethr-did-resolver/issues/140 */ it('verifies claim of user with secp256k1 key with 0x prefix', async () => { const did = `did:${Methods.Erc1056}:${hexPrefixAddress}`; const signer = EwSigner.fromPrivateKey( hexPrefixKeys.privateKey, providerSettings ); const doc = new DIDDocumentFull( did, new Operator(signer, { address: registry }) ); // Manually doing "create" as need to add hex prefix const pubKey = signer.publicKey; pubKey.length.should.equal(compressedSecp256k1KeyLength); const updateData: IUpdateData = { algo: KeyType.Secp256k1, type: PubKeyType.VerificationKey2018, encoding: Encoding.HEX, // Adding hex prefix to simulate an owner key with a hex prefix value: { publicKey: `0x${signer.publicKey}`, tag: KeyTags.OWNER }, }; await doc.update(DIDAttribute.PublicKey, updateData); const userWithHexPrefixKey = new ClaimsUser(signer, doc, store); const claim = await userWithHexPrefixKey.createPublicClaim(claimData); const url = await userWithHexPrefixKey.publishPublicClaim(claim, claimData); return userWithHexPrefixKey.verify(url).should.be.fulfilled; }); });