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

@owlmeans/did

v0.1.1

Published

A comprehensive Decentralized Identity (DID) and cryptographic wallet management library for OwlMeans Common applications. This package provides secure key generation, hierarchical deterministic wallets, and decentralized identity management with mnemonic

Readme

@owlmeans/did

A comprehensive Decentralized Identity (DID) and cryptographic wallet management library for OwlMeans Common applications. This package provides secure key generation, hierarchical deterministic wallets, and decentralized identity management with mnemonic seed support.

Overview

The @owlmeans/did package is the core decentralized identity library in the OwlMeans Common ecosystem, providing:

  • DID Wallet Management: Hierarchical deterministic wallet creation and management
  • Mnemonic Key Generation: BIP39-compatible mnemonic phrase generation and recovery
  • Cryptographic Key Derivation: Secure key derivation with configurable depth
  • Identity Management: Profile and entity-based identity organization
  • Secure Storage: Resource-based secure storage for keys and metadata
  • Plugin Architecture: Extensible cryptographic algorithm support
  • Cross-Platform Support: Works across server, web, and mobile environments

Installation

npm install @owlmeans/did

Core Concepts

DID Wallet

A DIDWallet is a hierarchical deterministic wallet that manages cryptographic keys and associated metadata. It supports key derivation, profile management, and secure storage.

DID Key Model

A DIDKeyModel extends the basic key pair model with DID-specific functionality, including path-based key derivation and parent-child key relationships.

Key Metadata

Key metadata associates human-readable information with cryptographic keys, including names, entity IDs, and profile information.

Mnemonic Seeds

Mnemonic phrases provide a human-readable way to backup and restore wallets, following BIP39 standards.

API Reference

Types

DIDWallet

Core wallet interface for managing decentralized identities.

interface DIDWallet {
  store: DIDStore                                                    // Storage backend
  generate: (opts?: MnemonicOptions) => Promise<void>               // Generate new wallet
  mnemonic: (crash?: boolean) => Promise<string | false>            // Get mnemonic phrase
  master: () => Promise<DIDKeyModel>                                // Get master key
  add: (key: DIDKeyModel, meta: KeyMeta) => Promise<void>           // Add key with metadata
  meta: (key: string | DIDKeyModel) => Promise<KeyMeta>             // Get key metadata
  update: (key: DIDKeyModel, meta: KeyMeta) => Promise<[DIDKeyModel, KeyMeta]>  // Update key metadata
  get: (did: string) => Promise<DIDKeyModel | null>                 // Get key by DID
  find: (meta: Partial<KeyMeta>) => Promise<DIDKeyModel[]>          // Find keys by metadata
  provide: (meta: Partial<KeyMeta>) => Promise<DIDKeyModel[]>       // Provide keys matching criteria
  remove: (did: string | KeyMeta | DIDKeyModel) => Promise<DIDKeyModel>  // Remove key
  all: () => Promise<DIDKeyModel[]>                                 // Get all keys
  allMeta: () => Promise<KeyMeta[]>                                 // Get all metadata
}

DIDKeyModel

Extended key model with DID capabilities.

interface DIDKeyModel extends KeyPairModel {
  keyPair?: DIDKeyPair                        // Underlying key pair
  derive: (path: string) => DIDKeyModel       // Derive child keys
}

KeyMeta

Metadata associated with keys.

interface KeyMeta extends Partial<Profile> {
  id: string          // Unique identifier
  name: string        // Human-readable name
  entityId?: string   // Associated entity ID
}

DIDStore

Storage interface for wallet data.

interface DIDStore {
  master: MasterResource      // Master key storage
  keys: KeyPairResource       // Key pair storage
  meta: KeyMetaResource       // Metadata storage
}

Factory Functions

makeWallet(store: DIDStore, opts?: MakeDIDWalletOptions): Promise<DIDWallet>

Creates a new DID wallet instance.

Parameters:

  • store: Storage backend for wallet data
  • opts: Optional wallet creation options

Options:

interface MakeDIDWalletOptions {
  force?: boolean           // Force creation even if master exists
  allowEmpty?: boolean      // Allow empty wallet creation
  mnemonic?: MnemonicOptions  // Mnemonic generation options
  type?: string            // Key type (default: 'owlmk')
  allowCustomType?: boolean // Allow custom key types
}

makeDidKeyModel(input?: KeyPair | string): DIDKeyModel

Creates a DID key model from key pair or type string.

Wallet Operations

generate(opts?: MnemonicOptions): Promise<void>

Generates a new wallet with mnemonic seed.

// Generate with default options
await wallet.generate()

// Generate with custom entropy
await wallet.generate({ size: 256 })

mnemonic(crash?: boolean): Promise<string | false>

Retrieves the wallet's mnemonic phrase.

// Get mnemonic (safe, returns false if not available)
const mnemonic = await wallet.mnemonic()

// Get mnemonic (throws error if not available)
const mnemonic = await wallet.mnemonic(true)

master(): Promise<DIDKeyModel>

Gets the master key for the wallet.

const masterKey = await wallet.master()
console.log('Master DID:', masterKey.did)

Key Management

add(key: DIDKeyModel, meta: KeyMeta): Promise<void>

Adds a key with metadata to the wallet.

const childKey = masterKey.derive('profile/user')
await wallet.add(childKey, {
  id: 'user-profile',
  name: 'User Profile Key',
  entityId: 'user-123'
})

get(did: string): Promise<DIDKeyModel | null>

Retrieves a key by its DID.

const key = await wallet.get('did:owlmeans:key:...')
if (key) {
  console.log('Found key:', key.did)
}

find(meta: Partial<KeyMeta>): Promise<DIDKeyModel[]>

Finds keys matching metadata criteria.

// Find all profile keys
const profileKeys = await wallet.find({ entityId: 'user-123' })

// Find keys by name pattern
const namedKeys = await wallet.find({ name: 'Service Key' })

Key Derivation

derive(path: string): DIDKeyModel

Derives child keys from parent keys using hierarchical paths.

const masterKey = await wallet.master()

// Derive profile key
const profileKey = masterKey.derive('profile/user')

// Derive service key
const serviceKey = masterKey.derive('service/api')

// Derive entity-specific key
const entityKey = masterKey.derive('entity/org/dept')

Constants

const KEY_OWL = 'owlmk'              // Default key type
const MAX_DEPTH = 6                 // Maximum derivation depth
const PROFILE_PREFIX = 'profile'    // Profile key prefix
const ENTITY_PREFIX = 'entity'      // Entity key prefix  
const SERVICE_PREFIX = 'service'    // Service key prefix
const MASTER = '_master_key'        // Master key identifier

Usage Examples

Basic Wallet Creation

import { makeWallet } from '@owlmeans/did'
import { createDIDStore } from './storage'

// Create storage backend
const store = createDIDStore()

// Create new wallet
const wallet = await makeWallet(store, {
  allowEmpty: true
})

// Generate master key
await wallet.generate()

// Get mnemonic for backup
const mnemonic = await wallet.mnemonic()
console.log('Backup phrase:', mnemonic)

Key Derivation and Management

// Get master key
const master = await wallet.master()

// Derive keys for different purposes
const profileKey = master.derive('profile/personal')
const workKey = master.derive('profile/work')
const apiKey = master.derive('service/api/v1')

// Add keys with metadata
await wallet.add(profileKey, {
  id: 'personal-profile',
  name: 'Personal Profile',
  entityId: 'user-123'
})

await wallet.add(workKey, {
  id: 'work-profile', 
  name: 'Work Profile',
  entityId: 'org-456'
})

await wallet.add(apiKey, {
  id: 'api-service',
  name: 'API Service Key',
  entityId: 'service-789'
})

Identity Management

// Create identity for a user
const createUserIdentity = async (userId: string, name: string) => {
  const master = await wallet.master()
  const userKey = master.derive(`profile/${userId}`)
  
  await wallet.add(userKey, {
    id: `user-${userId}`,
    name: `${name}'s Identity`,
    entityId: userId,
    scopes: ['user:profile', 'user:data']
  })
  
  return userKey
}

// Create identity for a service
const createServiceIdentity = async (serviceName: string) => {
  const master = await wallet.master()
  const serviceKey = master.derive(`service/${serviceName}`)
  
  await wallet.add(serviceKey, {
    id: `service-${serviceName}`,
    name: `${serviceName} Service`,
    entityId: serviceName,
    scopes: ['service:*']
  })
  
  return serviceKey
}

Signature and Verification

// Sign data with a specific key
const signWithProfile = async (data: string, profileId: string) => {
  const keys = await wallet.find({ id: profileId })
  if (keys.length === 0) {
    throw new Error('Profile key not found')
  }
  
  const key = keys[0]
  const signature = await key.sign(Buffer.from(data, 'utf8'))
  
  return {
    data,
    signature: signature.toString('base64'),
    did: key.did,
    publicKey: key.publicKey?.toString('base64')
  }
}

// Verify signature
const verifySignature = async (signedData: any) => {
  const key = await wallet.get(signedData.did)
  if (!key) {
    throw new Error('Key not found')
  }
  
  const signature = Buffer.from(signedData.signature, 'base64')
  const data = Buffer.from(signedData.data, 'utf8')
  
  return await key.verify(data, signature)
}

Multi-Entity Wallet

// Organization with multiple departments
const setupOrganizationWallet = async () => {
  const master = await wallet.master()
  
  // Organization master key
  const orgKey = master.derive('entity/acme-corp')
  await wallet.add(orgKey, {
    id: 'acme-corp',
    name: 'ACME Corporation',
    entityId: 'org-acme'
  })
  
  // Department keys
  const departments = ['hr', 'engineering', 'sales']
  
  for (const dept of departments) {
    const deptKey = orgKey.derive(`dept/${dept}`)
    await wallet.add(deptKey, {
      id: `acme-${dept}`,
      name: `ACME ${dept.toUpperCase()} Department`,
      entityId: `org-acme-${dept}`
    })
  }
  
  // Employee keys within departments
  const engineeringKey = await wallet.get('acme-engineering')
  const employeeKey = engineeringKey!.derive('employee/john-doe')
  
  await wallet.add(employeeKey, {
    id: 'john-doe-work',
    name: 'John Doe Work Identity',
    entityId: 'user-john-doe',
    groups: ['engineering', 'senior-dev']
  })
}

Wallet Recovery

// Recover wallet from mnemonic
const recoverWallet = async (mnemonic: string, store: DIDStore) => {
  // Create wallet allowing empty state
  const wallet = await makeWallet(store, { allowEmpty: true })
  
  // Import from mnemonic
  await wallet.generate({ mnemonic })
  
  // Verify master key was restored
  const master = await wallet.master()
  console.log('Recovered master DID:', master.did)
  
  // List all recovered keys
  const allKeys = await wallet.all()
  console.log(`Recovered ${allKeys.length} keys`)
  
  return wallet
}

Key Export and Import

// Export key for external use
const exportKey = async (keyId: string) => {
  const keys = await wallet.find({ id: keyId })
  if (keys.length === 0) {
    throw new Error('Key not found')
  }
  
  const key = keys[0]
  const meta = await wallet.meta(key)
  
  return {
    did: key.did,
    publicKey: key.publicKey?.toString('base64'),
    privateKey: key.privateKey?.toString('base64'), // Only if needed
    meta: {
      id: meta.id,
      name: meta.name,
      entityId: meta.entityId
    }
  }
}

// Import external key
const importKey = async (keyData: any) => {
  const keyModel = makeDidKeyModel({
    type: 'ed25519',
    publicKey: Buffer.from(keyData.publicKey, 'base64'),
    privateKey: keyData.privateKey ? Buffer.from(keyData.privateKey, 'base64') : undefined
  })
  
  await wallet.add(keyModel, keyData.meta)
}

Advanced Features

Custom Key Types

// Register custom key type
const customKeyType = 'custom-ed25519'

const wallet = await makeWallet(store, {
  type: customKeyType,
  allowCustomType: true
})

Hierarchical Path Management

// Standardized path structure
const createStandardPath = (type: 'profile' | 'entity' | 'service', identifier: string, subpath?: string) => {
  const basePath = `${type}/${identifier}`
  return subpath ? `${basePath}/${subpath}` : basePath
}

// Usage
const userProfilePath = createStandardPath('profile', 'user123')
const serviceApiPath = createStandardPath('service', 'api', 'v1')
const entityDeptPath = createStandardPath('entity', 'corp', 'dept/engineering')

Batch Operations

// Batch key creation
const createBatchKeys = async (specifications: Array<{path: string, meta: Omit<KeyMeta, 'id'>}>) => {
  const master = await wallet.master()
  const keys: DIDKeyModel[] = []
  
  for (const spec of specifications) {
    const key = master.derive(spec.path)
    await wallet.add(key, {
      ...spec.meta,
      id: `${spec.meta.name.toLowerCase().replace(/\s+/g, '-')}`
    })
    keys.push(key)
  }
  
  return keys
}

Error Handling

The package provides specialized error types:

import { DIDWalletError, DIDKeyError, DIDInitializationError } from '@owlmeans/did'

try {
  const wallet = await makeWallet(store)
  await wallet.generate()
} catch (error) {
  if (error instanceof DIDInitializationError) {
    console.error('Wallet initialization failed:', error.message)
  } else if (error instanceof DIDKeyError) {
    console.error('Key operation failed:', error.message)
  } else if (error instanceof DIDWalletError) {
    console.error('Wallet operation failed:', error.message)
  }
}

Integration with OwlMeans Ecosystem

The @owlmeans/did package integrates with:

  • @owlmeans/basic-keys: Core cryptographic operations and key management
  • @owlmeans/auth: Authentication and authorization with DID-based identities
  • @owlmeans/resource: Storage backend for wallet data persistence
  • @owlmeans/client-did: Client-side DID wallet implementations
  • @owlmeans/server-auth: Server-side DID authentication
  • @owlmeans/context: Service registration and dependency injection

Security Considerations

  • Store mnemonic phrases securely and never expose them in logs
  • Use appropriate key derivation paths to prevent key correlation
  • Implement proper access controls for wallet operations
  • Regular backup of wallet data and mnemonic phrases
  • Use secure random number generation for key creation
  • Validate all imported keys and metadata

Best Practices

Key Management

  • Use descriptive names and metadata for all keys
  • Implement consistent path naming conventions
  • Regular audit of stored keys and remove unused ones
  • Use different keys for different purposes (signing, encryption, etc.)

Security

  • Never store private keys in plain text
  • Use hardware security modules where possible
  • Implement proper key rotation policies
  • Monitor for unauthorized key access

Performance

  • Cache frequently used keys in memory
  • Use batch operations for multiple key operations
  • Implement proper indexing for key searches
  • Consider key compression for storage efficiency

Fixes #32.