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 • 11.8 kB
{"version":3,"file":"peerDidNumAlgo2.mjs","names":[],"sources":["../../../../../src/modules/dids/methods/peer/peerDidNumAlgo2.ts"],"sourcesContent":["import { CredoError } from '../../../../error'\nimport type { JsonObject } from '../../../../types'\nimport { JsonEncoder, JsonTransformer } from '../../../../utils'\nimport { PublicJwk } from '../../../kms'\nimport type { DidDocument, VerificationMethod } from '../../domain'\nimport { DidDocumentService } from '../../domain'\nimport { DidDocumentBuilder } from '../../domain/DidDocumentBuilder'\nimport {\n getPublicJwkFromVerificationMethod,\n getVerificationMethodsForPublicJwk,\n} from '../../domain/key-type/keyDidMapping'\nimport { parseDid } from '../../domain/parse'\n\nenum DidPeerPurpose {\n Assertion = 'A',\n Encryption = 'E',\n Verification = 'V',\n CapabilityInvocation = 'I',\n CapabilityDelegation = 'D',\n Service = 'S',\n}\n\nfunction isDidPeerKeyPurpose(purpose: string): purpose is Exclude<DidPeerPurpose, DidPeerPurpose.Service> {\n return purpose !== DidPeerPurpose.Service && Object.values(DidPeerPurpose).includes(purpose as DidPeerPurpose)\n}\n\nconst didPeerAbbreviations: { [key: string]: string | undefined } = {\n type: 't',\n DIDCommMessaging: 'dm',\n serviceEndpoint: 's',\n routingKeys: 'r',\n accept: 'a',\n}\n\nconst didPeerExpansions: { [key: string]: string | undefined } = {\n t: 'type',\n dm: 'DIDCommMessaging',\n s: 'serviceEndpoint',\n r: 'routingKeys',\n a: 'accept',\n}\n\nexport function didToNumAlgo2DidDocument(did: string) {\n const parsed = parseDid(did)\n const identifierWithoutNumAlgo = parsed.id.substring(2)\n\n // Get a list of all did document entries splitted by .\n const entries = identifierWithoutNumAlgo.split('.')\n const didDocument = new DidDocumentBuilder(did)\n let serviceIndex = 0\n let keyIndex = 1\n\n for (const entry of entries) {\n // Remove the purpose identifier to get the service or key content\n const entryContent = entry.substring(1)\n // Get the purpose identifier\n const purpose = entry[0]\n\n // Handle service entry first\n if (purpose === DidPeerPurpose.Service) {\n let services = JsonEncoder.fromBase64Url(entryContent)\n\n // Make sure we have an array of services (can be both json or array)\n services = Array.isArray(services) ? services : [services]\n\n for (let service of services) {\n // Expand abbreviations used for service key/values\n service = expandServiceAbbreviations(service)\n\n service.id = `${did}#${service.type.toLowerCase()}-${serviceIndex++}`\n\n didDocument.addService(JsonTransformer.fromJSON(service, DidDocumentService))\n }\n }\n // Otherwise we can be sure it is a key\n else {\n // Decode the fingerprint, and extract the verification method(s)\n const publicJwk = PublicJwk.fromFingerprint(entryContent)\n const verificationMethods = getVerificationMethodsForPublicJwk(publicJwk, did)\n\n // Add all verification methods to the did document\n for (const verificationMethod of verificationMethods) {\n verificationMethod.id = `${did}#key-${keyIndex++}`\n addVerificationMethodToDidDocument(didDocument, verificationMethod, purpose)\n }\n }\n }\n\n return didDocument.build()\n}\n\nexport function didDocumentToNumAlgo2Did(didDocument: DidDocument) {\n const purposeMapping = {\n [DidPeerPurpose.Assertion]: didDocument.assertionMethod,\n [DidPeerPurpose.Encryption]: didDocument.keyAgreement,\n // FIXME: should verification be authentication or verificationMethod\n // verificationMethod is general so it doesn't make a lot of sense to add\n // it to the verificationMethod list\n [DidPeerPurpose.Verification]: didDocument.authentication,\n [DidPeerPurpose.CapabilityInvocation]: didDocument.capabilityInvocation,\n [DidPeerPurpose.CapabilityDelegation]: didDocument.capabilityDelegation,\n }\n\n let did = 'did:peer:2'\n\n const keys: { id: string; encoded: string }[] = []\n\n for (const [purpose, entries] of Object.entries(purposeMapping)) {\n // Not all entries are required to be defined\n if (entries === undefined) continue\n\n // Dereference all entries to full verification methods\n const dereferenced = entries.map((entry) =>\n typeof entry === 'string' ? didDocument.dereferenceVerificationMethod(entry) : entry\n )\n\n // Transform all verification methods into a fingerprint (multibase, multicodec)\n for (const entry of dereferenced) {\n const key = getPublicJwkFromVerificationMethod(entry)\n\n // Encode as '.PurposeFingerprint'\n const encoded = `.${purpose}${key.fingerprint}`\n\n keys.push({ id: entry.id, encoded })\n }\n }\n\n const prefix = 'key-'\n if (!keys.every((key) => key.id.split('#')[1]?.startsWith(prefix))) {\n throw new CredoError('Ids for keys within DID Document for did:peer:2 creation must follow the pattern `#key-n`')\n }\n\n // Add all encoded keys ordered by their id (#key-1, #key-2, etc.)\n did += keys\n .sort((a, b) => {\n const aFragment = a.id.split('#')[1]\n const bFragment = b.id.split('#')[1]\n const aIndex = Number(aFragment.replace(prefix, ''))\n const bIndex = Number(bFragment.replace(prefix, ''))\n\n return aIndex - bIndex\n })\n .map((key) => key.encoded)\n .join('')\n\n if (didDocument.service && didDocument.service.length > 0) {\n const abbreviatedServices = didDocument.service.map((service) => {\n // Transform to JSON, remove id property\n const serviceJson = JsonTransformer.toJSON(service)\n serviceJson.id = undefined\n\n return abbreviateServiceJson(serviceJson)\n })\n\n for (const abbreviatedService of abbreviatedServices) {\n const encodedService = JsonEncoder.toBase64Url(abbreviatedService)\n did += `.${DidPeerPurpose.Service}${encodedService}`\n }\n }\n\n return did\n}\n\nfunction expandServiceAbbreviations(service: JsonObject) {\n const expand = (abbreviated: string) => didPeerExpansions[abbreviated] ?? abbreviated\n const expandJson = (json: unknown): unknown => {\n if (!json) return json\n if (typeof json === 'number') return json\n if (typeof json === 'string') return expand(json)\n if (Array.isArray(json)) return json.map(expandJson)\n if (typeof json === 'object')\n return Object.entries(json as Record<string, unknown>).reduce(\n (jsonBody, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: no explanation\n ...jsonBody,\n [expand(key)]: expandJson(value),\n }),\n {}\n )\n }\n\n const fullService = expandJson(service) as Record<string, unknown>\n\n // Handle the case where a legacy DIDComm v2 service has been encoded in the did:peer:2.\n // We use the legacy `DIDComm` type (over `DIDCommMessaging`)\n if ('t' in service && service.t === 'dm' && typeof service.serviceEndpoint === 'string') {\n return {\n ...fullService,\n type: 'DIDComm',\n }\n }\n\n return fullService\n}\n\nfunction abbreviateServiceJson(service: JsonObject) {\n const abbreviate = (expanded: string) => didPeerAbbreviations[expanded] ?? expanded\n\n const abbreviatedService = Object.entries(service).reduce(\n (serviceBody, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: no explanation\n ...serviceBody,\n [abbreviate(key)]: abbreviate(value as string),\n }),\n {}\n )\n\n return abbreviatedService\n}\n\nfunction addVerificationMethodToDidDocument(\n didDocument: DidDocumentBuilder,\n verificationMethod: VerificationMethod,\n purpose: string\n) {\n const purposeMapping = {\n [DidPeerPurpose.Assertion]: didDocument.addAssertionMethod.bind(didDocument),\n [DidPeerPurpose.Encryption]: didDocument.addKeyAgreement.bind(didDocument),\n // FIXME: should verification be authentication or verificationMethod\n // verificationMethod is general so it doesn't make a lot of sense to add\n // it to the verificationMethod list\n [DidPeerPurpose.Verification]: didDocument.addAuthentication.bind(didDocument),\n [DidPeerPurpose.CapabilityInvocation]: didDocument.addCapabilityInvocation.bind(didDocument),\n [DidPeerPurpose.CapabilityDelegation]: didDocument.addCapabilityDelegation.bind(didDocument),\n }\n\n // Verify the purpose is a did peer key purpose (service excluded)\n if (isDidPeerKeyPurpose(purpose)) {\n const addVerificationMethod = purposeMapping[purpose]\n\n // Add the verification method based on the method from the mapping\n addVerificationMethod(verificationMethod)\n } else {\n throw new CredoError(`Unsupported peer did purpose '${purpose}'`)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,IAAK,0DAAL;AACE;AACA;AACA;AACA;AACA;AACA;;EANG;AASL,SAAS,oBAAoB,SAA6E;AACxG,QAAO,YAAY,eAAe,WAAW,OAAO,OAAO,eAAe,CAAC,SAAS,QAA0B;;AAGhH,MAAM,uBAA8D;CAClE,MAAM;CACN,kBAAkB;CAClB,iBAAiB;CACjB,aAAa;CACb,QAAQ;CACT;AAED,MAAM,oBAA2D;CAC/D,GAAG;CACH,IAAI;CACJ,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,SAAgB,yBAAyB,KAAa;CAKpD,MAAM,UAJS,SAAS,IAAI,CACY,GAAG,UAAU,EAAE,CAGd,MAAM,IAAI;CACnD,MAAM,cAAc,IAAI,mBAAmB,IAAI;CAC/C,IAAI,eAAe;CACnB,IAAI,WAAW;AAEf,MAAK,MAAM,SAAS,SAAS;EAE3B,MAAM,eAAe,MAAM,UAAU,EAAE;EAEvC,MAAM,UAAU,MAAM;AAGtB,MAAI,YAAY,eAAe,SAAS;GACtC,IAAI,WAAW,YAAY,cAAc,aAAa;AAGtD,cAAW,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS;AAE1D,QAAK,IAAI,WAAW,UAAU;AAE5B,cAAU,2BAA2B,QAAQ;AAE7C,YAAQ,KAAK,GAAG,IAAI,GAAG,QAAQ,KAAK,aAAa,CAAC,GAAG;AAErD,gBAAY,WAAW,gBAAgB,SAAS,SAAS,mBAAmB,CAAC;;SAI5E;GAGH,MAAM,sBAAsB,mCADV,UAAU,gBAAgB,aAAa,EACiB,IAAI;AAG9E,QAAK,MAAM,sBAAsB,qBAAqB;AACpD,uBAAmB,KAAK,GAAG,IAAI,OAAO;AACtC,uCAAmC,aAAa,oBAAoB,QAAQ;;;;AAKlF,QAAO,YAAY,OAAO;;AAG5B,SAAgB,yBAAyB,aAA0B;CACjE,MAAM,iBAAiB;GACpB,eAAe,YAAY,YAAY;GACvC,eAAe,aAAa,YAAY;GAIxC,eAAe,eAAe,YAAY;GAC1C,eAAe,uBAAuB,YAAY;GAClD,eAAe,uBAAuB,YAAY;EACpD;CAED,IAAI,MAAM;CAEV,MAAM,OAA0C,EAAE;AAElD,MAAK,MAAM,CAAC,SAAS,YAAY,OAAO,QAAQ,eAAe,EAAE;AAE/D,MAAI,YAAY,OAAW;EAG3B,MAAM,eAAe,QAAQ,KAAK,UAChC,OAAO,UAAU,WAAW,YAAY,8BAA8B,MAAM,GAAG,MAChF;AAGD,OAAK,MAAM,SAAS,cAAc;GAIhC,MAAM,UAAU,IAAI,UAHR,mCAAmC,MAAM,CAGnB;AAElC,QAAK,KAAK;IAAE,IAAI,MAAM;IAAI;IAAS,CAAC;;;CAIxC,MAAM,SAAS;AACf,KAAI,CAAC,KAAK,OAAO,QAAQ,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,WAAW,OAAO,CAAC,CAChE,OAAM,IAAI,WAAW,4FAA4F;AAInH,QAAO,KACJ,MAAM,GAAG,MAAM;EACd,MAAM,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC;EAClC,MAAM,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC;AAIlC,SAHe,OAAO,UAAU,QAAQ,QAAQ,GAAG,CAAC,GACrC,OAAO,UAAU,QAAQ,QAAQ,GAAG,CAAC;GAGpD,CACD,KAAK,QAAQ,IAAI,QAAQ,CACzB,KAAK,GAAG;AAEX,KAAI,YAAY,WAAW,YAAY,QAAQ,SAAS,GAAG;EACzD,MAAM,sBAAsB,YAAY,QAAQ,KAAK,YAAY;GAE/D,MAAM,cAAc,gBAAgB,OAAO,QAAQ;AACnD,eAAY,KAAK;AAEjB,UAAO,sBAAsB,YAAY;IACzC;AAEF,OAAK,MAAM,sBAAsB,qBAAqB;GACpD,MAAM,iBAAiB,YAAY,YAAY,mBAAmB;AAClE,UAAO,IAAI,eAAe,UAAU;;;AAIxC,QAAO;;AAGT,SAAS,2BAA2B,SAAqB;CACvD,MAAM,UAAU,gBAAwB,kBAAkB,gBAAgB;CAC1E,MAAM,cAAc,SAA2B;AAC7C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,SAAU,QAAO,OAAO,KAAK;AACjD,MAAI,MAAM,QAAQ,KAAK,CAAE,QAAO,KAAK,IAAI,WAAW;AACpD,MAAI,OAAO,SAAS,SAClB,QAAO,OAAO,QAAQ,KAAgC,CAAC,QACpD,UAAU,CAAC,KAAK,YAAY;GAE3B,GAAG;IACF,OAAO,IAAI,GAAG,WAAW,MAAM;GACjC,GACD,EAAE,CACH;;CAGL,MAAM,cAAc,WAAW,QAAQ;AAIvC,KAAI,OAAO,WAAW,QAAQ,MAAM,QAAQ,OAAO,QAAQ,oBAAoB,SAC7E,QAAO;EACL,GAAG;EACH,MAAM;EACP;AAGH,QAAO;;AAGT,SAAS,sBAAsB,SAAqB;CAClD,MAAM,cAAc,aAAqB,qBAAqB,aAAa;AAW3E,QAT2B,OAAO,QAAQ,QAAQ,CAAC,QAChD,aAAa,CAAC,KAAK,YAAY;EAE9B,GAAG;GACF,WAAW,IAAI,GAAG,WAAW,MAAgB;EAC/C,GACD,EAAE,CACH;;AAKH,SAAS,mCACP,aACA,oBACA,SACA;CACA,MAAM,iBAAiB;GACpB,eAAe,YAAY,YAAY,mBAAmB,KAAK,YAAY;GAC3E,eAAe,aAAa,YAAY,gBAAgB,KAAK,YAAY;GAIzE,eAAe,eAAe,YAAY,kBAAkB,KAAK,YAAY;GAC7E,eAAe,uBAAuB,YAAY,wBAAwB,KAAK,YAAY;GAC3F,eAAe,uBAAuB,YAAY,wBAAwB,KAAK,YAAY;EAC7F;AAGD,KAAI,oBAAoB,QAAQ,EAAE;EAChC,MAAM,wBAAwB,eAAe;AAG7C,wBAAsB,mBAAmB;OAEzC,OAAM,IAAI,WAAW,iCAAiC,QAAQ,GAAG"}