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 • 16.9 kB
{"version":3,"file":"DidDocument.mjs","names":[],"sources":["../../../../src/modules/dids/domain/DidDocument.ts"],"sourcesContent":["import { Expose, Type } from 'class-transformer'\nimport { IsArray, IsOptional, IsString, ValidateNested } from 'class-validator'\nimport { CredoError } from '../../../error'\nimport { TypedArrayEncoder } from '../../../utils'\nimport { JsonTransformer } from '../../../utils/JsonTransformer'\nimport { IsStringOrStringArray } from '../../../utils/transformers'\nimport { Ed25519PublicJwk, PublicJwk, X25519PublicJwk } from '../../kms'\nimport { findMatchingEd25519Key } from '../findMatchingEd25519Key'\nimport { getPublicJwkFromVerificationMethod } from './key-type'\nimport type { DidDocumentService } from './service'\nimport { DidCommV1Service, IndyAgentService } from './service'\nimport { ServiceTransformer } from './service/ServiceTransformer'\nimport { IsStringOrVerificationMethod, VerificationMethod, VerificationMethodTransformer } from './verificationMethod'\n\nexport type DidPurpose =\n | 'authentication'\n | 'keyAgreement'\n | 'assertionMethod'\n | 'capabilityInvocation'\n | 'capabilityDelegation'\n\ntype DidVerificationMethods = DidPurpose | 'verificationMethod'\n\ninterface DidDocumentOptions {\n context?: string | string[]\n id: string\n alsoKnownAs?: string[]\n controller?: string | string[]\n verificationMethod?: VerificationMethod[]\n service?: DidDocumentService[]\n authentication?: Array<string | VerificationMethod>\n assertionMethod?: Array<string | VerificationMethod>\n keyAgreement?: Array<string | VerificationMethod>\n capabilityInvocation?: Array<string | VerificationMethod>\n capabilityDelegation?: Array<string | VerificationMethod>\n}\n\nexport class DidDocument {\n @Expose({ name: '@context' })\n @IsStringOrStringArray()\n public context: string | string[] = ['https://www.w3.org/ns/did/v1']\n\n @IsString()\n public id!: string\n\n @IsArray()\n @IsString({ each: true })\n @IsOptional()\n public alsoKnownAs?: string[]\n\n @IsStringOrStringArray()\n @IsOptional()\n public controller?: string | string[]\n\n @IsArray()\n @ValidateNested({ each: true })\n @Type(() => VerificationMethod)\n @IsOptional()\n public verificationMethod?: VerificationMethod[]\n\n @IsArray()\n @ServiceTransformer()\n @IsOptional()\n public service?: DidDocumentService[]\n\n @IsArray()\n @VerificationMethodTransformer()\n @IsStringOrVerificationMethod({ each: true })\n @IsOptional()\n public authentication?: Array<string | VerificationMethod>\n\n @IsArray()\n @VerificationMethodTransformer()\n @IsStringOrVerificationMethod({ each: true })\n @IsOptional()\n public assertionMethod?: Array<string | VerificationMethod>\n\n @IsArray()\n @VerificationMethodTransformer()\n @IsStringOrVerificationMethod({ each: true })\n @IsOptional()\n public keyAgreement?: Array<string | VerificationMethod>\n\n @IsArray()\n @VerificationMethodTransformer()\n @IsStringOrVerificationMethod({ each: true })\n @IsOptional()\n public capabilityInvocation?: Array<string | VerificationMethod>\n\n @IsArray()\n @VerificationMethodTransformer()\n @IsStringOrVerificationMethod({ each: true })\n @IsOptional()\n public capabilityDelegation?: Array<string | VerificationMethod>\n\n public constructor(options: DidDocumentOptions) {\n if (options) {\n this.context = options.context ?? this.context\n this.id = options.id\n this.alsoKnownAs = options.alsoKnownAs\n this.controller = options.controller\n this.verificationMethod = options.verificationMethod\n this.service = options.service\n this.authentication = options.authentication\n this.assertionMethod = options.assertionMethod\n this.keyAgreement = options.keyAgreement\n this.capabilityInvocation = options.capabilityInvocation\n this.capabilityDelegation = options.capabilityDelegation\n }\n }\n\n public dereferenceVerificationMethod(keyId: string) {\n // TODO: once we use JSON-LD we should use that to resolve references in did documents.\n // for now we check whether the key id ends with the keyId.\n // so if looking for #123 and key.id is did:key:123#123, it is valid. But #123 as key.id is also valid\n const verificationMethod = this.verificationMethod?.find((key) => this.matchKeyId(keyId, key.id))\n\n if (!verificationMethod) {\n throw new CredoError(`Unable to locate verification method with id '${keyId}'`)\n }\n\n return verificationMethod\n }\n\n public dereferenceKey(keyId: string, allowedPurposes?: DidVerificationMethods[]) {\n const allPurposes: DidVerificationMethods[] = [\n 'authentication',\n 'keyAgreement',\n 'assertionMethod',\n 'capabilityInvocation',\n 'capabilityDelegation',\n 'verificationMethod',\n ]\n\n const purposes = allowedPurposes ?? allPurposes\n\n for (const purpose of purposes) {\n for (const key of this[purpose] ?? []) {\n if (typeof key === 'string' && this.matchKeyId(keyId, key)) {\n return this.dereferenceVerificationMethod(key)\n }\n if (typeof key !== 'string' && this.matchKeyId(keyId, key.id)) {\n return key\n }\n }\n }\n\n throw new CredoError(`Unable to locate verification method with id '${keyId}' in purposes ${purposes}`)\n }\n\n private matchKeyId(externalKeyId: string, didDocumentKeyId: string) {\n // Compact is did removed from start but only if it matches the id of this document.\n const compactExternalKeyId = externalKeyId.startsWith(this.id) ? externalKeyId.slice(this.id.length) : externalKeyId\n const compactDidDocumentKeyId = didDocumentKeyId.startsWith(this.id)\n ? didDocumentKeyId.slice(this.id.length)\n : didDocumentKeyId\n\n return compactExternalKeyId === compactDidDocumentKeyId\n }\n\n public findVerificationMethodByPublicKey(publicJwk: PublicJwk, allowedPurposes?: DidVerificationMethods[]) {\n const allPurposes: DidVerificationMethods[] = [\n 'authentication',\n 'keyAgreement',\n 'assertionMethod',\n 'capabilityInvocation',\n 'capabilityDelegation',\n 'verificationMethod',\n ]\n\n const purposes = allowedPurposes ?? allPurposes\n\n for (const purpose of purposes) {\n for (const key of this[purpose] ?? []) {\n const verificationMethod = typeof key === 'string' ? this.dereferenceVerificationMethod(key) : key\n if (getPublicJwkFromVerificationMethod(verificationMethod).equals(publicJwk)) return verificationMethod\n }\n }\n\n throw new CredoError(\n `Unable to locate verification method with public key ${publicJwk.jwkTypeHumanDescription} in purposes ${purposes}`\n )\n }\n\n /**\n * Returns all of the service endpoints matching the given type.\n *\n * @param type The type of service(s) to query.\n */\n public getServicesByType<S extends DidDocumentService = DidDocumentService>(type: string): S[] {\n return (this.service?.filter((service) => service.type === type) ?? []) as S[]\n }\n\n /**\n * Returns all of the service endpoints matching the given class\n *\n * @param classType The class to query services.\n */\n public getServicesByClassType<S extends DidDocumentService = DidDocumentService>(\n classType: new (...args: never[]) => S\n ): S[] {\n return (this.service?.filter((service) => service instanceof classType) ?? []) as S[]\n }\n\n /**\n * Get all DIDComm services ordered by priority descending. This means the highest\n * priority will be the first entry.\n */\n public get didCommServices(): Array<IndyAgentService | DidCommV1Service> {\n const didCommServiceTypes = [IndyAgentService.type, DidCommV1Service.type]\n const services = (this.service?.filter((service) => didCommServiceTypes.includes(service.type)) ?? []) as Array<\n IndyAgentService | DidCommV1Service\n >\n\n // Sort services based on indicated priority\n return services.sort((a, b) => a.priority - b.priority)\n }\n\n // TODO: it would probably be easier if we add a utility to each service so we don't have to handle logic for all service types here\n public get recipientKeys(): PublicJwk<Ed25519PublicJwk | X25519PublicJwk>[] {\n return this.getRecipientKeysWithVerificationMethod({\n // False for now to avoid breaking changes\n mapX25519ToEd25519: false,\n }).map(({ publicJwk }) => publicJwk)\n }\n\n /**\n * Returns the recipient keys with their verification method matches\n *\n * We should probably deprecate recipientKeys in favour of this one\n */\n public getRecipientKeysWithVerificationMethod<MapX25519ToEd25519 extends boolean>({\n mapX25519ToEd25519,\n }: {\n mapX25519ToEd25519: MapX25519ToEd25519\n }): Array<{\n verificationMethod: VerificationMethod\n publicJwk: PublicJwk<MapX25519ToEd25519 extends true ? Ed25519PublicJwk : Ed25519PublicJwk | X25519PublicJwk>\n }> {\n const recipientKeys: Array<{\n verificationMethod: VerificationMethod\n publicJwk: PublicJwk<Ed25519PublicJwk | X25519PublicJwk>\n }> = []\n\n const seenVerificationMethodIds: string[] = []\n for (const service of this.didCommServices) {\n if (service.type === IndyAgentService.type) {\n for (const publicKeyBase58 of service.recipientKeys) {\n const publicJwk = PublicJwk.fromPublicKey({\n kty: 'OKP',\n crv: 'Ed25519',\n publicKey: TypedArrayEncoder.fromBase58(publicKeyBase58),\n })\n const verificationMethod = [...(this.verificationMethod ?? []), ...(this.authentication ?? [])]\n .map((v) => (typeof v === 'string' ? this.dereferenceVerificationMethod(v) : v))\n .find((v) => {\n const vPublicJwk = getPublicJwkFromVerificationMethod(v)\n return vPublicJwk.equals(publicJwk)\n })\n\n if (!verificationMethod) {\n throw new CredoError('Could not find verification method for IndyAgentService recipient key')\n }\n\n // Skip adding if already present\n if (seenVerificationMethodIds.includes(verificationMethod.id)) {\n continue\n }\n\n recipientKeys.push({\n publicJwk,\n verificationMethod,\n })\n }\n } else if (service.type === DidCommV1Service.type) {\n for (const recipientKey of service.recipientKeys) {\n const verificationMethod = this.dereferenceKey(recipientKey, ['authentication', 'keyAgreement'])\n if (seenVerificationMethodIds.includes(verificationMethod.id)) {\n // Skip adding if already present\n continue\n }\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n\n if (!publicJwk.is(Ed25519PublicJwk, X25519PublicJwk)) {\n throw new CredoError(\n 'Expected either Ed25519PublicJwk or X25519PublicJwk for DidcommV1Service recipient key'\n )\n }\n\n recipientKeys.push({\n publicJwk,\n verificationMethod,\n })\n }\n }\n }\n\n if (!mapX25519ToEd25519) {\n return recipientKeys as Array<{\n verificationMethod: VerificationMethod\n publicJwk: PublicJwk<MapX25519ToEd25519 extends true ? Ed25519PublicJwk : Ed25519PublicJwk | X25519PublicJwk>\n }>\n }\n\n return recipientKeys.map(({ publicJwk, verificationMethod }) => {\n if (publicJwk.is(Ed25519PublicJwk)) return { publicJwk, verificationMethod }\n\n const matchingEd25519Key = findMatchingEd25519Key(publicJwk as PublicJwk<X25519PublicJwk>, this)\n\n // For DIDcomm v1 if you use X25519 you MUST also include the Ed25519 key\n if (!matchingEd25519Key) {\n throw new CredoError(\n `Unable to find matching Ed25519 key for X25519 verification method with id ${verificationMethod.id}`\n )\n }\n\n return matchingEd25519Key\n })\n }\n\n public toJSON() {\n return JsonTransformer.toJSON(this)\n }\n\n public static fromJSON(didDocument: unknown) {\n return JsonTransformer.fromJSON(didDocument, DidDocument)\n }\n}\n\n/**\n * Extracting the verification method for signature type\n * @param type Signature type\n * @param didDocument DidDocument\n * @returns verification method\n */\nexport async function findVerificationMethodByKeyType(\n keyType: string,\n didDocument: DidDocument\n): Promise<VerificationMethod | null> {\n const didVerificationMethods: DidVerificationMethods[] = [\n 'verificationMethod',\n 'authentication',\n 'keyAgreement',\n 'assertionMethod',\n 'capabilityInvocation',\n 'capabilityDelegation',\n ]\n for (const purpose of didVerificationMethods) {\n const key: VerificationMethod[] | (string | VerificationMethod)[] | undefined = didDocument[purpose]\n if (Array.isArray(key)) {\n for (const method of key) {\n if (typeof method !== 'string') {\n if (method.type === keyType) {\n return method\n }\n }\n }\n }\n }\n\n return null\n}\n"],"mappings":"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"}