@enbox/dwn-sdk-js 0.0.4 → 0.0.5

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 (134) hide show
  1. package/dist/browser.mjs +135 -0
  2. package/dist/browser.mjs.map +7 -0
  3. package/dist/esm/generated/precompiled-validators.js +640 -510
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/src/core/auth.js +6 -1
  6. package/dist/esm/src/core/auth.js.map +1 -1
  7. package/dist/esm/src/core/dwn-error.js +3 -0
  8. package/dist/esm/src/core/dwn-error.js.map +1 -1
  9. package/dist/esm/src/core/protocol-authorization.js +4 -0
  10. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  11. package/dist/esm/src/dwn.js +14 -0
  12. package/dist/esm/src/dwn.js.map +1 -1
  13. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  14. package/dist/esm/src/handlers/records-delete.js +13 -0
  15. package/dist/esm/src/handlers/records-delete.js.map +1 -1
  16. package/dist/esm/src/handlers/records-subscribe.js +121 -66
  17. package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
  18. package/dist/esm/src/handlers/records-write.js +1 -1
  19. package/dist/esm/src/handlers/records-write.js.map +1 -1
  20. package/dist/esm/src/index.js +1 -1
  21. package/dist/esm/src/index.js.map +1 -1
  22. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  23. package/dist/esm/src/interfaces/records-delete.js +1 -0
  24. package/dist/esm/src/interfaces/records-delete.js.map +1 -1
  25. package/dist/esm/src/interfaces/records-subscribe.js +2 -0
  26. package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
  27. package/dist/esm/src/interfaces/records-write.js +28 -45
  28. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  29. package/dist/esm/src/jose/jws/general/verifier.js +9 -1
  30. package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
  31. package/dist/esm/src/smt/smt-utils.js +1 -1
  32. package/dist/esm/src/smt/smt-utils.js.map +1 -1
  33. package/dist/esm/src/types/records-types.js.map +1 -1
  34. package/dist/esm/src/utils/encryption.js +221 -78
  35. package/dist/esm/src/utils/encryption.js.map +1 -1
  36. package/dist/esm/src/utils/hd-key.js +6 -7
  37. package/dist/esm/src/utils/hd-key.js.map +1 -1
  38. package/dist/esm/src/utils/protocols.js +12 -10
  39. package/dist/esm/src/utils/protocols.js.map +1 -1
  40. package/dist/esm/src/utils/records.js +33 -44
  41. package/dist/esm/src/utils/records.js.map +1 -1
  42. package/dist/esm/tests/features/protocol-composition.spec.js +26 -21
  43. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
  44. package/dist/esm/tests/features/records-tags.spec.js +5 -5
  45. package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
  46. package/dist/esm/tests/handlers/records-delete.spec.js +120 -2
  47. package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
  48. package/dist/esm/tests/handlers/records-read.spec.js +25 -26
  49. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  50. package/dist/esm/tests/handlers/records-subscribe.spec.js +103 -0
  51. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  52. package/dist/esm/tests/handlers/records-write.spec.js +124 -10
  53. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  54. package/dist/esm/tests/interfaces/messages-get.spec.js +3 -2
  55. package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
  56. package/dist/esm/tests/interfaces/records-write.spec.js +43 -34
  57. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  58. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +4 -4
  59. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
  60. package/dist/esm/tests/utils/encryption-callbacks.spec.js +21 -24
  61. package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
  62. package/dist/esm/tests/utils/encryption.spec.js +69 -66
  63. package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
  64. package/dist/esm/tests/utils/filters.spec.js +1 -0
  65. package/dist/esm/tests/utils/filters.spec.js.map +1 -1
  66. package/dist/esm/tests/utils/test-data-generator.js +28 -7
  67. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  68. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +1 -1
  69. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
  70. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  71. package/dist/types/src/core/auth.d.ts +3 -1
  72. package/dist/types/src/core/auth.d.ts.map +1 -1
  73. package/dist/types/src/core/dwn-error.d.ts +3 -0
  74. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  75. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
  76. package/dist/types/src/dwn.d.ts +12 -0
  77. package/dist/types/src/dwn.d.ts.map +1 -1
  78. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  79. package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
  80. package/dist/types/src/handlers/records-subscribe.d.ts +17 -28
  81. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
  82. package/dist/types/src/index.d.ts +4 -4
  83. package/dist/types/src/index.d.ts.map +1 -1
  84. package/dist/types/src/interfaces/records-delete.d.ts +4 -0
  85. package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
  86. package/dist/types/src/interfaces/records-subscribe.d.ts +4 -1
  87. package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
  88. package/dist/types/src/interfaces/records-write.d.ts +23 -53
  89. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  90. package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -1
  91. package/dist/types/src/types/encryption-types.d.ts +9 -8
  92. package/dist/types/src/types/encryption-types.d.ts.map +1 -1
  93. package/dist/types/src/types/protocols-types.d.ts +65 -16
  94. package/dist/types/src/types/protocols-types.d.ts.map +1 -1
  95. package/dist/types/src/types/records-types.d.ts +7 -26
  96. package/dist/types/src/types/records-types.d.ts.map +1 -1
  97. package/dist/types/src/utils/encryption.d.ts +157 -28
  98. package/dist/types/src/utils/encryption.d.ts.map +1 -1
  99. package/dist/types/src/utils/hd-key.d.ts +2 -3
  100. package/dist/types/src/utils/hd-key.d.ts.map +1 -1
  101. package/dist/types/src/utils/protocols.d.ts.map +1 -1
  102. package/dist/types/src/utils/records.d.ts +3 -4
  103. package/dist/types/src/utils/records.d.ts.map +1 -1
  104. package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
  105. package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
  106. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  107. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
  108. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  109. package/dist/types/tests/utils/test-data-generator.d.ts +7 -0
  110. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  111. package/package.json +8 -19
  112. package/src/core/auth.ts +12 -1
  113. package/src/core/dwn-error.ts +3 -0
  114. package/src/core/protocol-authorization.ts +8 -0
  115. package/src/dwn.ts +15 -0
  116. package/src/handlers/protocols-configure.ts +4 -4
  117. package/src/handlers/records-delete.ts +12 -0
  118. package/src/handlers/records-subscribe.ts +174 -75
  119. package/src/handlers/records-write.ts +1 -1
  120. package/src/index.ts +4 -4
  121. package/src/interfaces/protocols-configure.ts +5 -5
  122. package/src/interfaces/records-delete.ts +9 -3
  123. package/src/interfaces/records-subscribe.ts +6 -1
  124. package/src/interfaces/records-write.ts +33 -105
  125. package/src/jose/jws/general/verifier.ts +11 -1
  126. package/src/smt/smt-utils.ts +1 -1
  127. package/src/types/encryption-types.ts +9 -8
  128. package/src/types/protocols-types.ts +72 -18
  129. package/src/types/records-types.ts +7 -29
  130. package/src/utils/encryption.ts +346 -88
  131. package/src/utils/hd-key.ts +9 -10
  132. package/src/utils/protocols.ts +15 -13
  133. package/src/utils/records.ts +47 -55
  134. package/dist/bundles/dwn.js +0 -151
@@ -1,4 +1,5 @@
1
1
  import type { DerivedPrivateJwk } from './hd-key.js';
2
+ import type { Jwk } from '@enbox/crypto';
2
3
  import type { KeyDecrypter } from '../types/encryption-types.js';
3
4
  import type { Filter, KeyValues, StartsWithFilter } from '../types/query-types.js';
4
5
  import type { GenericMessage, GenericSignaturePayload, MessageSort } from '../types/message-types.js';
@@ -12,8 +13,8 @@ import { Jws } from './jws.js';
12
13
  import { Message } from '../core/message.js';
13
14
  import { PermissionGrant } from '../protocols/permission-grant.js';
14
15
  import { removeUndefinedProperties } from './object.js';
15
- import { Secp256k1 } from './secp256k1.js';
16
16
  import { SortDirection } from '../types/query-types.js';
17
+ import { X25519 } from '@enbox/crypto';
17
18
  import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
18
19
  import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
19
20
  import { HdKey, KeyDerivationScheme } from './hd-key.js';
@@ -39,7 +40,7 @@ export class Records {
39
40
  * Decrypts the encrypted data in a message reply.
40
41
  *
41
42
  * Overload 1 (callback-based): Accepts a KeyDecrypter that performs
42
- * HKDF derivation + ECIES decryption internally.
43
+ * HKDF derivation + ECDH-ES key agreement + AES Key Unwrap internally.
43
44
  */
44
45
  public static async decrypt(
45
46
  recordsWrite: RecordsWriteMessage,
@@ -48,7 +49,7 @@ export class Records {
48
49
  ): Promise<ReadableStream<Uint8Array>>;
49
50
 
50
51
  /**
51
- * Overload 2 (raw-key, existing): Takes DerivedPrivateJwk directly.
52
+ * Overload 2 (raw-key): Takes DerivedPrivateJwk directly.
52
53
  * @param ancestorPrivateKey Any ancestor private key in the key derivation path.
53
54
  */
54
55
  public static async decrypt(
@@ -64,72 +65,64 @@ export class Records {
64
65
  cipherStream: ReadableStream<Uint8Array>,
65
66
  ): Promise<ReadableStream<Uint8Array>> {
66
67
  const { encryption } = recordsWrite;
68
+ if (encryption === undefined) {
69
+ throw new DwnError(
70
+ DwnErrorCode.RecordsDecryptNoMatchingKeyEncryptedFound,
71
+ 'Message does not have an encryption property.'
72
+ );
73
+ }
74
+
67
75
  const isCallback = 'decrypt' in keyOrDecrypter;
68
76
 
69
- // Find matching key encryption entry
70
- const matchingEncryptedKey = encryption!.keyEncryption.find(key =>
71
- key.rootKeyId === keyOrDecrypter.rootKeyId &&
72
- key.derivationScheme === keyOrDecrypter.derivationScheme
77
+ // Parse the JWE protected header to determine the content encryption algorithm
78
+ const protectedHeader = Encryption.parseProtectedHeader(encryption.protected);
79
+ const enc = protectedHeader.enc;
80
+
81
+ // Find matching recipient entry by rootKeyId and derivationScheme
82
+ const matchingRecipient = encryption.recipients.find(r =>
83
+ r.header.kid === keyOrDecrypter.rootKeyId &&
84
+ r.header.derivationScheme === keyOrDecrypter.derivationScheme
73
85
  );
74
- if (matchingEncryptedKey === undefined) {
86
+ if (matchingRecipient === undefined) {
75
87
  throw new DwnError(
76
88
  DwnErrorCode.RecordsDecryptNoMatchingKeyEncryptedFound,
77
- `Unable to find a symmetric key encrypted using key \
89
+ `Unable to find a JWE recipient matching key \
78
90
  with ID '${keyOrDecrypter.rootKeyId}' and '${keyOrDecrypter.derivationScheme}' derivation scheme.`
79
91
  );
80
92
  }
81
93
 
82
- // Construct the full derivation path (reused for both paths)
94
+ // Construct the full derivation path
83
95
  const fullDerivationPath = Records.constructKeyDerivationPath(
84
- matchingEncryptedKey.derivationScheme, recordsWrite,
96
+ matchingRecipient.header.derivationScheme, recordsWrite,
85
97
  );
86
98
 
87
- let dataEncryptionKey: Uint8Array;
99
+ let cek: Uint8Array;
88
100
 
89
101
  if (isCallback) {
90
- // Callback-based: delegate HKDF + ECIES to the KeyDecrypter
91
- const encryptedKeyBytes = Encoder.base64UrlToBytes(
92
- matchingEncryptedKey.encryptedKey,
93
- );
94
- const ephemeralPublicKeyBytes = Secp256k1.publicJwkToBytes(
95
- matchingEncryptedKey.ephemeralPublicKey,
96
- );
97
- const iv = Encoder.base64UrlToBytes(
98
- matchingEncryptedKey.initializationVector,
99
- );
100
- const mac = Encoder.base64UrlToBytes(
101
- matchingEncryptedKey.messageAuthenticationCode,
102
- );
102
+ // Callback-based: delegate HKDF + ECDH-ES + AES Key Unwrap to the KeyDecrypter
103
+ const encryptedKeyBytes = Encoder.base64UrlToBytes(matchingRecipient.encrypted_key);
103
104
 
104
- dataEncryptionKey = await keyOrDecrypter.decrypt(fullDerivationPath, {
105
- ciphertext : encryptedKeyBytes,
106
- ephemeralPublicKey : ephemeralPublicKeyBytes,
107
- initializationVector : iv,
108
- messageAuthenticationCode : mac,
105
+ cek = await keyOrDecrypter.decrypt(fullDerivationPath, {
106
+ encryptedKey : encryptedKeyBytes,
107
+ ephemeralPublicKey : matchingRecipient.header.epk,
109
108
  });
110
109
  } else {
111
- // Raw-key path (existing logic, unchanged)
112
- // NOTE: right now only `ECIES-ES256K` algorithm is supported for asymmetric encryption,
113
- // so we will assume that's the algorithm without additional switch/if statements
114
- const leafPrivateKey = await Records.derivePrivateKey(keyOrDecrypter, fullDerivationPath);
115
- const encryptedKeyBytes = Encoder.base64UrlToBytes(matchingEncryptedKey.encryptedKey);
116
- const ephemeralPublicKey = Secp256k1.publicJwkToBytes(matchingEncryptedKey.ephemeralPublicKey);
117
- const keyEncryptionInitializationVector = Encoder.base64UrlToBytes(matchingEncryptedKey.initializationVector);
118
- const messageAuthenticationCode = Encoder.base64UrlToBytes(matchingEncryptedKey.messageAuthenticationCode);
119
- dataEncryptionKey = await Encryption.eciesSecp256k1Decrypt({
120
- ciphertext : encryptedKeyBytes,
121
- ephemeralPublicKey,
122
- initializationVector : keyEncryptionInitializationVector,
123
- messageAuthenticationCode,
124
- privateKey : leafPrivateKey
125
- });
110
+ // Raw-key path: derive the leaf private key, then ECDH-ES + AES Key Unwrap
111
+ const leafPrivateKeyBytes = await Records.derivePrivateKey(keyOrDecrypter, fullDerivationPath);
112
+ const leafPrivateKeyJwk = await X25519.bytesToPrivateKey({ privateKeyBytes: leafPrivateKeyBytes });
113
+ const wrappedKeyBytes = Encoder.base64UrlToBytes(matchingRecipient.encrypted_key);
114
+
115
+ cek = await Encryption.ecdhEsUnwrapKey(
116
+ leafPrivateKeyJwk,
117
+ matchingRecipient.header.epk as Jwk,
118
+ wrappedKeyBytes,
119
+ );
126
120
  }
127
121
 
128
- // AES decrypt data (shared by both paths)
129
- // NOTE: right now only `A256CTR` algorithm is supported for symmetric encryption,
130
- // so we will assume that's the algorithm without additional switch/if statements
131
- const dataEncryptionInitializationVector = Encoder.base64UrlToBytes(encryption!.initializationVector);
132
- const plaintextStream = await Encryption.aes256CtrDecrypt(dataEncryptionKey, dataEncryptionInitializationVector, cipherStream);
122
+ // AEAD decrypt data using the CEK
123
+ const iv = Encoder.base64UrlToBytes(encryption.iv);
124
+ const tag = Encoder.base64UrlToBytes(encryption.tag);
125
+ const plaintextStream = await Encryption.aeadDecryptStream(enc, cek, iv, cipherStream, tag);
133
126
 
134
127
  return plaintextStream;
135
128
  }
@@ -256,15 +249,14 @@ export class Records {
256
249
 
257
250
  /**
258
251
  * Derives a descendant private key given an ancestor private key and the full absolute derivation path.
259
- * NOTE: right now only `ECIES-ES256K` algorithm is supported for asymmetric encryption,
260
- * so we will only derive SECP256K1 key without additional conditional checks
252
+ * Uses X25519 keys for encryption key derivation.
261
253
  */
262
254
  public static async derivePrivateKey(ancestorPrivateKey: DerivedPrivateJwk, fullDescendantDerivationPath: string[]): Promise<Uint8Array> {
263
255
  const crv = 'crv' in ancestorPrivateKey.derivedPrivateKey ? ancestorPrivateKey.derivedPrivateKey.crv : undefined;
264
- if (crv !== 'secp256k1') {
256
+ if (crv !== 'X25519') {
265
257
  throw new DwnError(
266
258
  DwnErrorCode.RecordsDerivePrivateKeyUnSupportedCurve,
267
- `Curve ${crv} is not supported.`
259
+ `Curve '${crv}' is not supported for encryption key derivation. Expected 'X25519'.`
268
260
  );
269
261
  }
270
262
 
@@ -273,7 +265,7 @@ export class Records {
273
265
  Records.validateAncestorKeyAndDescentKeyDerivationPathsMatch(ancestorPrivateKeyDerivationPath, fullDescendantDerivationPath);
274
266
 
275
267
  const subDerivationPath = fullDescendantDerivationPath.slice(ancestorPrivateKeyDerivationPath.length);
276
- const ancestorPrivateKeyBytes = Secp256k1.privateJwkToBytes(ancestorPrivateKey.derivedPrivateKey);
268
+ const ancestorPrivateKeyBytes = await X25519.privateKeyToBytes({ privateKey: ancestorPrivateKey.derivedPrivateKey });
277
269
  const leafPrivateKey = await HdKey.derivePrivateKeyBytes(ancestorPrivateKeyBytes, subDerivationPath);
278
270
 
279
271
  return leafPrivateKey;