UNPKG

@ew-did-registry/claims

Version:

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

106 lines (102 loc) 3.36 kB
/* eslint-disable new-cap */ import { decrypt } from 'eciesjs'; import crypto from 'crypto'; import { bn, ecc } from 'sjcl'; import { Algorithms } from '@ew-did-registry/jwt'; import { IClaimsIssuer } from '../interface'; import { Claims } from '../claims'; import { IPrivateClaim, IPublicClaim } from '../models'; import { ProofVerifier } from '..'; export class ClaimsIssuer extends Claims implements IClaimsIssuer { /** * Verifies user signature on token and issue new token signed by issuer./ * Throws if user signature not valid * * @example * ```typescript * import { Keys } from '@ew-did-registry/keys'; * import { ClaimsIssuer } from '@ew-did-registry/claims'; * * const issuer = new Keys(); * claims = new ClaimsIssuer(issuer); * const issuedToken = await claims.issuePublicClaim(token); * ``` * @param { string | IPublicClaim } claim - claim to issue. Can be * specified as signed or unsigned claim * @returns { Promise<string> } issued token */ async issuePublicClaim( claim: string | IPublicClaim ): Promise<string> { if (typeof claim === 'string') { claim = this.jwt.decode(claim) as IPublicClaim; } const { claimData, did, credentialStatus, exp } = claim; const dataToSign = { claimData, did, signer: this.did, ...(credentialStatus && { credentialStatus }), exp, }; const signedToken = await this.jwt.sign(dataToSign, { algorithm: Algorithms.ES256, issuer: this.did, subject: claim.did, noTimestamp: true, }); return signedToken; } /** * Verifies user signature on token, decrypt private data and issue new token * with sha256-hashed decrypted data signed by issuer. Throws if user * signature not valid * * @example * ```typescript * import { Keys } from '@ew-did-registry/keys'; * import { ClaimsIssuer } from '@ew-did-registry/claims'; * * const issuer = new Keys(); * claims = new ClaimsIssuer(issuer); * const issuedToken = await claims.issuePrivateClaim(token); * ``` * @params { string } token to verify * @returns { Promise<string> } issued token */ async issuePrivateClaim(token: string): Promise<string> { if (!this.keys.privateKey) { throw new Error('Private claim not supported'); } const curve: sjcl.SjclEllipticalCurve = ecc.curves.k256; const g = curve.G; const claim: IPrivateClaim = this.jwt.decode(token) as IPrivateClaim; const proofVerifier = new ProofVerifier( await this.document.read(claim.signer) ); if (!(await proofVerifier.verifyAssertionProof(token))) { throw new Error('User signature not valid'); } claim.signer = this.did; Object.entries(claim.claimData).forEach(([key, value]) => { const decryptedField = decrypt( this.keys.privateKey as string, Buffer.from(value as string, 'hex') ); const fieldHash = crypto .createHash('sha256') .update(decryptedField) .digest('hex'); const PK = g.mult(new bn(fieldHash)); claim.claimData[key] = PK.toBits() as []; }); delete claim.iss; return this.jwt.sign(claim, { algorithm: Algorithms.ES256, issuer: this.did, subject: claim.sub as string, noTimestamp: true, }); } } export default ClaimsIssuer;