@enbox/dwn-sdk-js 0.0.3 → 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.
- package/dist/browser.mjs +135 -0
- package/dist/browser.mjs.map +7 -0
- package/dist/esm/generated/precompiled-validators.js +640 -510
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/auth.js +6 -1
- package/dist/esm/src/core/auth.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +3 -0
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +4 -0
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/dwn.js +14 -0
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +13 -0
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +121 -66
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +1 -1
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +1 -0
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +2 -0
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +28 -45
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +9 -1
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/smt/smt-utils.js +1 -1
- package/dist/esm/src/smt/smt-utils.js.map +1 -1
- package/dist/esm/src/types/records-types.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +221 -78
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +6 -7
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +12 -10
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +33 -44
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +26 -21
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +5 -5
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +120 -2
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +25 -26
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +103 -0
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +124 -10
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-get.spec.js +3 -2
- package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +43 -34
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +4 -4
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +21 -24
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +69 -66
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/filters.spec.js +1 -0
- package/dist/esm/tests/utils/filters.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +28 -7
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/auth.d.ts +3 -1
- package/dist/types/src/core/auth.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +3 -0
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts +12 -0
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +17 -28
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +4 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-delete.d.ts +4 -0
- package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +4 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +23 -53
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -1
- package/dist/types/src/types/encryption-types.d.ts +9 -8
- package/dist/types/src/types/encryption-types.d.ts.map +1 -1
- package/dist/types/src/types/protocols-types.d.ts +65 -16
- package/dist/types/src/types/protocols-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +7 -26
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +157 -28
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/hd-key.d.ts +2 -3
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +3 -4
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +7 -0
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/package.json +10 -21
- package/src/core/auth.ts +12 -1
- package/src/core/dwn-error.ts +3 -0
- package/src/core/protocol-authorization.ts +8 -0
- package/src/dwn.ts +15 -0
- package/src/handlers/protocols-configure.ts +4 -4
- package/src/handlers/records-delete.ts +12 -0
- package/src/handlers/records-subscribe.ts +174 -75
- package/src/handlers/records-write.ts +1 -1
- package/src/index.ts +4 -4
- package/src/interfaces/protocols-configure.ts +5 -5
- package/src/interfaces/records-delete.ts +9 -3
- package/src/interfaces/records-subscribe.ts +6 -1
- package/src/interfaces/records-write.ts +33 -105
- package/src/jose/jws/general/verifier.ts +11 -1
- package/src/smt/smt-utils.ts +1 -1
- package/src/types/encryption-types.ts +9 -8
- package/src/types/protocols-types.ts +72 -18
- package/src/types/records-types.ts +7 -29
- package/src/utils/encryption.ts +346 -88
- package/src/utils/hd-key.ts +9 -10
- package/src/utils/protocols.ts +15 -13
- package/src/utils/records.ts +47 -55
- 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 `
|
|
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
|
|
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
|
|
463
|
+
'Cannot append recipients: record does not have an existing `encryption` property.'
|
|
517
464
|
);
|
|
518
465
|
}
|
|
519
466
|
|
|
520
|
-
// Build only the new
|
|
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.
|
|
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
|
-
//
|
|
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
|
|
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:
|
|
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
|
-
*
|
|
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<
|
|
875
|
+
encryptionInput: EncryptionInput | undefined,
|
|
876
|
+
): Promise<JweEncryption | undefined> {
|
|
916
877
|
if (encryptionInput === undefined) {
|
|
917
878
|
return undefined;
|
|
918
879
|
}
|
|
919
880
|
|
|
920
|
-
//
|
|
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
|
-
|
|
968
|
-
|
|
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
|
|
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:
|
|
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
|
|
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);
|
package/src/smt/smt-utils.ts
CHANGED
|
@@ -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
|
|
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 {
|
|
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
|
|
30
|
-
* The implementor performs HKDF key derivation and
|
|
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
|
-
*
|
|
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
|
|
46
|
-
* @returns The
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
200
|
-
|
|
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 {
|
|
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?:
|
|
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?:
|
|
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 = {
|