@enbox/dids 0.0.4 → 0.0.6

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.
Files changed (55) hide show
  1. package/dist/browser.mjs +1 -1
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/methods/did-dht-dns.js +455 -0
  4. package/dist/esm/methods/did-dht-dns.js.map +1 -0
  5. package/dist/esm/methods/did-dht-pkarr.js +168 -0
  6. package/dist/esm/methods/did-dht-pkarr.js.map +1 -0
  7. package/dist/esm/methods/did-dht-types.js +116 -0
  8. package/dist/esm/methods/did-dht-types.js.map +1 -0
  9. package/dist/esm/methods/did-dht-utils.js +143 -0
  10. package/dist/esm/methods/did-dht-utils.js.map +1 -0
  11. package/dist/esm/methods/did-dht.js +65 -842
  12. package/dist/esm/methods/did-dht.js.map +1 -1
  13. package/dist/esm/methods/did-ion-utils.js +161 -0
  14. package/dist/esm/methods/did-ion-utils.js.map +1 -0
  15. package/dist/esm/methods/did-ion.js +4 -151
  16. package/dist/esm/methods/did-ion.js.map +1 -1
  17. package/dist/esm/methods/did-key-utils.js +235 -0
  18. package/dist/esm/methods/did-key-utils.js.map +1 -0
  19. package/dist/esm/methods/did-key.js +6 -222
  20. package/dist/esm/methods/did-key.js.map +1 -1
  21. package/dist/esm/utils.js +15 -19
  22. package/dist/esm/utils.js.map +1 -1
  23. package/dist/types/methods/did-dht-dns.d.ts +114 -0
  24. package/dist/types/methods/did-dht-dns.d.ts.map +1 -0
  25. package/dist/types/methods/did-dht-pkarr.d.ts +56 -0
  26. package/dist/types/methods/did-dht-pkarr.d.ts.map +1 -0
  27. package/dist/types/methods/did-dht-types.d.ts +286 -0
  28. package/dist/types/methods/did-dht-types.d.ts.map +1 -0
  29. package/dist/types/methods/did-dht-utils.d.ts +54 -0
  30. package/dist/types/methods/did-dht-utils.d.ts.map +1 -0
  31. package/dist/types/methods/did-dht.d.ts +42 -457
  32. package/dist/types/methods/did-dht.d.ts.map +1 -1
  33. package/dist/types/methods/did-ion-utils.d.ts +86 -0
  34. package/dist/types/methods/did-ion-utils.d.ts.map +1 -0
  35. package/dist/types/methods/did-ion.d.ts +2 -82
  36. package/dist/types/methods/did-ion.d.ts.map +1 -1
  37. package/dist/types/methods/did-key-utils.d.ts +138 -0
  38. package/dist/types/methods/did-key-utils.d.ts.map +1 -0
  39. package/dist/types/methods/did-key.d.ts +3 -124
  40. package/dist/types/methods/did-key.d.ts.map +1 -1
  41. package/dist/types/utils.d.ts +25 -25
  42. package/dist/types/utils.d.ts.map +1 -1
  43. package/dist/utils.js +1 -1
  44. package/dist/utils.js.map +4 -4
  45. package/package.json +4 -4
  46. package/src/methods/did-dht-dns.ts +516 -0
  47. package/src/methods/did-dht-pkarr.ts +192 -0
  48. package/src/methods/did-dht-types.ts +316 -0
  49. package/src/methods/did-dht-utils.ts +157 -0
  50. package/src/methods/did-dht.ts +122 -1128
  51. package/src/methods/did-ion-utils.ts +186 -0
  52. package/src/methods/did-ion.ts +14 -190
  53. package/src/methods/did-key-utils.ts +258 -0
  54. package/src/methods/did-key.ts +14 -266
  55. package/src/utils.ts +31 -30
@@ -1,39 +1,30 @@
1
+ import type { PortableDid } from '../types/portable-did.js';
2
+ import type { DidCreateOptions, DidCreateVerificationMethod } from './did-method.js';
3
+ import type {
4
+ DidDocument,
5
+ DidResolutionOptions,
6
+ DidResolutionResult,
7
+ DidVerificationMethod,
8
+ } from '../types/did-core.js';
1
9
  import type {
2
- AsymmetricKeyConverter,
3
10
  InferKeyGeneratorAlgorithm,
4
- Jwk,
5
- KeyCompressor,
6
11
  KeyIdentifier,
7
12
  KeyImporterExporter,
8
13
  KeyManager,
9
14
  KmsExportKeyParams,
10
15
  KmsImportKeyParams,
11
16
  } from '@enbox/crypto';
12
- import type { MulticodecCode, MulticodecDefinition } from '@enbox/common';
13
17
 
14
- import {
15
- Ed25519,
16
- LocalKeyManager,
17
- Secp256k1,
18
- Secp256r1,
19
- } from '@enbox/crypto';
20
- import { Multicodec, universalTypeOf } from '@enbox/common';
21
-
22
- import type { PortableDid } from '../types/portable-did.js';
23
- import type { DidCreateOptions, DidCreateVerificationMethod } from './did-method.js';
24
- import type {
25
- DidDocument,
26
- DidResolutionOptions,
27
- DidResolutionResult,
28
- DidVerificationMethod,
29
- } from '../types/did-core.js';
18
+ import { universalTypeOf } from '@enbox/common';
19
+ import { Ed25519, LocalKeyManager, Secp256k1 } from '@enbox/crypto';
30
20
 
31
21
  import { BearerDid } from '../bearer-did.js';
32
22
  import { Did } from '../did.js';
23
+ import { DidKeyUtils } from './did-key-utils.js';
33
24
  import { DidMethod } from './did-method.js';
34
25
  import { EMPTY_DID_RESOLUTION_RESULT } from '../types/did-resolution.js';
35
26
  import { DidError, DidErrorCode } from '../did-error.js';
36
- import { getVerificationMethodTypes, keyBytesToMultibaseId, multibaseIdToKeyBytes } from '../utils.js';
27
+ import { getVerificationMethodTypes, multibaseIdToKeyBytes } from '../utils.js';
37
28
 
38
29
  /**
39
30
  * Defines the set of options available when creating a new Decentralized Identifier (DID) with the
@@ -165,19 +156,6 @@ export const DidKeyVerificationMethodType = {
165
156
  JsonWebKey2020: 'https://w3id.org/security/suites/jws-2020/v1',
166
157
  } as const;
167
158
 
168
- /**
169
- * Private helper that maps algorithm identifiers to their corresponding DID Key
170
- * {@link DidKeyRegisteredKeyType | registered key type}.
171
- */
172
- const AlgorithmToKeyTypeMap = {
173
- Ed25519 : DidKeyRegisteredKeyType.Ed25519,
174
- ES256K : DidKeyRegisteredKeyType.secp256k1,
175
- ES256 : DidKeyRegisteredKeyType.secp256r1,
176
- 'P-256' : DidKeyRegisteredKeyType.secp256r1,
177
- secp256k1 : DidKeyRegisteredKeyType.secp256k1,
178
- secp256r1 : DidKeyRegisteredKeyType.secp256r1,
179
- } as const;
180
-
181
159
  /**
182
160
  * The `DidKey` class provides an implementation of the 'did:key' DID method.
183
161
  *
@@ -733,235 +711,5 @@ export class DidKey extends DidMethod {
733
711
  }
734
712
  }
735
713
 
736
- /**
737
- * The `DidKeyUtils` class provides utility functions to support operations in the DID Key method.
738
- */
739
- export class DidKeyUtils {
740
- /**
741
- * A mapping from JSON Web Key (JWK) property descriptors to multicodec names.
742
- *
743
- * This mapping is used to convert keys in JWK (JSON Web Key) format to multicodec format.
744
- *
745
- * @remarks
746
- * The keys of this object are strings that describe the JOSE key type and usage,
747
- * such as 'Ed25519:public', 'Ed25519:private', etc. The values are the corresponding multicodec
748
- * names used to represent these key types.
749
- *
750
- * @example
751
- * ```ts
752
- * const multicodecName = JWK_TO_MULTICODEC['Ed25519:public'];
753
- * // Returns 'ed25519-pub', the multicodec name for an Ed25519 public key
754
- * ```
755
- */
756
- private static JWK_TO_MULTICODEC: { [key: string]: string } = {
757
- 'Ed25519:public' : 'ed25519-pub',
758
- 'Ed25519:private' : 'ed25519-priv',
759
- 'secp256k1:public' : 'secp256k1-pub',
760
- 'secp256k1:private' : 'secp256k1-priv',
761
- };
762
-
763
- /**
764
- * Defines the expected byte lengths for public keys associated with different cryptographic
765
- * algorithms, indexed by their multicodec code values.
766
- */
767
- public static MULTICODEC_PUBLIC_KEY_LENGTH: Record<number, number> = {
768
- // secp256k1-pub - Secp256k1 public key (compressed) - 33 bytes
769
- 0xe7: 33,
770
-
771
- // ed25519-pub - Ed25519 public key - 32 bytes
772
- 0xed: 32
773
- };
774
-
775
- /**
776
- * A mapping from multicodec names to their corresponding JOSE (JSON Object Signing and Encryption)
777
- * representations. This mapping facilitates the conversion of multicodec key formats to
778
- * JWK (JSON Web Key) formats.
779
- *
780
- * @remarks
781
- * The keys of this object are multicodec names, such as 'ed25519-pub', 'ed25519-priv', etc.
782
- * The values are objects representing the corresponding JWK properties for that key type.
783
- *
784
- * @example
785
- * ```ts
786
- * const joseKey = MULTICODEC_TO_JWK['ed25519-pub'];
787
- * // Returns a partial JWK for an Ed25519 public key
788
- * ```
789
- */
790
- private static MULTICODEC_TO_JWK: { [key: string]: Jwk } = {
791
- 'ed25519-pub' : { crv: 'Ed25519', kty: 'OKP', x: '' },
792
- 'ed25519-priv' : { crv: 'Ed25519', kty: 'OKP', x: '', d: '' },
793
- 'secp256k1-pub' : { crv: 'secp256k1', kty: 'EC', x: '', y: '' },
794
- 'secp256k1-priv' : { crv: 'secp256k1', kty: 'EC', x: '', y: '', d: '' },
795
- };
796
-
797
- /**
798
- * Converts a JWK (JSON Web Key) to a Multicodec code and name.
799
- *
800
- * @example
801
- * ```ts
802
- * const jwk: Jwk = { crv: 'Ed25519', kty: 'OKP', x: '...' };
803
- * const { code, name } = await DidKeyUtils.jwkToMulticodec({ jwk });
804
- * ```
805
- *
806
- * @param params - The parameters for the conversion.
807
- * @param params.jwk - The JSON Web Key to be converted.
808
- * @returns A promise that resolves to a Multicodec definition.
809
- */
810
- public static async jwkToMulticodec({ jwk }: {
811
- jwk: Jwk
812
- }): Promise<MulticodecDefinition<MulticodecCode>> {
813
- const params: string[] = [];
814
-
815
- if (jwk.crv) {
816
- params.push(jwk.crv);
817
- if (jwk.d) {
818
- params.push('private');
819
- } else {
820
- params.push('public');
821
- }
822
- }
823
-
824
- const lookupKey = params.join(':');
825
- const name = DidKeyUtils.JWK_TO_MULTICODEC[lookupKey];
826
-
827
- if (name === undefined) {
828
- throw new Error(`Unsupported JWK to Multicodec conversion: '${lookupKey}'`);
829
- }
830
-
831
- const code = Multicodec.getCodeFromName({ name });
832
-
833
- return { code, name };
834
- }
835
-
836
- /**
837
- * Returns the appropriate public key compressor for the specified cryptographic curve.
838
- *
839
- * @param curve - The cryptographic curve to use for the key conversion.
840
- * @returns A public key compressor for the specified curve.
841
- */
842
- public static keyCompressor(
843
- curve: string
844
- ): KeyCompressor['compressPublicKey'] {
845
- // ): ({ publicKeyBytes }: { publicKeyBytes: Uint8Array }) => Promise<Uint8Array> {
846
- const compressors = {
847
- 'P-256' : Secp256r1.compressPublicKey,
848
- 'secp256k1' : Secp256k1.compressPublicKey
849
- } as Record<string, KeyCompressor['compressPublicKey']>;
850
-
851
- const compressor = compressors[curve];
852
-
853
- if (!compressor) {throw new DidError(DidErrorCode.InvalidPublicKeyType, `Unsupported curve: ${curve}`);}
854
-
855
- return compressor;
856
- }
857
-
858
- /**
859
- * Returns the appropriate key converter for the specified cryptographic curve.
860
- *
861
- * @param curve - The cryptographic curve to use for the key conversion.
862
- * @returns An `AsymmetricKeyConverter` for the specified curve.
863
- */
864
- public static keyConverter(curve: string): AsymmetricKeyConverter {
865
- const converters: Record<string, AsymmetricKeyConverter> = {
866
- 'Ed25519' : Ed25519,
867
- 'P-256' : Secp256r1,
868
- 'secp256k1' : Secp256k1,
869
- };
870
-
871
- const converter = converters[curve];
872
-
873
- if (!converter) {throw new DidError(DidErrorCode.InvalidPublicKeyType, `Unsupported curve: ${curve}`);}
874
-
875
- return converter;
876
- }
877
-
878
- /**
879
- * Converts a Multicodec code or name to parial JWK (JSON Web Key).
880
- *
881
- * @example
882
- * ```ts
883
- * const partialJwk = await DidKeyUtils.multicodecToJwk({ name: 'ed25519-pub' });
884
- * ```
885
- *
886
- * @param params - The parameters for the conversion.
887
- * @param params.code - Optional Multicodec code to convert.
888
- * @param params.name - Optional Multicodec name to convert.
889
- * @returns A promise that resolves to a JOSE format key.
890
- */
891
- public static async multicodecToJwk({ code, name }: {
892
- code?: MulticodecCode,
893
- name?: string
894
- }): Promise<Jwk> {
895
- // Either code or name must be specified, but not both.
896
- if (!(name ? !code : code)) {
897
- throw new Error(`Either 'name' or 'code' must be defined, but not both.`);
898
- }
899
-
900
- // If name is undefined, lookup by code.
901
- name = (name === undefined ) ? Multicodec.getNameFromCode({ code: code! }) : name;
902
-
903
- const lookupKey = name;
904
- const jose = DidKeyUtils.MULTICODEC_TO_JWK[lookupKey];
905
-
906
- if (jose === undefined) {
907
- throw new Error(`Unsupported Multicodec to JWK conversion`);
908
- }
909
-
910
- return { ...jose };
911
- }
912
-
913
- /**
914
- * Converts a public key in JWK (JSON Web Key) format to a multibase identifier.
915
- *
916
- * @remarks
917
- * Note: All secp public keys are converted to compressed point encoding
918
- * before the multibase identifier is computed.
919
- *
920
- * Per {@link https://github.com/multiformats/multicodec/blob/master/table.csv | Multicodec table}:
921
- * Public keys for Elliptic Curve cryptography algorithms (e.g., secp256k1,
922
- * secp256k1r1, secp384r1, etc.) are always represented with compressed point
923
- * encoding (e.g., secp256k1-pub, p256-pub, p384-pub, etc.).
924
- *
925
- * Per {@link https://datatracker.ietf.org/doc/html/rfc8812#name-jose-and-cose-secp256k1-cur | RFC 8812}:
926
- * "As a compressed point encoding representation is not defined for JWK
927
- * elliptic curve points, the uncompressed point encoding defined there
928
- * MUST be used. The x and y values represented MUST both be exactly
929
- * 256 bits, with any leading zeros preserved."
930
- *
931
- * @example
932
- * ```ts
933
- * const publicKey = { crv: 'Ed25519', kty: 'OKP', x: '...' };
934
- * const multibaseId = await DidKeyUtils.publicKeyToMultibaseId({ publicKey });
935
- * ```
936
- *
937
- * @param params - The parameters for the conversion.
938
- * @param params.publicKey - The public key in JWK format.
939
- * @returns A promise that resolves to the multibase identifier.
940
- */
941
- public static async publicKeyToMultibaseId({ publicKey }: {
942
- publicKey: Jwk
943
- }): Promise<string> {
944
- if (!(publicKey?.crv && publicKey.crv in AlgorithmToKeyTypeMap)) {
945
- throw new DidError(DidErrorCode.InvalidPublicKeyType, `Public key contains an unsupported key type: ${publicKey?.crv ?? 'undefined'}`);
946
- }
947
-
948
- // Convert the public key from JWK format to a byte array.
949
- let publicKeyBytes = await DidKeyUtils.keyConverter(publicKey.crv).publicKeyToBytes({ publicKey });
950
-
951
- // Compress the public key if it is an elliptic curve key.
952
- if (/^(secp256k1|P-256|P-384|P-521)$/.test(publicKey.crv)) {
953
- publicKeyBytes = await DidKeyUtils.keyCompressor(publicKey.crv)({ publicKeyBytes });
954
- }
955
-
956
- // Convert the JSON Web Key (JWK) parameters to a Multicodec name.
957
- const { name: multicodecName } = await DidKeyUtils.jwkToMulticodec({ jwk: publicKey });
958
-
959
- // Compute the multibase identifier based on the provided key.
960
- const multibaseId = keyBytesToMultibaseId({
961
- keyBytes: publicKeyBytes,
962
- multicodecName
963
- });
964
-
965
- return multibaseId;
966
- }
967
- }
714
+ // Re-export DidKeyUtils from its dedicated module for backward compatibility.
715
+ export { DidKeyUtils } from './did-key-utils.js';
package/src/utils.ts CHANGED
@@ -19,38 +19,44 @@ import { DidError, DidErrorCode } from './did-error.js';
19
19
  * Represents a Decentralized Web Node (DWN) service in a DID Document.
20
20
  *
21
21
  * A DWN DID service is a specialized type of DID service with the `type` set to
22
- * `DecentralizedWebNode`. It includes specific properties `enc` and `sig` that are used to identify
23
- * the public keys that can be used to interact with the DID Subject. The values of these properties
24
- * are strings or arrays of strings containing one or more verification method `id` values present in
25
- * the same DID document. If the `enc` and/or `sig` properties are an array of strings, an entity
26
- * interacting with the DID subject is expected to use the verification methods in the order they
27
- * are listed.
22
+ * `DecentralizedWebNode`. Encryption and signing keys are resolved from the DID document's
23
+ * verification methods, not from the service entry.
24
+ *
25
+ * The `enc` and `sig` properties are optional legacy fields that may be present on existing
26
+ * DID documents for backward compatibility. When present, they contain verification method `id`
27
+ * values that hint at which keys to use for encryption and signing. New implementations should
28
+ * resolve keys from the DID document's verification methods by purpose (`keyAgreement` for
29
+ * encryption, `authentication`/`assertionMethod` for signing).
28
30
  *
29
31
  * @example
30
32
  * ```ts
31
33
  * const service: DwnDidService = {
32
34
  * id: 'did:example:123#dwn',
33
35
  * type: 'DecentralizedWebNode',
34
- * serviceEndpoint: 'https://enbox-dwn.fly.dev',
35
- * enc: 'did:example:123#key-1',
36
- * sig: 'did:example:123#key-2'
36
+ * serviceEndpoint: 'https://enbox-dwn.fly.dev'
37
37
  * }
38
38
  * ```
39
39
  *
40
- * @see {@link https://identity.foundation/decentralized-web-node/spec/ | DIF Decentralized Web Node (DWN) Specification}
40
+ * @see {@link https://github.com/enboxorg/dwn-spec | Enbox DWN Specification}
41
41
  */
42
42
  export interface DwnDidService extends DidService {
43
43
  /**
44
+ * @deprecated Optional legacy field. Resolve encryption keys from the DID document's
45
+ * `keyAgreement` verification methods instead.
46
+ *
44
47
  * One or more verification method `id` values that can be used to encrypt information
45
48
  * intended for the DID subject.
46
49
  */
47
50
  enc?: string | string[];
48
51
 
49
52
  /**
53
+ * @deprecated Optional legacy field. Resolve signing keys from the DID document's
54
+ * `authentication` or `assertionMethod` verification methods instead.
55
+ *
50
56
  * One or more verification method `id` values that will be used by the DID subject to sign data
51
57
  * or by another entity to verify signatures created by the DID subject.
52
58
  */
53
- sig: string | string[];
59
+ sig?: string | string[];
54
60
  }
55
61
 
56
62
  /**
@@ -368,9 +374,11 @@ export function isDidService(obj: unknown): obj is DidService {
368
374
  /**
369
375
  * Checks if a given object is a {@link DwnDidService}.
370
376
  *
371
- * A {@link DwnDidService} is defined as {@link DidService} object with a `type` of
372
- * "DecentralizedWebNode" and `enc` and `sig` properties, where both properties are either strings
373
- * or arrays of strings.
377
+ * A {@link DwnDidService} is defined as a {@link DidService} object with a `type` of
378
+ * `"DecentralizedWebNode"`. The `enc` and `sig` properties are optional they may be present
379
+ * on existing DID documents for backward compatibility, but are not required per the DWN
380
+ * specification. Encryption and signing keys are resolved from the DID document's verification
381
+ * methods, not from the service entry.
374
382
  *
375
383
  * @example
376
384
  * ```ts
@@ -382,33 +390,25 @@ export function isDidService(obj: unknown): obj is DidService {
382
390
  * type: 'JsonWebKey2020',
383
391
  * controller: 'did:example:123',
384
392
  * publicKeyJwk: { ... }
385
- * },
386
- * {
387
- * id: 'did:example:123#key-2',
388
- * type: 'JsonWebKey2020',
389
- * controller: 'did:example:123',
390
- * publicKeyJwk: { ... }
391
393
  * }
392
394
  * ],
393
395
  * service: [
394
396
  * {
395
397
  * id: 'did:example:123#dwn',
396
398
  * type: 'DecentralizedWebNode',
397
- * serviceEndpoint: 'https://enbox-dwn.fly.dev',
398
- * enc: 'did:example:123#key-1',
399
- * sig: 'did:example:123#key-2'
399
+ * serviceEndpoint: 'https://enbox-dwn.fly.dev'
400
400
  * }
401
401
  * ]
402
402
  * };
403
403
  *
404
- * if (isDwnService(didDocument.service[0])) {
404
+ * if (isDwnDidService(didDocument.service[0])) {
405
405
  * console.log('The object is a DwnDidService');
406
406
  * } else {
407
407
  * console.log('The object is not a DwnDidService');
408
408
  * }
409
409
  * ```
410
410
  *
411
- * @see {@link https://identity.foundation/decentralized-web-node/spec/ | Decentralized Web Node (DWN) Specification}
411
+ * @see {@link https://github.com/enboxorg/dwn-spec | Enbox DWN Specification}
412
412
  *
413
413
  * @param obj - The object to be checked.
414
414
  * @returns `true` if `obj` is a DwnDidService; otherwise, `false`.
@@ -420,13 +420,14 @@ export function isDwnDidService(obj: unknown): obj is DwnDidService {
420
420
  // Validate that the `type` property is `DecentralizedWebNode`.
421
421
  if (obj.type !== 'DecentralizedWebNode') {return false;}
422
422
 
423
- // Validate that the given object has the `enc` and `sig` properties.
424
- if (!('enc' in obj && 'sig' in obj)) {return false;}
425
-
426
- // Validate that the `enc` and `sig` properties are either strings or arrays of strings.
423
+ // If `enc` or `sig` are present, validate they are strings or arrays of strings.
427
424
  const isStringOrStringArray = (prop: any): boolean =>
428
425
  typeof prop === 'string' || Array.isArray(prop) && prop.every(item => typeof item === 'string');
429
- return (isStringOrStringArray(obj.enc)) && (isStringOrStringArray(obj.sig));
426
+
427
+ if ('enc' in obj && obj.enc !== undefined && !isStringOrStringArray(obj.enc)) {return false;}
428
+ if ('sig' in obj && obj.sig !== undefined && !isStringOrStringArray(obj.sig)) {return false;}
429
+
430
+ return true;
430
431
  }
431
432
 
432
433
  /**