npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@interop/did-method-key

v7.3.2

Published

A did:key method resolver.

Readme

did:key method driver (@interop/did-method-key)

CI NPM Version

A DID (Decentralized Identifier) method driver for the did-io library and for standalone use

Table of Contents

Background

See also (related specs):

A did:key method driver for the @interop/did-io client library and for standalone use.

The did:key method is used to express public keys in a way that doesn't require a DID Registry of any kind. Its general format is:

did:key:<multibase encoded, multicodec identified, public key>

So, for example, the following DID would be derived from a multibase encoded ed25519 public key:

did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH

That DID would correspond to the following DID Document:

Example DID Document

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
  "verificationMethod": [
    {
      "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
      "type": "Multikey",
      "controller": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
      "publicKeyMultibase": "z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
    }
  ],
  "authentication": [
    "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
  ],
  "assertionMethod": [
    "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
  ],
  "capabilityDelegation": [
    "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
  ],
  "capabilityInvocation": [
    "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
  ]
}

Security

By default this driver represents verification keys as W3C Multikey verification methods, and does not derive a separate keyAgreement (X25519) key. Reusing a single key for both signing (Ed25519) and key agreement (X25519) is a weaker security posture, so derivation is off by default.

If you need to encrypt to plain Ed25519 did:key identities (for example, JWE/DIDComm/EDV recipients), you can opt in per registration by passing enableEncryptionKeyDerivation: true to use(). When enabled, resolving an Ed25519 did:key additionally derives a Curve25519 keyAgreement public key (suitable for Diffie-Hellman key exchange) from the source Ed25519 key, matching the did:key spec's Ed25519 expansion. Note that this derived key is optional -- there's at least one proof that deriving it is safe to do.

Install

Requires Node.js 24+.

To install from npm:

npm install --save @interop/did-method-key

To install locally (for development), this project uses pnpm:

git clone https://github.com/interop-alliance/did-method-key.git
cd did-method-key
pnpm install

Usage

use()

This method registers a key type that the driver is allowed to handle, for both resolution (get()) and generation (generate()).

The preferred form passes a keyPairClass -- a KeyPair suite class. The driver reads the multibase-multikey header, deserializer, and key generator off the class, so you never have to look up or hard-code the literal multibase prefix:

import { driver } from '@interop/did-method-key'
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'

const didKeyDriver = driver()

didKeyDriver.use({ keyPairClass: Ed25519VerificationKey })

For a suite that does not expose the keyPairClass contract (no static multibaseHeader/from/generate), use the lower-level form: register the multibase-multikey header and a fromMultibase deserializer directly. Key types registered this way support resolution but not generate().

import * as EcdsaMultikey from '@digitalbazaar/ecdsa-multikey'
import { driver } from '@interop/did-method-key'

const didKeyDriverMultikey = driver()

didKeyDriverMultikey.use({
  multibaseMultikeyHeader: 'zDna',
  fromMultibase: EcdsaMultikey.from
})

Deriving a keyAgreement key (opt-in)

By default, resolving an Ed25519 did:key does not produce a keyAgreement (X25519) key. To have the driver derive one from the Ed25519 verification key and add it to the DID Document, pass enableEncryptionKeyDerivation: true when registering the Ed25519 suite:

import { driver } from '@interop/did-method-key'
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'

const didKeyDriver = driver()

didKeyDriver.use({
  keyPairClass: Ed25519VerificationKey,
  enableEncryptionKeyDerivation: true
})

const did = 'did:key:z6MkwLz9d2sa3FJjni9A7rXmicf9NN3e5xgJPUmdqaFMTgoE'
const didDocument = await didKeyDriver.get({ did })

didDocument.keyAgreement
// => [
//   {
//     id: 'did:key:z6MkwLz9d2sa3FJjni9A7rXmicf9NN3e5xgJPUmdqaFMTgoE#z6LSmgLugoC8vUoK1ouCTGKdqFdpg5jb3H193L6wFJucX14U',
//     type: 'X25519KeyAgreementKey2020',
//     controller: 'did:key:z6MkwLz9d2sa3FJjni9A7rXmicf9NN3e5xgJPUmdqaFMTgoE',
//     publicKeyMultibase: 'z6LSmgLugoC8vUoK1ouCTGKdqFdpg5jb3H193L6wFJucX14U'
//   }
// ]

The flag also works with the lower-level registration form (use({ multibaseMultikeyHeader: 'z6Mk', fromMultibase, enableEncryptionKeyDerivation: true })). It is detected by the Ed25519 z6Mk multibase-multikey header, so it has no effect when set on a non-Ed25519 suite. See Security for the rationale behind keeping derivation off by default.

createFromMultibase()

This utility function adapts a verification suite that exposes a fromFingerprint() static method (rather than a fromMultibase() method) so that it works with DidKeyDriver.

import { driver, createFromMultibase } from '@interop/did-method-key'
import { SomeVerificationKey } from 'some-verification-suite'

const didKeyDriver = driver()

didKeyDriver.use({
  multibaseMultikeyHeader: header,
  fromMultibase: createFromMultibase(SomeVerificationKey)
})

generate()

The simplest way to mint a brand-new did:key DID Document: register a suite via use({ keyPairClass }), then call generate(). The driver generates a fresh key pair using the registered suite and returns the DID Document along with the corresponding key pairs (for storage in a KMS).

import { driver } from '@interop/did-method-key'
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'

const didKeyDriver = driver()
didKeyDriver.use({ keyPairClass: Ed25519VerificationKey })

const { didDocument, keyPairs, methodFor } = await didKeyDriver.generate()

// serialize the public DID Document, e.g. for storage on disk
console.log(JSON.stringify(didDocument, null, 2))

When exactly one suite is registered, generate() uses it automatically. If more than one is registered, pass keyType (a KeyPair class or its multibase header) to disambiguate:

const { didDocument } = await didKeyDriver.generate({
  keyType: Ed25519VerificationKey
})

To deterministically derive the key pair from a secret-key seed (rather than generating a random one), pass a seed (a Uint8Array). The same seed always produces the same DID Document:

const { didDocument } = await didKeyDriver.generate({ seed })

The seed is passed through to the registered suite's generate(), so its required length and format are determined by that suite (for ed25519, a 32-byte Uint8Array).

Note that generate() requires a suite registered via use({ keyPairClass }); the lower-level use({ multibaseMultikeyHeader, fromMultibase }) form has no key generator and supports resolution only.

fromKeyPair()

To get the did:key method DID Document that corresponds to an existing verification keypair (for example, one you generated or loaded yourself).

import { driver } from '@interop/did-method-key'
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'

const didKeyDriver = driver()

didKeyDriver.use({ keyPairClass: Ed25519VerificationKey })

const publicKeyMultibase = 'z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH'
const verificationKeyPair = await Ed25519VerificationKey.from({
  publicKeyMultibase
})
// or perhaps:
// const verificationKeyPair = await Ed25519VerificationKey.generate();

const { didDocument, keyPairs, methodFor } = await didKeyDriver.fromKeyPair({
  verificationKeyPair
})

// print the DID Document above
console.log(JSON.stringify(didDocument, null, 2))

// keyPairs will be set like so =>
Map(1) {
  'did:key:z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T#z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T' => Ed25519VerificationKey {
    id: 'did:key:z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T#z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T',
    controller: 'did:key:z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T',
    type: 'Ed25519VerificationKey2020',
    publicKeyMultibase: 'z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T'
  }
}

methodFor is a convenience function that returns a key pair instance that contains publicKeyMultibase for a given purpose. For example, a verification key (containing signer() and verifier() functions) is frequently useful for jsonld-signatures operations. After generating a new did:key DID, you can do:

// For signing Verifiable Credentials
const assertionKeyPair = methodFor({ purpose: 'assertionMethod' })
// For Authorization Capabilities (zCaps)
const invocationKeyPair = methodFor({ purpose: 'capabilityInvocation' })

Note that methodFor returns a key pair that contains a publicKeyMultibase. This makes it useful for verifying and encrypting operations.

Because the default Multikey representation does not derive a keyAgreement key, methodFor({ purpose: 'keyAgreement' }) will throw for an ed25519 DID unless you explicitly supplied a keyAgreementKeyPair to fromKeyPair(), or registered the Ed25519 suite with enableEncryptionKeyDerivation: true.

publicKeyToDidDoc()

If you already have a public key object (as an LDKeyPair instance, or a plain key description object), you can turn it into a DID Document:

const { didDocument } = await didKeyDriver.publicKeyToDidDoc({
  publicKeyDescription
})

get()

Getting a full DID Document from a did:key DID

To get a DID Document for an existing did:key DID:

const did = 'did:key:z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T'
const didDocument = await didKeyDriver.get({ did })

(Results in the example DID Doc above).

Getting the DID Document from key id

You can also use a .get() to retrieve an individual key, if you know its id already (this is useful for constructing documentLoaders for JSON-LD Signature libs, and the resulting key does include the appropriate @context).

const verificationKeyId =
  'did:key:z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T#z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T'

const keyData = await didKeyDriver.get({ url: verificationKeyId })

// key node ->
console.log(JSON.stringify(keyData, null, 2))

publicMethodFor()

Often, you have just a did:key DID, and you need to get a key for a particular purpose from it, such as an assertionMethod key to verify a VC signature.

For that purpose, you can use a combination of get() and publicMethodFor:

// Start with the DID
const didDocument = await didKeyDriver.get({ did })
// This lets you use `publicMethodFor()` to get a key for a specific purpose
const assertionMethod = didKeyDriver.publicMethodFor({
  didDocument,
  purpose: 'assertionMethod'
})

// If you have a known key type, you can create a key instance which gives you
// access to a `verify()` function.
const assertionMethodPublicKey =
  await Ed25519VerificationKey.from(assertionMethod)
const { verify } = assertionMethodPublicKey.verifier()

publicMethodFor will throw an error if no key is found for a given purpose.

Contribute

PRs accepted.

If editing the Readme, please conform to the standard-readme specification.

License

New BSD License (3-clause) © Interop Alliance and Digital Bazaar