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 • 17.1 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 public findVerificationMethodsByPurpose(allowedPurposes: readonly DidVerificationMethods[]): VerificationMethod[] {\n const methods: VerificationMethod[] = []\n\n for (const purpose of allowedPurposes) {\n for (const entry of this[purpose] ?? []) {\n methods.push(typeof entry === 'string' ? this.dereferenceVerificationMethod(entry) : entry)\n }\n }\n\n return methods\n }\n\n public findVerificationMethodsByTypeAndPurpose(\n verificationMethodTypes: string | readonly string[],\n allowedPurposes: readonly DidVerificationMethods[]\n ): VerificationMethod[] {\n const acceptedTypes = new Set(\n typeof verificationMethodTypes === 'string' ? [verificationMethodTypes] : verificationMethodTypes\n )\n\n return this.findVerificationMethodsByPurpose(allowedPurposes).filter((method) => acceptedTypes.has(method.type))\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"],"mappings":"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"}