UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

1 lines • 13.5 kB
{"version":3,"file":"JwsLinkedDataSignature.mjs","names":[],"sources":["../../../../../src/modules/vc/linked-data-proofs/signature-suites/JwsLinkedDataSignature.ts"],"sourcesContent":["/*!\n * Copyright (c) 2020-2021 Digital Bazaar, Inc. All rights reserved.\n */\n\nimport { CredoError } from '../../../../error'\nimport { JsonEncoder, TypedArrayEncoder } from '../../../../utils'\nimport { isKnownJwaSignatureAlgorithm, PublicJwk } from '../../../kms'\nimport { suites } from '../adapters/jsonld-signatures-adapter'\nimport type { LdKeyPair } from '../models/LdKeyPair'\nimport type { DocumentLoader, Proof, VerificationMethod } from '../proof-ops/jsonldUtil'\n\nconst LinkedDataSignature = suites.LinkedDataSignature\nexport interface JwsLinkedDataSignatureOptions {\n type: string\n algorithm: string\n LDKeyClass?: typeof LdKeyPair\n key?: LdKeyPair\n proof?: Proof\n date?: string\n contextUrl: string\n useNativeCanonize?: boolean\n}\n\nexport class JwsLinkedDataSignature extends LinkedDataSignature {\n /**\n * @param options - Options hashmap.\n * @param options.type - Provided by subclass.\n * @param options.alg - JWS alg provided by subclass.\n * @param [options.LDKeyClass] - Provided by subclass or subclass\n * overrides `getVerificationMethod`.\n *\n * Either a `key` OR at least one of `signer`/`verifier` is required.\n *\n * @param [options.key] - An optional key object (containing an\n * `id` property, and either `signer` or `verifier`, depending on the\n * intended operation. Useful for when the application is managing keys\n * itself (when using a KMS, you never have access to the private key,\n * and so should use the `signer` param instead).\n *\n * Advanced optional parameters and overrides.\n *\n * @param [options.proof] - A JSON-LD document with options to use\n * for the `proof` node. Any other custom fields can be provided here\n * using a context different from `security-v2`.\n * @param [options.date] - Signing date to use if not passed.\n * @param options.contextUrl - JSON-LD context url that corresponds\n * to this signature suite. Used for enforcing suite context during the\n * `sign()` operation.\n * @param [options.useNativeCanonize] - Whether to use a native\n * canonize algorithm.\n */\n public constructor(options: JwsLinkedDataSignatureOptions) {\n super({\n type: options.type,\n LDKeyClass: options.LDKeyClass,\n contextUrl: options.contextUrl,\n key: options.key,\n signer: undefined,\n verifier: undefined,\n proof: options.proof,\n date: options.date,\n useNativeCanonize: options.useNativeCanonize,\n })\n this.alg = options.algorithm\n }\n\n /**\n * @param options - Options hashmap.\n * @param options.verifyData - The data to sign.\n * @param options.proof - A JSON-LD document with options to use\n * for the `proof` node. Any other custom fields can be provided here\n * using a context different from `security-v2`.\n *\n * @returns The proof containing the signature value.\n */\n public async sign(options: { verifyData: Uint8Array; proof: Proof }) {\n if (!(this.signer && typeof this.signer.sign === 'function')) {\n throw new Error('A signer API has not been specified.')\n }\n\n // Ensure the key signs with the same algorithm as declared in the JWS header\n if (this.key?.publicJwk instanceof PublicJwk) {\n if (!isKnownJwaSignatureAlgorithm(this.alg)) {\n throw new CredoError(`Unsupported JWA signature algorithm '${this.alg}' for signature suite ${this.type}`)\n }\n this.key.publicJwk.alg = this.alg\n }\n\n // JWS header\n const header = {\n alg: this.alg,\n b64: false,\n crit: ['b64'],\n }\n\n /*\n +-------+-----------------------------------------------------------+\n | \"b64\" | JWS Signing Input Formula |\n +-------+-----------------------------------------------------------+\n | true | ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || |\n | | BASE64URL(JWS Payload)) |\n | | |\n | false | ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.') || |\n | | JWS Payload |\n +-------+-----------------------------------------------------------+\n */\n\n // create JWS data and sign\n const encodedHeader = JsonEncoder.toBase64Url(header)\n\n const data = _createJws({ encodedHeader, verifyData: options.verifyData })\n\n const signature = await this.signer.sign({ data })\n\n // create detached content signature\n const encodedSignature = TypedArrayEncoder.toBase64Url(signature)\n options.proof.jws = `${encodedHeader}..${encodedSignature}`\n return options.proof\n }\n\n /**\n * @param options - Options hashmap.\n * @param options.verifyData - The data to verify.\n * @param options.verificationMethod - A verification method.\n * @param options.proof - The proof to be verified.\n *\n * @returns Resolves with the verification result.\n */\n public async verifySignature(options: {\n verifyData: Uint8Array\n verificationMethod: VerificationMethod\n proof: Proof\n }) {\n if (!(options.proof.jws && typeof options.proof.jws === 'string' && options.proof.jws.includes('.'))) {\n throw new TypeError('The proof does not include a valid \"jws\" property.')\n }\n // add payload into detached content signature\n const [encodedHeader /*payload*/, , encodedSignature] = options.proof.jws.split('.')\n\n // biome-ignore lint/suspicious/noImplicitAnyLet: no explanation\n let header\n try {\n header = JsonEncoder.fromBase64Url(encodedHeader)\n } catch (e) {\n throw new Error(`Could not parse JWS header; ${e}`)\n }\n if (!(header && typeof header === 'object')) {\n throw new Error('Invalid JWS header.')\n }\n\n // confirm header matches all expectations\n if (\n !(\n header.alg === this.alg &&\n header.b64 === false &&\n Array.isArray(header.crit) &&\n header.crit.length === 1 &&\n header.crit[0] === 'b64' &&\n Object.keys(header).length === 3\n )\n ) {\n throw new Error(`Invalid JWS header parameters for ${this.type}.`)\n }\n\n // do signature verification\n const signature = TypedArrayEncoder.fromBase64Url(encodedSignature)\n\n const data = _createJws({ encodedHeader, verifyData: options.verifyData })\n\n let { verifier } = this\n if (!verifier) {\n const key = await this.LDKeyClass.from(options.verificationMethod)\n\n // Ensure verification uses the alg of the JWS header (checked above to match the suite algorithm)\n if (key.publicJwk instanceof PublicJwk) {\n if (!isKnownJwaSignatureAlgorithm(header.alg)) {\n throw new CredoError(`Unsupported JWA signature algorithm '${header.alg}' for signature suite ${this.type}`)\n }\n key.publicJwk.alg = header.alg\n }\n\n verifier = key.verifier()\n }\n return verifier.verify({ data, signature })\n }\n\n public async getVerificationMethod(options: { proof: Proof; documentLoader?: DocumentLoader }) {\n if (this.key) {\n // This happens most often during sign() operations. For verify(),\n // the expectation is that the verification method will be fetched\n // by the documentLoader (below), not provided as a `key` parameter.\n return this.key.export({ publicKey: true })\n }\n\n let { verificationMethod } = options.proof\n\n if (typeof verificationMethod === 'object' && verificationMethod !== null) {\n verificationMethod = verificationMethod.id\n }\n\n if (!verificationMethod) {\n throw new Error('No \"verificationMethod\" found in proof.')\n }\n\n if (!options.documentLoader) {\n throw new CredoError('Missing custom document loader. This is required for resolving verification methods.')\n }\n\n const { document } = await options.documentLoader(verificationMethod)\n\n verificationMethod = typeof document === 'string' ? JSON.parse(document) : document\n\n await this.assertVerificationMethod(verificationMethod)\n return verificationMethod\n }\n\n /**\n * Checks whether a given proof exists in the document.\n *\n * @param options - Options hashmap.\n * @param options.proof - A proof.\n * @param options.document - A JSON-LD document.\n * @param options.purpose - A jsonld-signatures ProofPurpose\n * instance (e.g. AssertionProofPurpose, AuthenticationProofPurpose, etc).\n * @param options.documentLoader - A secure document loader (it is\n * recommended to use one that provides static known documents, instead of\n * fetching from the web) for returning contexts, controller documents,\n * keys, and other relevant URLs needed for the proof.\n *\n * @returns Whether a match for the proof was found.\n */\n public async matchProof(options: {\n proof: Proof\n document: VerificationMethod\n // biome-ignore lint/suspicious/noExplicitAny: no explanation\n purpose: any\n documentLoader?: DocumentLoader\n }) {\n const proofMatches = await super.matchProof({\n proof: options.proof,\n document: options.document,\n purpose: options.purpose,\n documentLoader: options.documentLoader,\n })\n if (!proofMatches) {\n return false\n }\n // NOTE: When subclassing this suite: Extending suites will need to check\n\n if (!this.key) {\n // no key specified, so assume this suite matches and it can be retrieved\n return true\n }\n\n const { verificationMethod } = options.proof\n\n // only match if the key specified matches the one in the proof\n if (typeof verificationMethod === 'object') {\n return verificationMethod.id === this.key.id\n }\n return verificationMethod === this.key.id\n }\n}\n\n/**\n * Creates the bytes ready for signing.\n *\n * @param {object} options - Options hashmap.\n * @param {string} options.encodedHeader - A base64url encoded JWT header.\n * @param {Uint8Array} options.verifyData - Payload to sign/verify.\n * @returns {Uint8Array} A combined byte array for signing.\n */\nfunction _createJws(options: { encodedHeader: string; verifyData: Uint8Array }): Uint8Array {\n const encodedHeaderBytes = TypedArrayEncoder.fromUtf8String(`${options.encodedHeader}.`)\n\n // concatenate the two uint8arrays\n const data = new Uint8Array(encodedHeaderBytes.length + options.verifyData.length)\n data.set(encodedHeaderBytes, 0)\n data.set(options.verifyData, encodedHeaderBytes.length)\n return data\n}\n"],"mappings":"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"}