@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
@@ -6,8 +6,6 @@ import type { MessageStore } from '../types/message-store.js';
6
6
  import type { PublicKeyJwk } from '../types/jose-types.js';
7
7
  import type {
8
8
  DataEncodedRecordsWriteMessage,
9
- EncryptedKey,
10
- EncryptionProperty,
11
9
  InternalRecordsWriteMessage,
12
10
  RecordsWriteAttestationPayload,
13
11
  RecordsWriteDescriptor,
@@ -15,12 +13,12 @@ import type {
15
13
  RecordsWriteSignaturePayload,
16
14
  RecordsWriteTags
17
15
  } from '../types/records-types.js';
16
+ import type { EncryptionInput, JweEncryption } from '../utils/encryption.js';
18
17
  import type { GenericMessage, GenericSignaturePayload } from '../types/message-types.js';
19
18
 
20
19
  import { Cid } from '../utils/cid.js';
21
20
  import { Encoder } from '../utils/encoder.js';
22
21
  import { Encryption } from '../utils/encryption.js';
23
- import { EncryptionAlgorithm } from '../utils/encryption.js';
24
22
  import { GeneralJwsBuilder } from '../jose/jws/general/builder.js';
25
23
  import { Jws } from '../utils/jws.js';
26
24
  import { KeyDerivationScheme } from '../utils/hd-key.js';
@@ -29,7 +27,6 @@ import { PermissionGrant } from '../protocols/permission-grant.js';
29
27
  import { Records } from '../utils/records.js';
30
28
  import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
31
29
  import { removeUndefinedProperties } from '../utils/object.js';
32
- import { Secp256k1 } from '../utils/secp256k1.js';
33
30
  import { Time } from '../utils/time.js';
34
31
  import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
35
32
  import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
@@ -85,57 +82,7 @@ export type RecordsWriteOptions = {
85
82
  };
86
83
  };
87
84
 
88
- /**
89
- * Input that describes how data is encrypted as spec-ed in TP18.
90
- */
91
- export type EncryptionInput = {
92
- /**
93
- * Algorithm used for encrypting the Data. Uses {EncryptionAlgorithm.Aes256Ctr} if not given.
94
- */
95
- algorithm?: EncryptionAlgorithm;
96
-
97
- /**
98
- * Initialization vector used for encrypting the data.
99
- */
100
- initializationVector: Uint8Array;
101
-
102
- /**
103
- * Symmetric key used to encrypt the data.
104
- */
105
- key: Uint8Array;
106
-
107
- /**
108
- * Array of input that specifies how the symmetric key is encrypted.
109
- * Each entry in the array will result in a unique ciphertext of the symmetric key.
110
- */
111
- keyEncryptionInputs: KeyEncryptionInput[];
112
- };
113
-
114
- /**
115
- * Input that specifies how a symmetric key is encrypted.
116
- */
117
- export type KeyEncryptionInput = {
118
- /**
119
- * Key derivation scheme used to derive the public key to encrypt the symmetric key.
120
- */
121
- derivationScheme: KeyDerivationScheme;
122
-
123
- /**
124
- * Fully qualified ID of root public key used derive the public key to be used to to encrypt the symmetric key.
125
- * (e.g. did:example:abc#encryption-key-id)
126
- */
127
- publicKeyId: string;
128
-
129
- /**
130
- * Public key to be used to encrypt the symmetric key.
131
- */
132
- publicKey: PublicKeyJwk;
133
-
134
- /**
135
- * Algorithm used for encrypting the symmetric key. Uses {EncryptionAlgorithm.EciesSecp256k1} if not given.
136
- */
137
- algorithm?: EncryptionAlgorithm;
138
- };
85
+ export type { EncryptionInput, KeyEncryptionInput } from '../utils/encryption.js';
139
86
 
140
87
  export type CreateFromOptions = {
141
88
  recordsWriteMessage: RecordsWriteMessage,
@@ -499,10 +446,10 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
499
446
  /**
500
447
  * Encrypts the symmetric encryption key using the public keys given and attach the resulting `encryption` property to the RecordsWrite.
501
448
  *
502
- * @param options.append - When `true`, appends new `keyEncryption` entries to the existing
449
+ * @param options.append - When `true`, appends new `recipients` entries to the existing
503
450
  * `encryption` property instead of replacing it. Requires `this._message.encryption` to
504
451
  * already exist (i.e., the record must already be encrypted). This is used for the reactive
505
- * root-record upgrade: adding a ProtocolContext `keyEncryption` entry alongside an existing
452
+ * root-record upgrade: adding a ProtocolContext recipient entry alongside an existing
506
453
  * ProtocolPath entry so both the owner and context key holders can decrypt.
507
454
  */
508
455
  public async encryptSymmetricEncryptionKey(
@@ -513,20 +460,20 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
513
460
  if (!this._message.encryption) {
514
461
  throw new DwnError(
515
462
  DwnErrorCode.RecordsWriteMissingEncryption,
516
- 'Cannot append keyEncryption entries: record does not have an existing `encryption` property.'
463
+ 'Cannot append recipients: record does not have an existing `encryption` property.'
517
464
  );
518
465
  }
519
466
 
520
- // Build only the new keyEncryption entries (reuses createEncryptionProperty for ECIES logic)
467
+ // Build only the new recipients (reuses createEncryptionProperty for ECDH-ES+A256KW logic)
521
468
  const newEncryption = await RecordsWrite.createEncryptionProperty(this._message.descriptor, encryptionInput);
522
469
  if (newEncryption) {
523
- this._message.encryption.keyEncryption.push(...newEncryption.keyEncryption);
470
+ this._message.encryption.recipients.push(...newEncryption.recipients);
524
471
  }
525
472
 
526
473
  // In append mode, preserve the author's identity and authorization so
527
474
  // that signAsOwner() can be called afterwards. The author's signature
528
475
  // payload will have a stale encryptionCid (since we just appended new
529
- // keyEncryption entries), but the owner's signature vouches for the
476
+ // recipients), but the owner's signature vouches for the
530
477
  // updated state. validateIntegrity() skips the encryptionCid check on
531
478
  // the author's signature when an ownerSignature is present.
532
479
  //
@@ -727,7 +674,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
727
674
 
728
675
  // If `encryption` is given in message, make sure the correct `encryptionCid`
729
676
  // is in the payload of the message signature — UNLESS the message has an
730
- // ownerSignature. When the DWN owner appends keyEncryption entries to an
677
+ // ownerSignature. When the DWN owner appends recipients to an
731
678
  // externally-authored record (reactive root-record upgrade), the author's
732
679
  // encryptionCid becomes stale. The owner's signature vouches for the
733
680
  // updated encryption property, so the mismatch is expected and safe.
@@ -759,7 +706,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
759
706
 
760
707
  /**
761
708
  * Validates the structural integrity of the `attestation` property.
762
- * NOTE: signature is not verified.
709
+ * NOTE: Cryptographic verification of attestation signatures is performed in `authenticate()`.
763
710
  */
764
711
  private static async validateAttestationIntegrity(message: RecordsWriteMessage): Promise<void> {
765
712
  if (message.attestation === undefined) {
@@ -906,21 +853,33 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
906
853
  }
907
854
 
908
855
  /**
909
- * Creates the `encryption` property if encryption input is given. Else `undefined` is returned.
910
- * @param descriptor Descriptor of the `RecordsWrite` message which contains the information need by key path derivation schemes.
856
+ * Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
857
+ * Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
858
+ * @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
859
+ */
860
+ /**
861
+ * Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
862
+ * Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
863
+ * @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
864
+ * @param encryptionInput The encryption input containing CEK, IV, and recipient key encryption inputs.
865
+ * @param tag The authentication tag from the AEAD content encryption (stored in the JWE, separate from the ciphertext).
866
+ */
867
+ /**
868
+ * Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
869
+ * Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
870
+ * @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
871
+ * @param encryptionInput The encryption input containing CEK, IV, authentication tag, and recipient key encryption inputs.
911
872
  */
912
873
  private static async createEncryptionProperty(
913
874
  descriptor: RecordsWriteDescriptor,
914
- encryptionInput: EncryptionInput | undefined
915
- ): Promise<EncryptionProperty | undefined> {
875
+ encryptionInput: EncryptionInput | undefined,
876
+ ): Promise<JweEncryption | undefined> {
916
877
  if (encryptionInput === undefined) {
917
878
  return undefined;
918
879
  }
919
880
 
920
- // encrypt the data encryption key once per encryption input
921
- const keyEncryption: EncryptedKey[] = [];
881
+ // Validate derivation scheme prerequisites
922
882
  for (const keyEncryptionInput of encryptionInput.keyEncryptionInputs) {
923
-
924
883
  if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.ProtocolPath && descriptor.protocol === undefined) {
925
884
  throw new DwnError(
926
885
  DwnErrorCode.RecordsWriteMissingProtocol,
@@ -934,43 +893,12 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
934
893
  '`schemas` encryption scheme cannot be applied to record without the `schema` property.'
935
894
  );
936
895
  }
937
-
938
- // NOTE: right now only `ECIES-ES256K` algorithm is supported for asymmetric encryption,
939
- // so we will assume that's the algorithm without additional switch/if statements
940
- const publicKeyBytes = Secp256k1.publicJwkToBytes(keyEncryptionInput.publicKey);
941
- const keyEncryptionOutput = await Encryption.eciesSecp256k1Encrypt(publicKeyBytes, encryptionInput.key);
942
-
943
- const encryptedKey = Encoder.bytesToBase64Url(keyEncryptionOutput.ciphertext);
944
- const ephemeralPublicKey = await Secp256k1.publicKeyToJwk(keyEncryptionOutput.ephemeralPublicKey);
945
- const keyEncryptionInitializationVector = Encoder.bytesToBase64Url(keyEncryptionOutput.initializationVector);
946
- const messageAuthenticationCode = Encoder.bytesToBase64Url(keyEncryptionOutput.messageAuthenticationCode);
947
- const encryptedKeyData: EncryptedKey = {
948
- rootKeyId : keyEncryptionInput.publicKeyId,
949
- algorithm : keyEncryptionInput.algorithm ?? EncryptionAlgorithm.EciesSecp256k1,
950
- derivationScheme : keyEncryptionInput.derivationScheme,
951
- ephemeralPublicKey,
952
- initializationVector : keyEncryptionInitializationVector,
953
- messageAuthenticationCode,
954
- encryptedKey
955
- };
956
-
957
- // we need to attach the actual public key if derivation scheme is protocol-context,
958
- // so that the responder to this message is able to encrypt the message/symmetric key using the same protocol-context derived public key,
959
- // without needing the knowledge of the corresponding private key
960
- if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.ProtocolContext) {
961
- encryptedKeyData.derivedPublicKey = keyEncryptionInput.publicKey;
962
- }
963
-
964
- keyEncryption.push(encryptedKeyData);
965
896
  }
966
897
 
967
- const encryption: EncryptionProperty = {
968
- algorithm : encryptionInput.algorithm ?? EncryptionAlgorithm.Aes256Ctr,
969
- initializationVector : Encoder.bytesToBase64Url(encryptionInput.initializationVector),
970
- keyEncryption
971
- };
898
+ // Build the JWE structure. The authentication tag comes from the AEAD encryption of record data.
899
+ const jwe = await Encryption.buildJwe(encryptionInput, encryptionInput.authenticationTag);
972
900
 
973
- return encryption;
901
+ return jwe;
974
902
  }
975
903
 
976
904
  /**
@@ -996,7 +924,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
996
924
  contextId: string | undefined,
997
925
  descriptorCid: string,
998
926
  attestation: GeneralJws | undefined,
999
- encryption: EncryptionProperty | undefined,
927
+ encryption: JweEncryption | undefined,
1000
928
  signer: MessageSigner,
1001
929
  delegatedGrantId?: string,
1002
930
  permissionGrantId?: string,
@@ -3,6 +3,7 @@ import type { GeneralJws } from '../../../types/jws-types.js';
3
3
  import type { PublicKeyJwk } from '../../../types/jose-types.js';
4
4
  import type { DidResolver, DidVerificationMethod } from '@enbox/dids';
5
5
 
6
+ import { Encoder } from '../../../utils/encoder.js';
6
7
  import { Jws } from '../../../utils/jws.js';
7
8
  import { MemoryCache } from '../../../utils/memory-cache.js';
8
9
  import { validateJsonSchema } from '../../../schema-validator.js';
@@ -51,7 +52,16 @@ export class GeneralJwsVerifier {
51
52
 
52
53
  for (const signatureEntry of jws.signatures) {
53
54
  let isVerified: boolean;
54
- const kid = Jws.getKid(signatureEntry);
55
+ const protectedHeader = Encoder.base64UrlToObject(signatureEntry.protected);
56
+ const { kid, alg } = protectedHeader;
57
+
58
+ if (kid === undefined || typeof kid !== 'string') {
59
+ throw new DwnError(DwnErrorCode.GeneralJwsVerifierMissingKid, `JWS protected header is missing required 'kid' property`);
60
+ }
61
+
62
+ if (alg === undefined || typeof alg !== 'string') {
63
+ throw new DwnError(DwnErrorCode.GeneralJwsVerifierMissingAlg, `JWS protected header is missing required 'alg' property`);
64
+ }
55
65
 
56
66
  const cacheKey = `${signatureEntry.protected}.${jws.payload}.${signatureEntry.signature}`;
57
67
  const cachedValue = await this.cache.get(cacheKey);
@@ -134,7 +134,7 @@ export function hashEquals(a: Hash, b: Hash): boolean {
134
134
  * Convert a hash to a hex string for use as a store key.
135
135
  */
136
136
  export function hashToHex(hash: Hash): string {
137
- return Buffer.from(hash).toString('hex');
137
+ return Array.from(hash, (b: number): string => b.toString(16).padStart(2, '0')).join('');
138
138
  }
139
139
 
140
140
  /**
@@ -1,4 +1,4 @@
1
- import type { EciesEncryptionOutput } from '../utils/encryption.js';
1
+ import type { JweKeyUnwrapPayload } from '../utils/encryption.js';
2
2
  import type { KeyDerivationScheme } from '../utils/hd-key.js';
3
3
  import type { PublicKeyJwk } from './jose-types.js';
4
4
 
@@ -26,8 +26,8 @@ export interface EncryptionKeyDeriver {
26
26
  }
27
27
 
28
28
  /**
29
- * A callback interface for decrypting ECIES-encrypted data encryption keys.
30
- * The implementor performs HKDF key derivation and ECIES decryption
29
+ * A callback interface for decrypting JWE-wrapped Content Encryption Keys (CEKs).
30
+ * The implementor performs HKDF key derivation, ECDH-ES key agreement, and AES Key Unwrap
31
31
  * internally — the private key never leaves the implementation boundary.
32
32
  *
33
33
  * Analogous to `MessageSigner` for signing operations.
@@ -38,15 +38,16 @@ export interface KeyDecrypter {
38
38
  /** The derivation scheme (e.g. KeyDerivationScheme.ProtocolPath) */
39
39
  derivationScheme: KeyDerivationScheme;
40
40
  /**
41
- * Decrypts an ECIES-SECP256K1 encrypted payload after deriving the
42
- * leaf decryption key via HKDF through the given derivation path.
41
+ * Unwraps a JWE-encrypted Content Encryption Key (CEK) after deriving the
42
+ * leaf decryption key via HKDF through the given derivation path, then
43
+ * performing ECDH-ES key agreement and AES-256 Key Unwrap.
43
44
  *
44
45
  * @param fullDerivationPath - The complete HKDF path to derive the leaf key
45
- * @param eciesEncryptedPayload - The ECIES ciphertext components
46
- * @returns The decrypted plaintext bytes (typically a 32-byte DEK)
46
+ * @param jweKeyUnwrapPayload - The wrapped CEK and ephemeral public key from the JWE recipient
47
+ * @returns The unwrapped CEK bytes (typically 32 bytes for AES-256)
47
48
  */
48
49
  decrypt(
49
50
  fullDerivationPath: string[],
50
- eciesEncryptedPayload: EciesEncryptionOutput,
51
+ jweKeyUnwrapPayload: JweKeyUnwrapPayload,
51
52
  ): Promise<Uint8Array>;
52
53
  }
@@ -49,7 +49,7 @@ export type ProtocolType = {
49
49
  /**
50
50
  * When `true`, records of this type **must** be encrypted at the DWN record
51
51
  * level using the tenant's ProtocolPath-derived encryption key. The tenant
52
- * DID must have a secp256k1 keyAgreement key; protocol installation will
52
+ * DID must have an X25519 keyAgreement key; protocol installation will
53
53
  * fail if it does not.
54
54
  *
55
55
  * When `false` or omitted, encryption is not required for this type.
@@ -105,9 +105,11 @@ export type ProtocolActionRule = {
105
105
  /**
106
106
  * May be 'anyone' | 'author' | 'recipient'.
107
107
  * If `who` === 'anyone', then `of` must be omitted. Otherwise `of` must be present.
108
- * Mutually exclusive with `role`
108
+ * Mutually exclusive with `role`.
109
+ *
110
+ * Accepts both enum values (`ProtocolActor.Anyone`) and string literals (`'anyone'`).
109
111
  */
110
- who?: string,
112
+ who?: ProtocolActor | `${ProtocolActor}` | (string & {});
111
113
 
112
114
  /**
113
115
  * The protocol path of a role record type marked with $role: true.
@@ -126,7 +128,7 @@ export type ProtocolActionRule = {
126
128
  * See {ProtocolAction} for possible values.
127
129
  * 'read' authorizes read, query, and subscribe access.
128
130
  */
129
- can: string[];
131
+ can: (ProtocolAction | `${ProtocolAction}` | (string & {}))[];
130
132
  };
131
133
  /**
132
134
  * Config for protocol-path encryption scheme.
@@ -144,6 +146,65 @@ export type ProtocolPathEncryption = {
144
146
  publicKeyJwk: PublicKeyJwk;
145
147
  };
146
148
 
149
+ /**
150
+ * Size constraints for records at a given protocol path.
151
+ */
152
+ export type ProtocolSizeDefinition = {
153
+ min?: number;
154
+ max?: number;
155
+ };
156
+
157
+ /**
158
+ * Tag rules for records at a given protocol path. Each non-`$`-prefixed property
159
+ * is a JSON Schema object constraining that tag's value.
160
+ */
161
+ export type ProtocolTagsDefinition = {
162
+ /** Array of tag names that must be present on every record. */
163
+ $requiredTags?: string[];
164
+ /** When `false` (default), only tags explicitly listed are allowed. */
165
+ $allowUndefinedTags?: boolean;
166
+ /** JSON Schema definitions for individual tags. */
167
+ [tag: string]: ProtocolTagSchema | string[] | boolean | undefined;
168
+ };
169
+
170
+ /**
171
+ * A JSON Schema object constraining a single tag value.
172
+ * Supports the subset of JSON Schema used by DWN tag validation.
173
+ */
174
+ export type ProtocolTagSchema = {
175
+ type: 'string' | 'number' | 'integer' | 'boolean' | 'array';
176
+ items?: { type: 'string' | 'number' | 'integer' };
177
+ contains?: { type: 'string' | 'number' | 'integer' };
178
+ enum?: (string | number | boolean)[];
179
+ minimum?: number;
180
+ maximum?: number;
181
+ exclusiveMinimum?: number;
182
+ exclusiveMaximum?: number;
183
+ minLength?: number;
184
+ maxLength?: number;
185
+ minItems?: number;
186
+ maxItems?: number;
187
+ uniqueItems?: boolean;
188
+ minContains?: number;
189
+ maxContains?: number;
190
+ };
191
+
192
+ /**
193
+ * Union of all value types that can appear as properties of a `ProtocolRuleSet`.
194
+ * This includes:
195
+ * - `$`-prefixed directive values (`$encryption`, `$actions`, `$role`, `$ref`, `$size`, `$tags`)
196
+ * - Child `ProtocolRuleSet` entries (non-`$` keys)
197
+ */
198
+ type ProtocolRuleSetValue =
199
+ | ProtocolRuleSet
200
+ | ProtocolActionRule[]
201
+ | ProtocolPathEncryption
202
+ | ProtocolTagsDefinition
203
+ | ProtocolSizeDefinition
204
+ | boolean
205
+ | string
206
+ | undefined;
207
+
147
208
  export type ProtocolRuleSet = {
148
209
  /**
149
210
  * Encryption setting for objects that are in this protocol path.
@@ -179,25 +240,18 @@ export type ProtocolRuleSet = {
179
240
  /**
180
241
  * If $size is set, the record size in bytes must be within the limits.
181
242
  */
182
- $size?: {
183
- min?: number,
184
- max?: number
185
- }
243
+ $size?: ProtocolSizeDefinition;
186
244
 
187
245
  /**
188
246
  * If $tags is set, the record must conform to the tag rules.
189
247
  */
190
- $tags?: {
191
- /** array of required tags */
192
- $requiredTags?: string[],
193
- /** allow properties other than those explicitly listed. defaults to false */
194
- $allowUndefinedTags?: boolean;
195
-
196
- [key: string]: any;
197
- }
248
+ $tags?: ProtocolTagsDefinition;
198
249
 
199
- // JSON Schema verifies that properties other than properties prefixed with $ will actually have type ProtocolRuleSet
200
- [key: string]: any;
250
+ /**
251
+ * Non-`$`-prefixed keys are nested child `ProtocolRuleSet` entries.
252
+ * At runtime, JSON Schema validation ensures only valid child rule sets appear here.
253
+ */
254
+ [key: string]: ProtocolRuleSetValue;
201
255
  };
202
256
 
203
257
  export type ProtocolsConfigureMessage = GenericMessage & {
@@ -1,7 +1,5 @@
1
- import type { EncryptionAlgorithm } from '../utils/encryption.js';
2
1
  import type { GeneralJws } from './jws-types.js';
3
- import type { KeyDerivationScheme } from '../utils/hd-key.js';
4
- import type { PublicKeyJwk } from './jose-types.js';
2
+ import type { JweEncryption } from '../utils/encryption.js';
5
3
  import type { AuthorizationModel, GenericMessage, GenericMessageReply, GenericSignaturePayload, MessageSubscription, Pagination } from './message-types.js';
6
4
  import type { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
7
5
  import type { PaginationCursor, RangeCriterion, RangeFilter, StartsWithFilter } from './query-types.js';
@@ -53,7 +51,7 @@ export type InternalRecordsWriteMessage = GenericMessage & {
53
51
  contextId?: string;
54
52
  descriptor: RecordsWriteDescriptor;
55
53
  attestation?: GeneralJws;
56
- encryption?: EncryptionProperty;
54
+ encryption?: JweEncryption;
57
55
  };
58
56
 
59
57
  export type RecordsWriteMessage = {
@@ -62,31 +60,7 @@ export type RecordsWriteMessage = {
62
60
  contextId?: string;
63
61
  descriptor: RecordsWriteDescriptor;
64
62
  attestation?: GeneralJws;
65
- encryption?: EncryptionProperty;
66
- };
67
-
68
- export type EncryptionProperty = {
69
- algorithm: EncryptionAlgorithm;
70
- initializationVector: string;
71
- keyEncryption: EncryptedKey[]
72
- };
73
-
74
- export type EncryptedKey = {
75
- /**
76
- * The fully qualified key ID (e.g. did:example:abc#encryption-key-id) of the root public key used to encrypt the symmetric encryption key.
77
- */
78
- rootKeyId: string;
79
-
80
- /**
81
- * The actual derived public key.
82
- */
83
- derivedPublicKey?: PublicKeyJwk;
84
- derivationScheme: KeyDerivationScheme;
85
- algorithm: EncryptionAlgorithm;
86
- initializationVector: string;
87
- ephemeralPublicKey: PublicKeyJwk;
88
- messageAuthenticationCode: string;
89
- encryptedKey: string;
63
+ encryption?: JweEncryption;
90
64
  };
91
65
 
92
66
  /**
@@ -146,6 +120,8 @@ export type RecordsSubscribeDescriptor = {
146
120
  method: DwnMethodName.Subscribe;
147
121
  messageTimestamp: string;
148
122
  filter: RecordsFilter;
123
+ dateSort?: DateSort;
124
+ pagination?: Pagination;
149
125
  };
150
126
 
151
127
  export type RecordsFilter = {
@@ -212,6 +188,8 @@ export type RecordsSubscribeMessage = GenericMessage & {
212
188
 
213
189
  export type RecordsSubscribeReply = GenericMessageReply & {
214
190
  subscription?: MessageSubscription;
191
+ entries?: RecordsQueryReplyEntry[];
192
+ cursor?: PaginationCursor;
215
193
  };
216
194
 
217
195
  export type RecordsReadMessage = {