UNPKG

@enbox/dids

Version:
201 lines 11.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { LocalKeyManager, CryptoUtils } from '@enbox/crypto'; import { DidError, DidErrorCode } from './did-error.js'; import { extractDidFragment, getVerificationMethods } from './utils.js'; /** * Represents a Decentralized Identifier (DID) along with its DID document, key manager, metadata, * and convenience functions. */ export class BearerDid { constructor({ uri, document, metadata, keyManager }) { this.uri = uri; this.document = document; this.metadata = metadata; this.keyManager = keyManager; } /** * Converts a `BearerDid` object to a portable format containing the URI and verification methods * associated with the DID. * * This method is useful when you need to represent the key material and metadata associated with * a DID in format that can be used independently of the specific DID method implementation. It * extracts both public and private keys from the DID's key manager and organizes them into a * `PortableDid` structure. * * @remarks * If the DID's key manager does not allow private keys to be exported, the `PortableDid` returned * will not contain a `privateKeys` property. This enables the importing and exporting DIDs that * use the same underlying KMS even if the KMS does not support exporting private keys. Examples * include hardware security modules (HSMs) and cloud-based KMS services like AWS KMS. * * If the DID's key manager does support exporting private keys, the resulting `PortableDid` will * include a `privateKeys` property which contains the same number of entries as there are * verification methods as the DID document, each with its associated private key and the * purpose(s) for which the key can be used (e.g., `authentication`, `assertionMethod`, etc.). * * @example * ```ts * // Assuming `did` is an instance of BearerDid * const portableDid = await did.export(); * // portableDid now contains the DID URI, document, metadata, and optionally, private keys. * ``` * * @returns A `PortableDid` containing the URI, DID document, metadata, and optionally private * keys associated with the `BearerDid`. * @throws An error if the DID document does not contain any verification methods or the keys for * any verification method are missing in the key manager. */ export() { return __awaiter(this, void 0, void 0, function* () { // Verify the DID document contains at least one verification method. if (!(Array.isArray(this.document.verificationMethod) && this.document.verificationMethod.length > 0)) { throw new Error(`DID document for '${this.uri}' is missing verification methods`); } // Create a new `PortableDid` copy object to store the exported data. let portableDid = JSON.parse(JSON.stringify({ uri: this.uri, document: this.document, metadata: this.metadata })); // If the BearerDid's key manager supports exporting private keys, add them to the portable DID. if ('exportKey' in this.keyManager && typeof this.keyManager.exportKey === 'function') { const privateKeys = []; for (let vm of this.document.verificationMethod) { if (!vm.publicKeyJwk) { throw new Error(`Verification method '${vm.id}' does not contain a public key in JWK format`); } // Compute the key URI of the verification method's public key. const keyUri = yield this.keyManager.getKeyUri({ key: vm.publicKeyJwk }); // Retrieve the private key from the key manager. const privateKey = yield this.keyManager.exportKey({ keyUri }); // Add the verification method to the key set. privateKeys.push(Object.assign({}, privateKey)); } portableDid.privateKeys = privateKeys; } return portableDid; }); } /** * Return a {@link Signer} that can be used to sign messages, credentials, or arbitrary data. * * If given, the `methodId` parameter is used to select a key from the verification methods * present in the DID Document. * * If `methodID` is not given, the first verification method intended for signing claims is used. * * @param params - The parameters for the `getSigner` operation. * @param params.methodId - ID of the verification method key that will be used for sign and * verify operations. Optional. * @returns An instantiated {@link Signer} that can be used to sign and verify data. */ getSigner(params) { return __awaiter(this, void 0, void 0, function* () { var _a; // Attempt to find a verification method that matches the given method ID, or if not given, // find the first verification method intended for signing claims. const verificationMethod = (_a = this.document.verificationMethod) === null || _a === void 0 ? void 0 : _a.find(vm => { var _a, _b; return extractDidFragment(vm.id) === ((_a = extractDidFragment(params === null || params === void 0 ? void 0 : params.methodId)) !== null && _a !== void 0 ? _a : extractDidFragment((_b = this.document.assertionMethod) === null || _b === void 0 ? void 0 : _b[0])); }); if (!(verificationMethod && verificationMethod.publicKeyJwk)) { throw new DidError(DidErrorCode.InternalError, 'A verification method intended for signing could not be determined from the DID Document'); } // Compute the expected key URI of the signing key. const keyUri = yield this.keyManager.getKeyUri({ key: verificationMethod.publicKeyJwk }); // Get the public key to be used for verify operations, which also verifies that the key is // present in the key manager's store. const publicKey = yield this.keyManager.getPublicKey({ keyUri }); // Bind the DID's key manager to the signer. const keyManager = this.keyManager; // Determine the signing algorithm. const algorithm = CryptoUtils.getJoseSignatureAlgorithmFromPublicKey(publicKey); return { algorithm: algorithm, keyId: verificationMethod.id, sign(_a) { return __awaiter(this, arguments, void 0, function* ({ data }) { const signature = yield keyManager.sign({ data, keyUri: keyUri }); // `keyUri` is guaranteed to be defined at this point. return signature; }); }, verify(_a) { return __awaiter(this, arguments, void 0, function* ({ data, signature }) { const isValid = yield keyManager.verify({ data, key: publicKey, signature }); // `publicKey` is guaranteed to be defined at this point. return isValid; }); } }; }); } /** * Instantiates a {@link BearerDid} object from a given {@link PortableDid}. * * This method allows for the creation of a `BearerDid` object using a previously created DID's * key material, DID document, and metadata. * * @example * ```ts * // Export an existing BearerDid to PortableDid format. * const portableDid = await did.export(); * // Reconstruct a BearerDid object from the PortableDid. * const did = await BearerDid.import({ portableDid }); * ``` * * @param params - The parameters for the import operation. * @param params.portableDid - The PortableDid object to import. * @param params.keyManager - Optionally specify an external Key Management System (KMS) used to * generate keys and sign data. If not given, a new * {@link LocalKeyManager} instance will be created and * used. * @returns A Promise resolving to a `BearerDid` object representing the DID formed from the * provided PortableDid. * @throws An error if the PortableDid document does not contain any verification methods or the * keys for any verification method are missing in the key manager. */ static import(_a) { return __awaiter(this, arguments, void 0, function* ({ portableDid, keyManager = new LocalKeyManager() }) { var _b; // Get all verification methods from the given DID document, including embedded methods. const verificationMethods = getVerificationMethods({ didDocument: portableDid.document }); // Validate that the DID document contains at least one verification method. if (verificationMethods.length === 0) { throw new DidError(DidErrorCode.InvalidDidDocument, `At least one verification method is required but 0 were given`); } // If given, import the private key material into the key manager. for (let key of (_b = portableDid.privateKeys) !== null && _b !== void 0 ? _b : []) { // confirm th key does not already exist before importing it to avoid failures from the key manager const keyUri = yield keyManager.getKeyUri({ key }); const keyExists = yield keyManager.getPublicKey({ keyUri }).then(() => true).catch(() => false); if (!keyExists) { yield keyManager.importKey({ key }); } } // Validate that the key material for every verification method in the DID document is present // in the key manager. for (let vm of verificationMethods) { if (!vm.publicKeyJwk) { throw new Error(`Verification method '${vm.id}' does not contain a public key in JWK format`); } // Compute the key URI of the verification method's public key. const keyUri = yield keyManager.getKeyUri({ key: vm.publicKeyJwk }); // Verify that the key is present in the key manager. If not, an error is thrown. yield keyManager.getPublicKey({ keyUri }); } // Use the given PortableDid to construct the BearerDid object. const did = new BearerDid({ uri: portableDid.uri, document: portableDid.document, metadata: portableDid.metadata, keyManager }); return did; }); } } //# sourceMappingURL=bearer-did.js.map