UNPKG

@digitalcredentials/did-method-key

Version:
121 lines (109 loc) 3.7 kB
/*! * Copyright (c) 2023 Digital Bazaar, Inc. All rights reserved. */ import { X25519KeyAgreementKey2020 } from '@digitalcredentials/x25519-key-agreement-key-2020'; const ED25519_KEY_2020_CONTEXT_URL = 'https://w3id.org/security/suites/ed25519-2020/v1'; const MULTIKEY_CONTEXT_V1_URL = 'https://w3id.org/security/multikey/v1'; const contextsBySuite = new Map([ ['Ed25519VerificationKey2020', ED25519_KEY_2020_CONTEXT_URL], ['Multikey', MULTIKEY_CONTEXT_V1_URL], [X25519KeyAgreementKey2020.suite, X25519KeyAgreementKey2020.SUITE_CONTEXT] ]); /** * Returns the public key object for a given key id fragment. * * @param {object} options - Options hashmap. * @param {object} options.didDocument - The DID Document to use when generating * the id. * @param {string} options.keyIdFragment - The key identifier fragment. * * @returns {object} Returns the public key node, with `@context`. */ export function getKey({didDocument, keyIdFragment}) { // Determine if the key id fragment belongs to the "main" public key, // or the keyAgreement key const keyId = didDocument.id + '#' + keyIdFragment; let publicKey; if(didDocument.verificationMethod?.[0].id === keyId) { // Return the public key node for the main public key publicKey = didDocument.verificationMethod[0]; } else { // Return the public key node for the X25519 key-agreement key publicKey = didDocument.keyAgreement[0]; } return { '@context': contextsBySuite.get(publicKey.type), ...publicKey }; } export function getDid({keyPair}) { return keyPair.fingerprint ? `did:key:${keyPair.fingerprint()}` : `did:key:${keyPair.publicKeyMultibase}`; } export function setKeyPairId({keyPair, did}) { keyPair.id = keyPair.fingerprint ? `${did}#${keyPair.fingerprint()}` : `${did}#${keyPair.publicKeyMultibase}`; } export function getKeyAgreementKeyPair({contexts, verificationPublicKey}) { // The KAK pair will use the source key's controller, but may generate // its own .id let keyAgreementKeyPair; switch(verificationPublicKey.type) { case 'Ed25519VerificationKey2020': { keyAgreementKeyPair = X25519KeyAgreementKey2020 .fromEd25519VerificationKey2020({keyPair: verificationPublicKey}); contexts.push(X25519KeyAgreementKey2020.SUITE_CONTEXT); break; } case 'Multikey': { // FIXME: Add keyAgreementKeyPair interface for Multikey. break; } default: { throw new Error( `Cannot derive key agreement key from verification key type "${verificationPublicKey.type}".`); } } return {keyAgreementKeyPair}; } export function getMultibaseMultikeyHeader({value}) { if(!value) { throw new TypeError('"publicKeyMultibase" must be a string.'); } return value.slice(0, 4); } export function addKeyAgreementKeyContext({contexts, keyAgreementKeyPair}) { const {type} = keyAgreementKeyPair; switch(type) { case 'X25519KeyAgreementKey2020': { if(!contexts.includes(X25519KeyAgreementKey2020.SUITE_CONTEXT)) { contexts.push(X25519KeyAgreementKey2020.SUITE_CONTEXT); } break; } default: { throw new Error(`Unsupported key agreement key type, "${type}".`); } } } export async function getKeyPair({ fromMultibase, publicKeyMultibase, publicKeyDescription } = {}) { let keyPair; if(fromMultibase && publicKeyMultibase) { keyPair = await fromMultibase({publicKeyMultibase}); } else { keyPair = publicKeyDescription; } const {type} = keyPair; let keyAgreementKeyPair; if(type === 'X25519KeyAgreementKey2020') { keyAgreementKeyPair = keyPair; keyPair = null; } return {keyPair, keyAgreementKeyPair}; }