@owlmeans/did 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
3
+ Copyright (c) 2026 OwlMeans Common — Fullstack typescript framework
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,552 +1,58 @@
1
1
  # @owlmeans/did
2
2
 
3
- 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.
3
+ Hierarchical deterministic (HD) wallet and DID document management for OwlMeans identity.
4
4
 
5
5
  ## Overview
6
6
 
7
- The `@owlmeans/did` package is the core decentralized identity library in the OwlMeans Common ecosystem, providing:
8
-
9
- - **DID Wallet Management**: Hierarchical deterministic wallet creation and management
10
- - **Mnemonic Key Generation**: BIP39-compatible mnemonic phrase generation and recovery
11
- - **Cryptographic Key Derivation**: Secure key derivation with configurable depth
12
- - **Identity Management**: Profile and entity-based identity organization
13
- - **Secure Storage**: Resource-based secure storage for keys and metadata
14
- - **Plugin Architecture**: Extensible cryptographic algorithm support
15
- - **Cross-Platform Support**: Works across server, web, and mobile environments
7
+ - `makeWallet()` creates a DID wallet from a persistent store, generating a master key on first use
8
+ - Wallets derive child keys by path (entity, profile, service) using BIP39 mnemonics
9
+ - The `owlmk` key type is a custom HD key scheme on top of ED25519
10
+ - Used by `@owlmeans/client-did` and `@owlmeans/server-auth` for identity management
16
11
 
17
12
  ## Installation
18
13
 
19
14
  ```bash
20
- npm install @owlmeans/did
15
+ bun add @owlmeans/did
21
16
  ```
22
17
 
23
- ## Core Concepts
24
-
25
- ### DID Wallet
26
-
27
- A `DIDWallet` is a hierarchical deterministic wallet that manages cryptographic keys and associated metadata. It supports key derivation, profile management, and secure storage.
28
-
29
- ### DID Key Model
30
-
31
- A `DIDKeyModel` extends the basic key pair model with DID-specific functionality, including path-based key derivation and parent-child key relationships.
32
-
33
- ### Key Metadata
34
-
35
- Key metadata associates human-readable information with cryptographic keys, including names, entity IDs, and profile information.
36
-
37
- ### Mnemonic Seeds
38
-
39
- Mnemonic phrases provide a human-readable way to backup and restore wallets, following BIP39 standards.
18
+ ## Usage
40
19
 
41
- ## API Reference
42
-
43
- ### Types
44
-
45
- #### `DIDWallet`
46
- Core wallet interface for managing decentralized identities.
47
-
48
- ```typescript
49
- interface DIDWallet {
50
- store: DIDStore // Storage backend
51
- generate: (opts?: MnemonicOptions) => Promise<void> // Generate new wallet
52
- mnemonic: (crash?: boolean) => Promise<string | false> // Get mnemonic phrase
53
- master: () => Promise<DIDKeyModel> // Get master key
54
- add: (key: DIDKeyModel, meta: KeyMeta) => Promise<void> // Add key with metadata
55
- meta: (key: string | DIDKeyModel) => Promise<KeyMeta> // Get key metadata
56
- update: (key: DIDKeyModel, meta: KeyMeta) => Promise<[DIDKeyModel, KeyMeta]> // Update key metadata
57
- get: (did: string) => Promise<DIDKeyModel | null> // Get key by DID
58
- find: (meta: Partial<KeyMeta>) => Promise<DIDKeyModel[]> // Find keys by metadata
59
- provide: (meta: Partial<KeyMeta>) => Promise<DIDKeyModel[]> // Provide keys matching criteria
60
- remove: (did: string | KeyMeta | DIDKeyModel) => Promise<DIDKeyModel> // Remove key
61
- all: () => Promise<DIDKeyModel[]> // Get all keys
62
- allMeta: () => Promise<KeyMeta[]> // Get all metadata
63
- }
64
- ```
65
-
66
- #### `DIDKeyModel`
67
- Extended key model with DID capabilities.
68
-
69
- ```typescript
70
- interface DIDKeyModel extends KeyPairModel {
71
- keyPair?: DIDKeyPair // Underlying key pair
72
- derive: (path: string) => DIDKeyModel // Derive child keys
73
- }
74
- ```
75
-
76
- #### `KeyMeta`
77
- Metadata associated with keys.
78
-
79
- ```typescript
80
- interface KeyMeta extends Partial<Profile> {
81
- id: string // Unique identifier
82
- name: string // Human-readable name
83
- entityId?: string // Associated entity ID
84
- }
85
- ```
86
-
87
- #### `DIDStore`
88
- Storage interface for wallet data.
89
-
90
- ```typescript
91
- interface DIDStore {
92
- master: MasterResource // Master key storage
93
- keys: KeyPairResource // Key pair storage
94
- meta: KeyMetaResource // Metadata storage
95
- }
96
- ```
97
-
98
- ### Factory Functions
99
-
100
- #### `makeWallet(store: DIDStore, opts?: MakeDIDWalletOptions): Promise<DIDWallet>`
101
- Creates a new DID wallet instance.
102
-
103
- **Parameters:**
104
- - `store`: Storage backend for wallet data
105
- - `opts`: Optional wallet creation options
106
-
107
- **Options:**
108
- ```typescript
109
- interface MakeDIDWalletOptions {
110
- force?: boolean // Force creation even if master exists
111
- allowEmpty?: boolean // Allow empty wallet creation
112
- mnemonic?: MnemonicOptions // Mnemonic generation options
113
- type?: string // Key type (default: 'owlmk')
114
- allowCustomType?: boolean // Allow custom key types
115
- }
116
- ```
117
-
118
- #### `makeDidKeyModel(input?: KeyPair | string): DIDKeyModel`
119
- Creates a DID key model from key pair or type string.
120
-
121
- ### Wallet Operations
122
-
123
- #### `generate(opts?: MnemonicOptions): Promise<void>`
124
- Generates a new wallet with mnemonic seed.
125
-
126
- ```typescript
127
- // Generate with default options
128
- await wallet.generate()
129
-
130
- // Generate with custom entropy
131
- await wallet.generate({ size: 256 })
132
- ```
133
-
134
- #### `mnemonic(crash?: boolean): Promise<string | false>`
135
- Retrieves the wallet's mnemonic phrase.
136
-
137
- ```typescript
138
- // Get mnemonic (safe, returns false if not available)
139
- const mnemonic = await wallet.mnemonic()
140
-
141
- // Get mnemonic (throws error if not available)
142
- const mnemonic = await wallet.mnemonic(true)
143
- ```
144
-
145
- #### `master(): Promise<DIDKeyModel>`
146
- Gets the master key for the wallet.
147
-
148
- ```typescript
149
- const masterKey = await wallet.master()
150
- console.log('Master DID:', masterKey.did)
151
- ```
152
-
153
- ### Key Management
154
-
155
- #### `add(key: DIDKeyModel, meta: KeyMeta): Promise<void>`
156
- Adds a key with metadata to the wallet.
157
-
158
- ```typescript
159
- const childKey = masterKey.derive('profile/user')
160
- await wallet.add(childKey, {
161
- id: 'user-profile',
162
- name: 'User Profile Key',
163
- entityId: 'user-123'
164
- })
165
- ```
166
-
167
- #### `get(did: string): Promise<DIDKeyModel | null>`
168
- Retrieves a key by its DID.
169
-
170
- ```typescript
171
- const key = await wallet.get('did:owlmeans:key:...')
172
- if (key) {
173
- console.log('Found key:', key.did)
174
- }
175
- ```
176
-
177
- #### `find(meta: Partial<KeyMeta>): Promise<DIDKeyModel[]>`
178
- Finds keys matching metadata criteria.
179
-
180
- ```typescript
181
- // Find all profile keys
182
- const profileKeys = await wallet.find({ entityId: 'user-123' })
183
-
184
- // Find keys by name pattern
185
- const namedKeys = await wallet.find({ name: 'Service Key' })
186
- ```
187
-
188
- ### Key Derivation
189
-
190
- #### `derive(path: string): DIDKeyModel`
191
- Derives child keys from parent keys using hierarchical paths.
192
-
193
- ```typescript
194
- const masterKey = await wallet.master()
195
-
196
- // Derive profile key
197
- const profileKey = masterKey.derive('profile/user')
198
-
199
- // Derive service key
200
- const serviceKey = masterKey.derive('service/api')
201
-
202
- // Derive entity-specific key
203
- const entityKey = masterKey.derive('entity/org/dept')
204
- ```
205
-
206
- ### Constants
207
-
208
- ```typescript
209
- const KEY_OWL = 'owlmk' // Default key type
210
- const MAX_DEPTH = 6 // Maximum derivation depth
211
- const PROFILE_PREFIX = 'profile' // Profile key prefix
212
- const ENTITY_PREFIX = 'entity' // Entity key prefix
213
- const SERVICE_PREFIX = 'service' // Service key prefix
214
- const MASTER = '_master_key' // Master key identifier
215
- ```
216
-
217
- ## Usage Examples
218
-
219
- ### Basic Wallet Creation
20
+ Create or load a wallet from a persistent store:
220
21
 
221
22
  ```typescript
222
23
  import { makeWallet } from '@owlmeans/did'
223
- import { createDIDStore } from './storage'
224
-
225
- // Create storage backend
226
- const store = createDIDStore()
227
-
228
- // Create new wallet
229
- const wallet = await makeWallet(store, {
230
- allowEmpty: true
231
- })
232
-
233
- // Generate master key
234
- await wallet.generate()
235
-
236
- // Get mnemonic for backup
237
- const mnemonic = await wallet.mnemonic()
238
- console.log('Backup phrase:', mnemonic)
239
- ```
240
-
241
- ### Key Derivation and Management
242
-
243
- ```typescript
244
- // Get master key
245
- const master = await wallet.master()
246
-
247
- // Derive keys for different purposes
248
- const profileKey = master.derive('profile/personal')
249
- const workKey = master.derive('profile/work')
250
- const apiKey = master.derive('service/api/v1')
251
-
252
- // Add keys with metadata
253
- await wallet.add(profileKey, {
254
- id: 'personal-profile',
255
- name: 'Personal Profile',
256
- entityId: 'user-123'
257
- })
258
-
259
- await wallet.add(workKey, {
260
- id: 'work-profile',
261
- name: 'Work Profile',
262
- entityId: 'org-456'
263
- })
264
-
265
- await wallet.add(apiKey, {
266
- id: 'api-service',
267
- name: 'API Service Key',
268
- entityId: 'service-789'
269
- })
270
- ```
271
-
272
- ### Identity Management
273
-
274
- ```typescript
275
- // Create identity for a user
276
- const createUserIdentity = async (userId: string, name: string) => {
277
- const master = await wallet.master()
278
- const userKey = master.derive(`profile/${userId}`)
279
-
280
- await wallet.add(userKey, {
281
- id: `user-${userId}`,
282
- name: `${name}'s Identity`,
283
- entityId: userId,
284
- scopes: ['user:profile', 'user:data']
285
- })
286
-
287
- return userKey
288
- }
289
-
290
- // Create identity for a service
291
- const createServiceIdentity = async (serviceName: string) => {
292
- const master = await wallet.master()
293
- const serviceKey = master.derive(`service/${serviceName}`)
294
-
295
- await wallet.add(serviceKey, {
296
- id: `service-${serviceName}`,
297
- name: `${serviceName} Service`,
298
- entityId: serviceName,
299
- scopes: ['service:*']
300
- })
301
-
302
- return serviceKey
303
- }
304
- ```
305
-
306
- ### Signature and Verification
307
-
308
- ```typescript
309
- // Sign data with a specific key
310
- const signWithProfile = async (data: string, profileId: string) => {
311
- const keys = await wallet.find({ id: profileId })
312
- if (keys.length === 0) {
313
- throw new Error('Profile key not found')
314
- }
315
-
316
- const key = keys[0]
317
- const signature = await key.sign(Buffer.from(data, 'utf8'))
318
-
319
- return {
320
- data,
321
- signature: signature.toString('base64'),
322
- did: key.did,
323
- publicKey: key.publicKey?.toString('base64')
324
- }
325
- }
24
+ import type { DIDStore } from '@owlmeans/did'
326
25
 
327
- // Verify signature
328
- const verifySignature = async (signedData: any) => {
329
- const key = await wallet.get(signedData.did)
330
- if (!key) {
331
- throw new Error('Key not found')
332
- }
333
-
334
- const signature = Buffer.from(signedData.signature, 'base64')
335
- const data = Buffer.from(signedData.data, 'utf8')
336
-
337
- return await key.verify(data, signature)
338
- }
339
- ```
340
-
341
- ### Multi-Entity Wallet
342
-
343
- ```typescript
344
- // Organization with multiple departments
345
- const setupOrganizationWallet = async () => {
346
- const master = await wallet.master()
347
-
348
- // Organization master key
349
- const orgKey = master.derive('entity/acme-corp')
350
- await wallet.add(orgKey, {
351
- id: 'acme-corp',
352
- name: 'ACME Corporation',
353
- entityId: 'org-acme'
354
- })
355
-
356
- // Department keys
357
- const departments = ['hr', 'engineering', 'sales']
358
-
359
- for (const dept of departments) {
360
- const deptKey = orgKey.derive(`dept/${dept}`)
361
- await wallet.add(deptKey, {
362
- id: `acme-${dept}`,
363
- name: `ACME ${dept.toUpperCase()} Department`,
364
- entityId: `org-acme-${dept}`
365
- })
366
- }
367
-
368
- // Employee keys within departments
369
- const engineeringKey = await wallet.get('acme-engineering')
370
- const employeeKey = engineeringKey!.derive('employee/john-doe')
371
-
372
- await wallet.add(employeeKey, {
373
- id: 'john-doe-work',
374
- name: 'John Doe Work Identity',
375
- entityId: 'user-john-doe',
376
- groups: ['engineering', 'senior-dev']
377
- })
378
- }
379
- ```
380
-
381
- ### Wallet Recovery
382
-
383
- ```typescript
384
- // Recover wallet from mnemonic
385
- const recoverWallet = async (mnemonic: string, store: DIDStore) => {
386
- // Create wallet allowing empty state
387
- const wallet = await makeWallet(store, { allowEmpty: true })
388
-
389
- // Import from mnemonic
390
- await wallet.generate({ mnemonic })
391
-
392
- // Verify master key was restored
393
- const master = await wallet.master()
394
- console.log('Recovered master DID:', master.did)
395
-
396
- // List all recovered keys
397
- const allKeys = await wallet.all()
398
- console.log(`Recovered ${allKeys.length} keys`)
399
-
400
- return wallet
401
- }
402
- ```
403
-
404
- ### Key Export and Import
405
-
406
- ```typescript
407
- // Export key for external use
408
- const exportKey = async (keyId: string) => {
409
- const keys = await wallet.find({ id: keyId })
410
- if (keys.length === 0) {
411
- throw new Error('Key not found')
412
- }
413
-
414
- const key = keys[0]
415
- const meta = await wallet.meta(key)
416
-
417
- return {
418
- did: key.did,
419
- publicKey: key.publicKey?.toString('base64'),
420
- privateKey: key.privateKey?.toString('base64'), // Only if needed
421
- meta: {
422
- id: meta.id,
423
- name: meta.name,
424
- entityId: meta.entityId
425
- }
426
- }
427
- }
428
-
429
- // Import external key
430
- const importKey = async (keyData: any) => {
431
- const keyModel = makeDidKeyModel({
432
- type: 'ed25519',
433
- publicKey: Buffer.from(keyData.publicKey, 'base64'),
434
- privateKey: keyData.privateKey ? Buffer.from(keyData.privateKey, 'base64') : undefined
435
- })
436
-
437
- await wallet.add(keyModel, keyData.meta)
438
- }
439
- ```
440
-
441
- ## Advanced Features
442
-
443
- ### Custom Key Types
26
+ const wallet = await makeWallet(store)
444
27
 
445
- ```typescript
446
- // Register custom key type
447
- const customKeyType = 'custom-ed25519'
448
-
449
- const wallet = await makeWallet(store, {
450
- type: customKeyType,
451
- allowCustomType: true
452
- })
453
- ```
454
-
455
- ### Hierarchical Path Management
456
-
457
- ```typescript
458
- // Standardized path structure
459
- const createStandardPath = (type: 'profile' | 'entity' | 'service', identifier: string, subpath?: string) => {
460
- const basePath = `${type}/${identifier}`
461
- return subpath ? `${basePath}/${subpath}` : basePath
462
- }
463
-
464
- // Usage
465
- const userProfilePath = createStandardPath('profile', 'user123')
466
- const serviceApiPath = createStandardPath('service', 'api', 'v1')
467
- const entityDeptPath = createStandardPath('entity', 'corp', 'dept/engineering')
468
- ```
469
-
470
- ### Batch Operations
471
-
472
- ```typescript
473
- // Batch key creation
474
- const createBatchKeys = async (specifications: Array<{path: string, meta: Omit<KeyMeta, 'id'>}>) => {
475
- const master = await wallet.master()
476
- const keys: DIDKeyModel[] = []
477
-
478
- for (const spec of specifications) {
479
- const key = master.derive(spec.path)
480
- await wallet.add(key, {
481
- ...spec.meta,
482
- id: `${spec.meta.name.toLowerCase().replace(/\s+/g, '-')}`
483
- })
484
- keys.push(key)
485
- }
486
-
487
- return keys
488
- }
28
+ // Derive a key for a specific entity
29
+ const key = await wallet.key({ entityId: 'entity-abc' })
30
+ const address = key.model.exportAddress()
489
31
  ```
490
32
 
491
- ## Error Handling
492
-
493
- The package provides specialized error types:
494
-
495
- ```typescript
496
- import { DIDWalletError, DIDKeyError, DIDInitializationError } from '@owlmeans/did'
497
-
498
- try {
499
- const wallet = await makeWallet(store)
500
- await wallet.generate()
501
- } catch (error) {
502
- if (error instanceof DIDInitializationError) {
503
- console.error('Wallet initialization failed:', error.message)
504
- } else if (error instanceof DIDKeyError) {
505
- console.error('Key operation failed:', error.message)
506
- } else if (error instanceof DIDWalletError) {
507
- console.error('Wallet operation failed:', error.message)
508
- }
509
- }
510
- ```
33
+ ## API
511
34
 
512
- ## Integration with OwlMeans Ecosystem
35
+ ### `makeWallet(store, opts?): Promise<DIDWallet>`
513
36
 
514
- The `@owlmeans/did` package integrates with:
37
+ Creates a wallet backed by the given `DIDStore`. Generates a master key on first call unless `opts.allowEmpty` is true.
515
38
 
516
- - **@owlmeans/basic-keys**: Core cryptographic operations and key management
517
- - **@owlmeans/auth**: Authentication and authorization with DID-based identities
518
- - **@owlmeans/resource**: Storage backend for wallet data persistence
519
- - **@owlmeans/client-did**: Client-side DID wallet implementations
520
- - **@owlmeans/server-auth**: Server-side DID authentication
521
- - **@owlmeans/context**: Service registration and dependency injection
39
+ ### `DIDWallet`
522
40
 
523
- ## Security Considerations
41
+ - `key(meta): Promise<DIDKeyModel>` — derive a key for the given metadata path
42
+ - `mnemonic(): string` — export the wallet mnemonic phrase
43
+ - `restore(mnemonic)` — restore the wallet from a mnemonic
524
44
 
525
- - Store mnemonic phrases securely and never expose them in logs
526
- - Use appropriate key derivation paths to prevent key correlation
527
- - Implement proper access controls for wallet operations
528
- - Regular backup of wallet data and mnemonic phrases
529
- - Use secure random number generation for key creation
530
- - Validate all imported keys and metadata
45
+ ### `DIDKeyModel`
531
46
 
532
- ## Best Practices
47
+ - `model: KeyPairModel` — the underlying `@owlmeans/basic-keys` model
48
+ - `meta: KeyMeta` — path metadata for this key
533
49
 
534
- ### Key Management
535
- - Use descriptive names and metadata for all keys
536
- - Implement consistent path naming conventions
537
- - Regular audit of stored keys and remove unused ones
538
- - Use different keys for different purposes (signing, encryption, etc.)
50
+ ### `KEY_OWL`
539
51
 
540
- ### Security
541
- - Never store private keys in plain text
542
- - Use hardware security modules where possible
543
- - Implement proper key rotation policies
544
- - Monitor for unauthorized key access
52
+ The default key type identifier: `'owlmk'`.
545
53
 
546
- ### Performance
547
- - Cache frequently used keys in memory
548
- - Use batch operations for multiple key operations
549
- - Implement proper indexing for key searches
550
- - Consider key compression for storage efficiency
54
+ ## Related Packages
551
55
 
552
- Fixes #32.
56
+ - [`@owlmeans/basic-keys`](../basic-keys) — `KeyPairModel` used internally for signing/verification
57
+ - [`@owlmeans/client-did`](../client-did) — client-side DID wallet service
58
+ - [`@owlmeans/server-auth`](../server-auth) — server-side auth using DID keys
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@owlmeans/did",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
+ "license": "MIT",
4
5
  "type": "module",
5
6
  "scripts": {
6
7
  "build": "tsc -b",
@@ -22,18 +23,19 @@
22
23
  "dependencies": {
23
24
  "@noble/curves": "^1.6.0",
24
25
  "@noble/hashes": "^1.5.0",
25
- "@owlmeans/auth": "^0.1.1",
26
- "@owlmeans/basic-keys": "^0.1.1",
27
- "@owlmeans/error": "^0.1.1",
28
- "@owlmeans/i18n": "^0.1.1",
29
- "@owlmeans/resource": "^0.1.1",
26
+ "@owlmeans/auth": "^0.1.3",
27
+ "@owlmeans/basic-keys": "^0.1.3",
28
+ "@owlmeans/error": "^0.1.3",
29
+ "@owlmeans/i18n": "^0.1.3",
30
+ "@owlmeans/resource": "^0.1.3",
30
31
  "@scure/base": "^1.1.9",
31
32
  "@scure/bip39": "^1.4.0"
32
33
  },
33
34
  "devDependencies": {
35
+ "@owlmeans/dep-config": "workspace:*",
34
36
  "nodemon": "^3.1.11",
35
37
  "npm-check": "^6.0.1",
36
- "typescript": "^5.8.3"
38
+ "typescript": "^6.0.2"
37
39
  },
38
40
  "publishConfig": {
39
41
  "access": "public"
package/tsconfig.json CHANGED
@@ -1,16 +1,11 @@
1
1
  {
2
2
  "extends": [
3
- "../tsconfig.default.json",
4
- "../tsconfig.react.json",
3
+ "@owlmeans/dep-config/tsconfig.base.json",
4
+ "@owlmeans/dep-config/tsconfig.react.json"
5
5
  ],
6
6
  "compilerOptions": {
7
- "rootDir": "./src/", /* Specify the root folder within your source files. */
8
- "outDir": "./build/", /* Specify an output folder for all emitted files. */
9
- "moduleResolution": "Bundler"
7
+ "rootDir": "./src/",
8
+ "outDir": "./build/"
10
9
  },
11
- "exclude": [
12
- "./dist/**/*",
13
- "./build/**/*",
14
- "./*.ts"
15
- ]
16
- }
10
+ "exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
11
+ }