@enbox/agent 0.1.3 → 0.1.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 +45 -52
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/crypto-api.js +6 -13
- package/dist/esm/crypto-api.js.map +1 -1
- package/dist/esm/dwn-api.js +92 -81
- package/dist/esm/dwn-api.js.map +1 -1
- package/dist/esm/hd-identity-vault.js +4 -5
- package/dist/esm/hd-identity-vault.js.map +1 -1
- package/dist/esm/identity-api.js +1 -1
- package/dist/esm/identity-api.js.map +1 -1
- package/dist/esm/index.js +0 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/local-key-manager.js +31 -32
- package/dist/esm/local-key-manager.js.map +1 -1
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js +1 -2
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js.map +1 -1
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js +15 -4
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js.map +1 -1
- package/dist/esm/prototyping/crypto/jose/jwe.js +1 -1
- package/dist/esm/prototyping/crypto/jose/jwe.js.map +1 -1
- package/dist/esm/store-data.js +3 -3
- package/dist/esm/store-data.js.map +1 -1
- package/dist/esm/store-did.js +1 -1
- package/dist/esm/store-did.js.map +1 -1
- package/dist/esm/sync-engine-level.js +49 -11
- package/dist/esm/sync-engine-level.js.map +1 -1
- package/dist/esm/test-harness.js +24 -8
- package/dist/esm/test-harness.js.map +1 -1
- package/dist/esm/types/dwn.js +1 -1
- package/dist/esm/types/dwn.js.map +1 -1
- package/dist/esm/web5-user-agent.js +1 -1
- package/dist/esm/web5-user-agent.js.map +1 -1
- package/dist/types/crypto-api.d.ts +8 -12
- package/dist/types/crypto-api.d.ts.map +1 -1
- package/dist/types/dwn-api.d.ts +15 -10
- package/dist/types/dwn-api.d.ts.map +1 -1
- package/dist/types/hd-identity-vault.d.ts.map +1 -1
- package/dist/types/identity-api.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/local-key-manager.d.ts +15 -18
- package/dist/types/local-key-manager.d.ts.map +1 -1
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts +1 -3
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts.map +1 -1
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts +1 -3
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts.map +1 -1
- package/dist/types/prototyping/crypto/jose/jwe.d.ts +1 -3
- package/dist/types/prototyping/crypto/jose/jwe.d.ts.map +1 -1
- package/dist/types/store-data.d.ts +2 -2
- package/dist/types/store-did.d.ts.map +1 -1
- package/dist/types/sync-engine-level.d.ts +18 -6
- package/dist/types/sync-engine-level.d.ts.map +1 -1
- package/dist/types/test-harness.d.ts.map +1 -1
- package/dist/types/types/agent.d.ts +1 -1
- package/dist/types/types/agent.d.ts.map +1 -1
- package/dist/types/types/dwn.d.ts +2 -2
- package/dist/types/types/dwn.d.ts.map +1 -1
- package/dist/types/types/key-manager.d.ts +15 -22
- package/dist/types/types/key-manager.d.ts.map +1 -1
- package/dist/types/utils-internal.d.ts +1 -1
- package/dist/types/utils-internal.d.ts.map +1 -1
- package/dist/types/web5-user-agent.d.ts +1 -1
- package/dist/types/web5-user-agent.d.ts.map +1 -1
- package/package.json +12 -14
- package/src/crypto-api.ts +24 -20
- package/src/dwn-api.ts +123 -105
- package/src/hd-identity-vault.ts +4 -5
- package/src/identity-api.ts +2 -1
- package/src/index.ts +0 -2
- package/src/local-key-manager.ts +43 -44
- package/src/prototyping/crypto/jose/jwe-compact.ts +3 -7
- package/src/prototyping/crypto/jose/jwe-flattened.ts +20 -9
- package/src/prototyping/crypto/jose/jwe.ts +2 -6
- package/src/store-data.ts +3 -3
- package/src/store-did.ts +1 -1
- package/src/sync-engine-level.ts +59 -16
- package/src/test-harness.ts +23 -8
- package/src/types/agent.ts +1 -1
- package/src/types/dwn.ts +2 -2
- package/src/types/key-manager.ts +31 -22
- package/src/utils-internal.ts +1 -1
- package/src/web5-user-agent.ts +2 -2
- package/dist/browser.js +0 -2213
- package/dist/browser.js.map +0 -7
- package/dist/esm/dwn-registrar.js +0 -120
- package/dist/esm/dwn-registrar.js.map +0 -1
- package/dist/esm/prototyping/clients/dwn-rpc-types.js +0 -2
- package/dist/esm/prototyping/clients/dwn-rpc-types.js.map +0 -1
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js +0 -74
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js.map +0 -1
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js +0 -112
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js.map +0 -1
- package/dist/esm/prototyping/clients/json-rpc-socket.js +0 -167
- package/dist/esm/prototyping/clients/json-rpc-socket.js.map +0 -1
- package/dist/esm/prototyping/clients/json-rpc.js +0 -58
- package/dist/esm/prototyping/clients/json-rpc.js.map +0 -1
- package/dist/esm/prototyping/clients/server-info-types.js +0 -2
- package/dist/esm/prototyping/clients/server-info-types.js.map +0 -1
- package/dist/esm/prototyping/clients/web-socket-clients.js +0 -90
- package/dist/esm/prototyping/clients/web-socket-clients.js.map +0 -1
- package/dist/esm/prototyping/common/object.js +0 -14
- package/dist/esm/prototyping/common/object.js.map +0 -1
- package/dist/esm/prototyping/common/type-utils.js +0 -2
- package/dist/esm/prototyping/common/type-utils.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js +0 -147
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js +0 -136
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js +0 -311
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js +0 -268
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js +0 -38
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js.map +0 -1
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js +0 -40
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js.map +0 -1
- package/dist/esm/prototyping/crypto/crypto-error.js +0 -41
- package/dist/esm/prototyping/crypto/crypto-error.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/crypto-api.js +0 -2
- package/dist/esm/prototyping/crypto/types/crypto-api.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/key-converter.js +0 -2
- package/dist/esm/prototyping/crypto/types/key-converter.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/key-deriver.js +0 -2
- package/dist/esm/prototyping/crypto/types/key-deriver.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/key-io.js +0 -2
- package/dist/esm/prototyping/crypto/types/key-io.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/key-manager.js +0 -2
- package/dist/esm/prototyping/crypto/types/key-manager.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/params-direct.js +0 -2
- package/dist/esm/prototyping/crypto/types/params-direct.js.map +0 -1
- package/dist/esm/prototyping/crypto/types/params-kms.js +0 -2
- package/dist/esm/prototyping/crypto/types/params-kms.js.map +0 -1
- package/dist/esm/prototyping/crypto/utils.js +0 -19
- package/dist/esm/prototyping/crypto/utils.js.map +0 -1
- package/dist/esm/prototyping/dids/resolver-cache-memory.js +0 -77
- package/dist/esm/prototyping/dids/resolver-cache-memory.js.map +0 -1
- package/dist/esm/prototyping/dids/utils.js +0 -9
- package/dist/esm/prototyping/dids/utils.js.map +0 -1
- package/dist/esm/rpc-client.js +0 -123
- package/dist/esm/rpc-client.js.map +0 -1
- package/dist/types/dwn-registrar.d.ts +0 -29
- package/dist/types/dwn-registrar.d.ts.map +0 -1
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts +0 -45
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts.map +0 -1
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts +0 -57
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts.map +0 -1
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts +0 -13
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts.map +0 -1
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts +0 -43
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts.map +0 -1
- package/dist/types/prototyping/clients/json-rpc.d.ts +0 -49
- package/dist/types/prototyping/clients/json-rpc.d.ts.map +0 -1
- package/dist/types/prototyping/clients/server-info-types.d.ts +0 -20
- package/dist/types/prototyping/clients/server-info-types.d.ts.map +0 -1
- package/dist/types/prototyping/clients/web-socket-clients.d.ts +0 -10
- package/dist/types/prototyping/clients/web-socket-clients.d.ts.map +0 -1
- package/dist/types/prototyping/common/object.d.ts +0 -2
- package/dist/types/prototyping/common/object.d.ts.map +0 -1
- package/dist/types/prototyping/common/type-utils.d.ts +0 -7
- package/dist/types/prototyping/common/type-utils.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts +0 -151
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts +0 -108
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts +0 -160
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts +0 -157
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts +0 -20
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts +0 -20
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/crypto-error.d.ts +0 -29
- package/dist/types/prototyping/crypto/crypto-error.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts +0 -34
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/key-converter.d.ts +0 -49
- package/dist/types/prototyping/crypto/types/key-converter.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts +0 -50
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/key-io.d.ts +0 -49
- package/dist/types/prototyping/crypto/types/key-io.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/key-manager.d.ts +0 -69
- package/dist/types/prototyping/crypto/types/key-manager.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/params-direct.d.ts +0 -75
- package/dist/types/prototyping/crypto/types/params-direct.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/types/params-kms.d.ts +0 -63
- package/dist/types/prototyping/crypto/types/params-kms.d.ts.map +0 -1
- package/dist/types/prototyping/crypto/utils.d.ts +0 -7
- package/dist/types/prototyping/crypto/utils.d.ts.map +0 -1
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts +0 -57
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts.map +0 -1
- package/dist/types/prototyping/dids/utils.d.ts +0 -3
- package/dist/types/prototyping/dids/utils.d.ts.map +0 -1
- package/dist/types/rpc-client.d.ts +0 -51
- package/dist/types/rpc-client.d.ts.map +0 -1
- package/src/dwn-registrar.ts +0 -127
- package/src/prototyping/clients/dwn-rpc-types.ts +0 -55
- package/src/prototyping/clients/dwn-server-info-cache-memory.ts +0 -79
- package/src/prototyping/clients/http-dwn-rpc-client.ts +0 -119
- package/src/prototyping/clients/json-rpc-socket.ts +0 -189
- package/src/prototyping/clients/json-rpc.ts +0 -113
- package/src/prototyping/clients/server-info-types.ts +0 -21
- package/src/prototyping/clients/web-socket-clients.ts +0 -103
- package/src/prototyping/common/object.ts +0 -15
- package/src/prototyping/common/type-utils.ts +0 -6
- package/src/prototyping/crypto/algorithms/aes-gcm.ts +0 -211
- package/src/prototyping/crypto/algorithms/aes-kw.ts +0 -160
- package/src/prototyping/crypto/algorithms/ecdsa.ts +0 -366
- package/src/prototyping/crypto/algorithms/eddsa.ts +0 -311
- package/src/prototyping/crypto/algorithms/hkdf.ts +0 -38
- package/src/prototyping/crypto/algorithms/pbkdf2.ts +0 -41
- package/src/prototyping/crypto/crypto-error.ts +0 -45
- package/src/prototyping/crypto/types/crypto-api.ts +0 -77
- package/src/prototyping/crypto/types/key-converter.ts +0 -53
- package/src/prototyping/crypto/types/key-deriver.ts +0 -56
- package/src/prototyping/crypto/types/key-io.ts +0 -51
- package/src/prototyping/crypto/types/key-manager.ts +0 -83
- package/src/prototyping/crypto/types/params-direct.ts +0 -95
- package/src/prototyping/crypto/types/params-kms.ts +0 -76
- package/src/prototyping/crypto/utils.ts +0 -41
- package/src/prototyping/dids/resolver-cache-memory.ts +0 -83
- package/src/prototyping/dids/utils.ts +0 -10
- package/src/rpc-client.ts +0 -160
package/src/dwn-api.ts
CHANGED
|
@@ -3,10 +3,8 @@ import type {
|
|
|
3
3
|
DwnConfig,
|
|
4
4
|
EncryptionInput,
|
|
5
5
|
EncryptionKeyDeriver,
|
|
6
|
-
EventStream,
|
|
7
6
|
GenericMessage,
|
|
8
7
|
KeyDecrypter,
|
|
9
|
-
MessageStore,
|
|
10
8
|
ProtocolDefinition,
|
|
11
9
|
ProtocolRuleSet,
|
|
12
10
|
ProtocolsQueryReply,
|
|
@@ -14,14 +12,13 @@ import type {
|
|
|
14
12
|
RecordsQueryReplyEntry,
|
|
15
13
|
RecordsReadReply,
|
|
16
14
|
RecordsWrite,
|
|
17
|
-
RecordsWriteMessage
|
|
18
|
-
StateIndex } from '@enbox/dwn-sdk-js';
|
|
15
|
+
RecordsWriteMessage } from '@enbox/dwn-sdk-js';
|
|
19
16
|
import type { KeyIdentifier, PrivateKeyJwk, PublicKeyJwk } from '@enbox/crypto';
|
|
20
17
|
|
|
21
|
-
import { CryptoUtils } from '@enbox/crypto';
|
|
22
18
|
import { TtlCache } from '@enbox/common';
|
|
23
19
|
import {
|
|
24
20
|
Cid,
|
|
21
|
+
ContentEncryptionAlgorithm,
|
|
25
22
|
DataStoreLevel,
|
|
26
23
|
DataStream,
|
|
27
24
|
Dwn,
|
|
@@ -37,9 +34,9 @@ import {
|
|
|
37
34
|
Protocols,
|
|
38
35
|
Records,
|
|
39
36
|
ResumableTaskStoreLevel,
|
|
40
|
-
Secp256k1,
|
|
41
37
|
StateIndexLevel
|
|
42
38
|
} from '@enbox/dwn-sdk-js';
|
|
39
|
+
import { CryptoUtils, X25519 } from '@enbox/crypto';
|
|
43
40
|
import { DidDht, DidJwk, DidResolverCacheLevel, UniversalResolver } from '@enbox/dids';
|
|
44
41
|
|
|
45
42
|
import type { Web5PlatformAgent } from './types/agent.js';
|
|
@@ -253,7 +250,7 @@ export class AgentDwnApi {
|
|
|
253
250
|
|
|
254
251
|
// Reactive root-record upgrade (PR E): if this is an externally-authored
|
|
255
252
|
// root record with only ProtocolPath encryption, the owner upgrades it by
|
|
256
|
-
// appending a ProtocolContext
|
|
253
|
+
// appending a ProtocolContext recipient entry so that context key
|
|
257
254
|
// holders (including the external author) can also decrypt.
|
|
258
255
|
const authorDid = Jws.getSignerDid(
|
|
259
256
|
recordsWriteMessage.authorization.signature.signatures[0]
|
|
@@ -299,7 +296,7 @@ export class AgentDwnApi {
|
|
|
299
296
|
derivationPath: contextDerivationPath,
|
|
300
297
|
});
|
|
301
298
|
const contextDerivedPrivateJwk =
|
|
302
|
-
await
|
|
299
|
+
await X25519.bytesToPrivateKey({ privateKeyBytes: contextDerivedPrivateKeyBytes });
|
|
303
300
|
const contextKeyPayload: DerivedPrivateJwk = {
|
|
304
301
|
rootKeyId : keyId,
|
|
305
302
|
derivationScheme : KeyDerivationScheme.ProtocolContext,
|
|
@@ -556,7 +553,7 @@ export class AgentDwnApi {
|
|
|
556
553
|
// For cross-DWN writes (target !== author), the external author cannot
|
|
557
554
|
// derive the target's context key. Root records use the target's ProtocolPath
|
|
558
555
|
// public key. The target's agent reactively upgrades the record to include a
|
|
559
|
-
// ProtocolContext
|
|
556
|
+
// ProtocolContext recipient entry. Non-root records extract the context
|
|
560
557
|
// public key (derivedPublicKey) from existing ProtocolContext-encrypted records
|
|
561
558
|
// in the same context on the target's DWN.
|
|
562
559
|
|
|
@@ -578,6 +575,7 @@ export class AgentDwnApi {
|
|
|
578
575
|
dataEncryptionKey: Uint8Array;
|
|
579
576
|
dataEncryptionIV: Uint8Array;
|
|
580
577
|
encryptedBytes: Uint8Array;
|
|
578
|
+
authenticationTag: Uint8Array;
|
|
581
579
|
} | undefined;
|
|
582
580
|
|
|
583
581
|
if (isDwnRequest(request, DwnInterface.RecordsWrite) && request.encryption && !rawMessage) {
|
|
@@ -649,14 +647,15 @@ export class AgentDwnApi {
|
|
|
649
647
|
throw new Error('AgentDwnApi: Data must be provided for encrypted records.');
|
|
650
648
|
}
|
|
651
649
|
|
|
652
|
-
// 5. Generate random DEK and IV
|
|
650
|
+
// 5. Generate random DEK and IV (IV size depends on content encryption algorithm)
|
|
651
|
+
const contentEncryptionAlgorithm = ContentEncryptionAlgorithm.A256GCM;
|
|
653
652
|
const dataEncryptionKey = crypto.getRandomValues(new Uint8Array(32));
|
|
654
|
-
const dataEncryptionIV = crypto.getRandomValues(new Uint8Array(
|
|
653
|
+
const dataEncryptionIV = crypto.getRandomValues(new Uint8Array(AgentDwnApi.ivLength(contentEncryptionAlgorithm)));
|
|
655
654
|
|
|
656
|
-
// 6. Build EncryptionInput
|
|
657
|
-
let encryptionInput: EncryptionInput | undefined;
|
|
655
|
+
// 6. Build partial EncryptionInput (authenticationTag added after AEAD encryption)
|
|
656
|
+
let encryptionInput: (Omit<EncryptionInput, 'authenticationTag'> & { authenticationTag?: Uint8Array }) | undefined;
|
|
658
657
|
|
|
659
|
-
const buildProtocolPathInput = (): EncryptionInput => this.buildEncryptionInput(
|
|
658
|
+
const buildProtocolPathInput = (): Omit<EncryptionInput, 'authenticationTag'> => this.buildEncryptionInput(
|
|
660
659
|
dataEncryptionKey, dataEncryptionIV,
|
|
661
660
|
ruleSet.$encryption.rootKeyId, ruleSet.$encryption.publicKeyJwk,
|
|
662
661
|
KeyDerivationScheme.ProtocolPath,
|
|
@@ -667,7 +666,7 @@ export class AgentDwnApi {
|
|
|
667
666
|
// External authors cannot derive the target's context key (HKDF requires
|
|
668
667
|
// the private key). Use the target's ProtocolPath public key from their
|
|
669
668
|
// protocol definition. The target's agent will reactively upgrade the record
|
|
670
|
-
// to include a ProtocolContext
|
|
669
|
+
// to include a ProtocolContext recipient entry.
|
|
671
670
|
encryptionInput = buildProtocolPathInput();
|
|
672
671
|
|
|
673
672
|
} else if (isCrossDwn && isMultiPartyContext && !isRootRecord) {
|
|
@@ -733,9 +732,9 @@ export class AgentDwnApi {
|
|
|
733
732
|
encryptionInput = buildProtocolPathInput();
|
|
734
733
|
}
|
|
735
734
|
|
|
736
|
-
// 7. Encrypt data with
|
|
737
|
-
const { encryptedBytes, dataCid, dataSize } =
|
|
738
|
-
await this.encryptAndComputeCid(plaintextBytes, dataEncryptionKey, dataEncryptionIV);
|
|
735
|
+
// 7. Encrypt data with AEAD and compute CID
|
|
736
|
+
const { encryptedBytes, dataCid, dataSize, authenticationTag } =
|
|
737
|
+
await this.encryptAndComputeCid(plaintextBytes, dataEncryptionKey, dataEncryptionIV, contentEncryptionAlgorithm);
|
|
739
738
|
|
|
740
739
|
// 8. Replace plaintext with encrypted data
|
|
741
740
|
messageParams.dataCid = dataCid;
|
|
@@ -745,10 +744,11 @@ export class AgentDwnApi {
|
|
|
745
744
|
request.dataStream = undefined;
|
|
746
745
|
|
|
747
746
|
if (encryptionInput) {
|
|
748
|
-
|
|
747
|
+
encryptionInput.authenticationTag = authenticationTag;
|
|
748
|
+
messageParams.encryptionInput = encryptionInput as EncryptionInput;
|
|
749
749
|
} else {
|
|
750
750
|
// Deferred — store info for post-creation encryption
|
|
751
|
-
deferredContextEncryption = { dataEncryptionKey, dataEncryptionIV, encryptedBytes };
|
|
751
|
+
deferredContextEncryption = { dataEncryptionKey, dataEncryptionIV, encryptedBytes, authenticationTag };
|
|
752
752
|
}
|
|
753
753
|
|
|
754
754
|
// 9. For cross-DWN writes in multi-party contexts, attach the author's
|
|
@@ -806,7 +806,8 @@ export class AgentDwnApi {
|
|
|
806
806
|
deferredContextEncryption.dataEncryptionIV,
|
|
807
807
|
);
|
|
808
808
|
|
|
809
|
-
|
|
809
|
+
const fullContextInput = { ...contextEncryptionInput, authenticationTag: deferredContextEncryption.authenticationTag };
|
|
810
|
+
await recordsWriteInstance.encryptSymmetricEncryptionKey(fullContextInput as EncryptionInput);
|
|
810
811
|
await recordsWriteInstance.sign({ signer });
|
|
811
812
|
|
|
812
813
|
// Cache context key info for subsequent writes in this context
|
|
@@ -893,7 +894,7 @@ export class AgentDwnApi {
|
|
|
893
894
|
* @param didUri - The DID URI to resolve encryption key info for
|
|
894
895
|
* @returns keyId (fully qualified verification method ID), keyUri (KMS reference),
|
|
895
896
|
* and publicKeyJwk. No private key material is returned.
|
|
896
|
-
* @throws If the DID has no keyAgreement verification method or it's not
|
|
897
|
+
* @throws If the DID has no keyAgreement verification method or it's not X25519.
|
|
897
898
|
*/
|
|
898
899
|
private async getEncryptionKeyInfo(didUri: string): Promise<{
|
|
899
900
|
keyId: string;
|
|
@@ -914,7 +915,7 @@ export class AgentDwnApi {
|
|
|
914
915
|
if (!keyAgreementRefs || keyAgreementRefs.length === 0) {
|
|
915
916
|
throw new Error(
|
|
916
917
|
`AgentDwnApi: DID '${didUri}' does not have a keyAgreement ` +
|
|
917
|
-
`verification method. Create the identity with
|
|
918
|
+
`verification method. Create the identity with an X25519 key ` +
|
|
918
919
|
`with keyAgreement purpose to use protocol encryption.`
|
|
919
920
|
);
|
|
920
921
|
}
|
|
@@ -940,12 +941,12 @@ export class AgentDwnApi {
|
|
|
940
941
|
);
|
|
941
942
|
}
|
|
942
943
|
|
|
943
|
-
// 4. Verify it's
|
|
944
|
+
// 4. Verify it's an X25519 key
|
|
944
945
|
const publicKeyJwk = verificationMethod.publicKeyJwk;
|
|
945
|
-
if (publicKeyJwk.crv !== '
|
|
946
|
+
if (publicKeyJwk.crv !== 'X25519') {
|
|
946
947
|
throw new Error(
|
|
947
948
|
`AgentDwnApi: keyAgreement key for '${didUri}' uses curve ` +
|
|
948
|
-
`'${publicKeyJwk.crv}', but DWN encryption requires '
|
|
949
|
+
`'${publicKeyJwk.crv}', but DWN encryption requires 'X25519'.`
|
|
949
950
|
);
|
|
950
951
|
}
|
|
951
952
|
|
|
@@ -960,17 +961,25 @@ export class AgentDwnApi {
|
|
|
960
961
|
}
|
|
961
962
|
|
|
962
963
|
/**
|
|
963
|
-
* Builds
|
|
964
|
-
*
|
|
965
|
-
*
|
|
964
|
+
* Builds a partial EncryptionInput object for a single key-encryption entry.
|
|
965
|
+
* The `authenticationTag` is NOT set here — the caller must set it after
|
|
966
|
+
* AEAD encryption produces the tag.
|
|
966
967
|
*/
|
|
968
|
+
/**
|
|
969
|
+
* Returns the correct nonce/IV byte length for the given content encryption algorithm.
|
|
970
|
+
* A256GCM uses 96-bit (12-byte) nonces; XC20P uses 192-bit (24-byte) nonces.
|
|
971
|
+
*/
|
|
972
|
+
private static ivLength(algorithm: ContentEncryptionAlgorithm): number {
|
|
973
|
+
return algorithm === ContentEncryptionAlgorithm.XC20P ? 24 : 12;
|
|
974
|
+
}
|
|
975
|
+
|
|
967
976
|
private buildEncryptionInput(
|
|
968
977
|
dek: Uint8Array,
|
|
969
978
|
iv: Uint8Array,
|
|
970
979
|
publicKeyId: string,
|
|
971
980
|
publicKey: PublicKeyJwk,
|
|
972
981
|
derivationScheme: typeof KeyDerivationScheme.ProtocolPath | typeof KeyDerivationScheme.ProtocolContext,
|
|
973
|
-
): EncryptionInput {
|
|
982
|
+
): Omit<EncryptionInput, 'authenticationTag'> {
|
|
974
983
|
return {
|
|
975
984
|
initializationVector : iv,
|
|
976
985
|
key : dek,
|
|
@@ -983,21 +992,23 @@ export class AgentDwnApi {
|
|
|
983
992
|
}
|
|
984
993
|
|
|
985
994
|
/**
|
|
986
|
-
* Encrypts plaintext bytes with
|
|
987
|
-
*
|
|
988
|
-
*
|
|
995
|
+
* Encrypts plaintext bytes with AEAD and computes the CID of the resulting ciphertext.
|
|
996
|
+
* Returns everything needed to attach the encrypted data to a DWN message, including
|
|
997
|
+
* the authentication tag.
|
|
989
998
|
*/
|
|
990
999
|
private async encryptAndComputeCid(
|
|
991
1000
|
plaintextBytes: Uint8Array,
|
|
992
1001
|
dek: Uint8Array,
|
|
993
1002
|
iv: Uint8Array,
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const
|
|
997
|
-
|
|
1003
|
+
algorithm: ContentEncryptionAlgorithm = ContentEncryptionAlgorithm.A256GCM,
|
|
1004
|
+
): Promise<{ encryptedBytes: Uint8Array; dataCid: string; dataSize: number; authenticationTag: Uint8Array }> {
|
|
1005
|
+
const { ciphertextStream, tag: authenticationTag } = await Encryption.aeadEncryptStream(
|
|
1006
|
+
algorithm, dek, iv, DataStream.fromBytes(plaintextBytes),
|
|
1007
|
+
);
|
|
1008
|
+
const encryptedBytes = await DataStream.toBytes(ciphertextStream);
|
|
998
1009
|
const cidStream = DataStream.fromBytes(encryptedBytes);
|
|
999
1010
|
const dataCid = await Cid.computeDagPbCidFromStream(cidStream);
|
|
1000
|
-
return { encryptedBytes, dataCid, dataSize: encryptedBytes.length };
|
|
1011
|
+
return { encryptedBytes, dataCid, dataSize: encryptedBytes.length, authenticationTag };
|
|
1001
1012
|
}
|
|
1002
1013
|
|
|
1003
1014
|
/**
|
|
@@ -1011,7 +1022,7 @@ export class AgentDwnApi {
|
|
|
1011
1022
|
contextId: string,
|
|
1012
1023
|
dek: Uint8Array,
|
|
1013
1024
|
iv: Uint8Array,
|
|
1014
|
-
): Promise<{ encryptionInput: EncryptionInput
|
|
1025
|
+
): Promise<{ encryptionInput: Omit<EncryptionInput, 'authenticationTag'>; keyId: string; keyUri: KeyIdentifier; contextDerivationPath: string[] }> {
|
|
1015
1026
|
const { keyId, keyUri } = await this.getEncryptionKeyInfo(didUri);
|
|
1016
1027
|
const contextDerivationPath =
|
|
1017
1028
|
Records.constructKeyDerivationPathUsingProtocolContextScheme(contextId);
|
|
@@ -1028,7 +1039,7 @@ export class AgentDwnApi {
|
|
|
1028
1039
|
}
|
|
1029
1040
|
|
|
1030
1041
|
/**
|
|
1031
|
-
* Builds a KMS-backed
|
|
1042
|
+
* Builds a KMS-backed JWE key unwrap callback. Used for both ProtocolPath
|
|
1032
1043
|
* and ProtocolContext decryption where the KMS holds the root private key.
|
|
1033
1044
|
*/
|
|
1034
1045
|
private buildKmsDecryptCallback(
|
|
@@ -1040,14 +1051,12 @@ export class AgentDwnApi {
|
|
|
1040
1051
|
return {
|
|
1041
1052
|
rootKeyId : keyId,
|
|
1042
1053
|
derivationScheme,
|
|
1043
|
-
decrypt : async (fullDerivationPath,
|
|
1044
|
-
return keyManager.
|
|
1054
|
+
decrypt : async (fullDerivationPath, jwePayload): Promise<Uint8Array> => {
|
|
1055
|
+
return keyManager.jweKeyUnwrap({
|
|
1045
1056
|
keyUri,
|
|
1046
|
-
derivationPath
|
|
1047
|
-
|
|
1048
|
-
ephemeralPublicKey
|
|
1049
|
-
initializationVector : eciesPayload.initializationVector,
|
|
1050
|
-
messageAuthenticationCode : eciesPayload.messageAuthenticationCode,
|
|
1057
|
+
derivationPath : fullDerivationPath,
|
|
1058
|
+
encryptedKey : jwePayload.encryptedKey,
|
|
1059
|
+
ephemeralPublicKey : jwePayload.ephemeralPublicKey,
|
|
1051
1060
|
});
|
|
1052
1061
|
},
|
|
1053
1062
|
};
|
|
@@ -1384,18 +1393,18 @@ export class AgentDwnApi {
|
|
|
1384
1393
|
return undefined;
|
|
1385
1394
|
}
|
|
1386
1395
|
|
|
1387
|
-
// Search entries for one with a ProtocolContext
|
|
1396
|
+
// Search entries for one with a ProtocolContext recipient entry
|
|
1388
1397
|
// that includes derivedPublicKey
|
|
1389
1398
|
for (const entry of queryReply.entries) {
|
|
1390
|
-
if (entry.encryption?.
|
|
1391
|
-
const contextEntry = entry.encryption.
|
|
1392
|
-
(
|
|
1393
|
-
|
|
1399
|
+
if (entry.encryption?.recipients) {
|
|
1400
|
+
const contextEntry = entry.encryption.recipients.find(
|
|
1401
|
+
(r: { header: { derivationScheme: string; derivedPublicKey?: PublicKeyJwk } }) =>
|
|
1402
|
+
r.header.derivationScheme === KeyDerivationScheme.ProtocolContext && r.header.derivedPublicKey
|
|
1394
1403
|
);
|
|
1395
|
-
if (contextEntry?.derivedPublicKey) {
|
|
1404
|
+
if (contextEntry?.header.derivedPublicKey) {
|
|
1396
1405
|
return {
|
|
1397
|
-
rootKeyId : contextEntry.
|
|
1398
|
-
derivedPublicKey : contextEntry.derivedPublicKey,
|
|
1406
|
+
rootKeyId : contextEntry.header.kid,
|
|
1407
|
+
derivedPublicKey : contextEntry.header.derivedPublicKey,
|
|
1399
1408
|
};
|
|
1400
1409
|
}
|
|
1401
1410
|
}
|
|
@@ -1406,7 +1415,7 @@ export class AgentDwnApi {
|
|
|
1406
1415
|
|
|
1407
1416
|
/**
|
|
1408
1417
|
* Reactively upgrades an externally-authored root record that has only
|
|
1409
|
-
* ProtocolPath encryption by appending a ProtocolContext
|
|
1418
|
+
* ProtocolPath encryption by appending a ProtocolContext recipient entry.
|
|
1410
1419
|
*
|
|
1411
1420
|
* After the upgrade, both the owner (ProtocolPath) and context key holders —
|
|
1412
1421
|
* including the external author (ProtocolContext) — can decrypt the record.
|
|
@@ -1415,7 +1424,7 @@ export class AgentDwnApi {
|
|
|
1415
1424
|
* 1. Decrypt the DEK using the owner's ProtocolPath-derived private key
|
|
1416
1425
|
* 2. Derive the context public key from the owner's #enc key
|
|
1417
1426
|
* 3. ECIES-encrypt the same DEK to the context public key
|
|
1418
|
-
* 4. Append the ProtocolContext
|
|
1427
|
+
* 4. Append the ProtocolContext recipient entry (using PR 0b append mode)
|
|
1419
1428
|
* 5. Re-sign the record as owner
|
|
1420
1429
|
*
|
|
1421
1430
|
* The author's signature payload includes an `encryptionCid` that becomes
|
|
@@ -1441,20 +1450,20 @@ export class AgentDwnApi {
|
|
|
1441
1450
|
if (!encryption) { return; }
|
|
1442
1451
|
|
|
1443
1452
|
// Verify: has ProtocolPath but NOT ProtocolContext
|
|
1444
|
-
const hasProtocolPath = encryption.
|
|
1445
|
-
(
|
|
1453
|
+
const hasProtocolPath = encryption.recipients.some(
|
|
1454
|
+
(r: { header: { derivationScheme: string } }) => r.header.derivationScheme === KeyDerivationScheme.ProtocolPath
|
|
1446
1455
|
);
|
|
1447
|
-
const hasProtocolContext = encryption.
|
|
1448
|
-
(
|
|
1456
|
+
const hasProtocolContext = encryption.recipients.some(
|
|
1457
|
+
(r: { header: { derivationScheme: string } }) => r.header.derivationScheme === KeyDerivationScheme.ProtocolContext
|
|
1449
1458
|
);
|
|
1450
1459
|
if (!hasProtocolPath || hasProtocolContext) { return; }
|
|
1451
1460
|
|
|
1452
1461
|
// 1. Decrypt the DEK using the owner's ProtocolPath key
|
|
1453
1462
|
const keyDecrypter = await this.getKeyDecrypter(tenantDid);
|
|
1454
1463
|
|
|
1455
|
-
// Find the ProtocolPath
|
|
1456
|
-
const
|
|
1457
|
-
(
|
|
1464
|
+
// Find the ProtocolPath recipient entry
|
|
1465
|
+
const pathRecipient = encryption.recipients.find(
|
|
1466
|
+
(r: { header: { derivationScheme: string } }) => r.header.derivationScheme === KeyDerivationScheme.ProtocolPath
|
|
1458
1467
|
)!;
|
|
1459
1468
|
|
|
1460
1469
|
const fullDerivationPath = Records.constructKeyDerivationPathUsingProtocolPathScheme(
|
|
@@ -1464,30 +1473,31 @@ export class AgentDwnApi {
|
|
|
1464
1473
|
const dataEncryptionKey = await keyDecrypter.decrypt(
|
|
1465
1474
|
fullDerivationPath,
|
|
1466
1475
|
{
|
|
1467
|
-
|
|
1468
|
-
ephemeralPublicKey
|
|
1469
|
-
initializationVector : Encoder.base64UrlToBytes(pathEntry.initializationVector),
|
|
1470
|
-
messageAuthenticationCode : Encoder.base64UrlToBytes(pathEntry.messageAuthenticationCode),
|
|
1476
|
+
encryptedKey : Encoder.base64UrlToBytes(pathRecipient.encrypted_key),
|
|
1477
|
+
ephemeralPublicKey : pathRecipient.header.epk,
|
|
1471
1478
|
},
|
|
1472
1479
|
);
|
|
1473
1480
|
|
|
1474
1481
|
// 2. Derive the context public key — contextId = recordId for root records
|
|
1475
1482
|
const contextId = recordsWrite.recordId;
|
|
1476
|
-
const encryptionIV = Encoder.base64UrlToBytes(encryption.
|
|
1483
|
+
const encryptionIV = Encoder.base64UrlToBytes(encryption.iv);
|
|
1477
1484
|
|
|
1478
|
-
// 3 & 4. Append the ProtocolContext
|
|
1485
|
+
// 3 & 4. Append the ProtocolContext recipient entry using append mode.
|
|
1479
1486
|
// Append mode preserves the author's identity and authorization so that
|
|
1480
1487
|
// signAsOwner() can be called in step 5.
|
|
1481
1488
|
const { encryptionInput: contextEncryptionInput, keyId, keyUri, contextDerivationPath } =
|
|
1482
1489
|
await this.deriveContextEncryptionInput(tenantDid, contextId, dataEncryptionKey, encryptionIV);
|
|
1483
1490
|
|
|
1491
|
+
// Set the authentication tag from the existing JWE encryption property
|
|
1492
|
+
const fullContextInput = { ...contextEncryptionInput, authenticationTag: Encoder.base64UrlToBytes(encryption.tag) };
|
|
1493
|
+
|
|
1484
1494
|
// Parse the message to get a RecordsWrite instance we can mutate
|
|
1485
1495
|
const recordsWriteInstance = await dwnMessageConstructors[DwnInterface.RecordsWrite].parse(
|
|
1486
1496
|
recordsWrite,
|
|
1487
1497
|
) as unknown as RecordsWrite;
|
|
1488
1498
|
|
|
1489
1499
|
await recordsWriteInstance.encryptSymmetricEncryptionKey(
|
|
1490
|
-
|
|
1500
|
+
fullContextInput as EncryptionInput,
|
|
1491
1501
|
{ append: true },
|
|
1492
1502
|
);
|
|
1493
1503
|
|
|
@@ -1505,35 +1515,44 @@ export class AgentDwnApi {
|
|
|
1505
1515
|
// We must also update the state index and event stream to keep sync and
|
|
1506
1516
|
// real-time subscribers consistent — without this, the upgraded record
|
|
1507
1517
|
// would never propagate to remote DWNs or notify subscribers.
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1518
|
+
const { messageStore, stateIndex, eventStream } = this._dwn.storage;
|
|
1519
|
+
|
|
1520
|
+
// Validate the upgrade only changed encryption and authorization fields.
|
|
1521
|
+
// The descriptor, recordId, contextId, and data must remain identical.
|
|
1522
|
+
// Note: parse() may produce a new descriptor object, so we compare by value.
|
|
1523
|
+
const upgradedMessage = recordsWriteInstance.message as RecordsQueryReplyEntry;
|
|
1524
|
+
if (JSON.stringify(upgradedMessage.descriptor) !== JSON.stringify(recordsWrite.descriptor)) {
|
|
1525
|
+
throw new Error('AgentDwnApi: upgradeExternalRootRecord() must not modify the descriptor.');
|
|
1526
|
+
}
|
|
1527
|
+
if (upgradedMessage.recordId !== recordsWrite.recordId) {
|
|
1528
|
+
throw new Error('AgentDwnApi: upgradeExternalRootRecord() must not modify the recordId.');
|
|
1529
|
+
}
|
|
1512
1530
|
|
|
1513
1531
|
// Fetch the stored original (which carries encodedData for small payloads)
|
|
1514
1532
|
const originalCid = await Message.getCid(recordsWrite);
|
|
1515
1533
|
const storedOriginal = await messageStore.get(tenantDid, originalCid) as RecordsQueryReplyEntry | undefined;
|
|
1516
1534
|
|
|
1517
|
-
// Remove the original message and its state index entry
|
|
1518
|
-
await messageStore.delete(tenantDid, originalCid);
|
|
1519
|
-
await stateIndex.delete(tenantDid, [originalCid]);
|
|
1520
|
-
|
|
1521
1535
|
// Build indexes for the upgraded message (mark as latest base state)
|
|
1522
1536
|
const isLatestBaseState = true;
|
|
1523
1537
|
const upgradedIndexes = await recordsWriteInstance.constructIndexes(isLatestBaseState);
|
|
1524
1538
|
|
|
1525
1539
|
// Carry over the encoded data from the stored original (the handler
|
|
1526
1540
|
// base64url-encodes small payloads into encodedData during processMessage)
|
|
1527
|
-
const upgradedMessage = recordsWriteInstance.message as RecordsQueryReplyEntry;
|
|
1528
1541
|
if (storedOriginal?.encodedData) {
|
|
1529
1542
|
upgradedMessage.encodedData = storedOriginal.encodedData;
|
|
1530
1543
|
}
|
|
1531
1544
|
|
|
1532
|
-
//
|
|
1533
|
-
|
|
1545
|
+
// Use put-before-delete ordering: if a crash occurs after the put but
|
|
1546
|
+
// before the delete, we end up with a duplicate (recoverable via the
|
|
1547
|
+
// isLatestBaseState index) rather than data loss (unrecoverable).
|
|
1534
1548
|
const upgradedCid = await Message.getCid(upgradedMessage);
|
|
1549
|
+
await messageStore.put(tenantDid, upgradedMessage, upgradedIndexes);
|
|
1535
1550
|
await stateIndex.insert(tenantDid, upgradedCid, upgradedIndexes);
|
|
1536
1551
|
|
|
1552
|
+
// Now remove the original message and its state index entry.
|
|
1553
|
+
await messageStore.delete(tenantDid, originalCid);
|
|
1554
|
+
await stateIndex.delete(tenantDid, [originalCid]);
|
|
1555
|
+
|
|
1537
1556
|
// Notify real-time subscribers (mirrors handler behavior)
|
|
1538
1557
|
if (eventStream !== undefined) {
|
|
1539
1558
|
eventStream.emit(tenantDid, { message: upgradedMessage }, upgradedIndexes);
|
|
@@ -1559,8 +1578,8 @@ export class AgentDwnApi {
|
|
|
1559
1578
|
const { encryption } = recordsWrite;
|
|
1560
1579
|
|
|
1561
1580
|
// Check if the record uses context-derived encryption
|
|
1562
|
-
const hasContextKey = encryption?.
|
|
1563
|
-
(
|
|
1581
|
+
const hasContextKey = encryption?.recipients.some(
|
|
1582
|
+
(r: { header: { derivationScheme: string } }) => r.header.derivationScheme === KeyDerivationScheme.ProtocolContext
|
|
1564
1583
|
);
|
|
1565
1584
|
|
|
1566
1585
|
if (!hasContextKey || !recordsWrite.contextId) {
|
|
@@ -1569,15 +1588,15 @@ export class AgentDwnApi {
|
|
|
1569
1588
|
}
|
|
1570
1589
|
|
|
1571
1590
|
// --- Multi-party context encryption ---
|
|
1572
|
-
const contextKeyEntry = encryption!.
|
|
1573
|
-
(
|
|
1591
|
+
const contextKeyEntry = encryption!.recipients.find(
|
|
1592
|
+
(r: { header: { derivationScheme: string } }) => r.header.derivationScheme === KeyDerivationScheme.ProtocolContext
|
|
1574
1593
|
)!;
|
|
1575
1594
|
|
|
1576
1595
|
const rootContextId = recordsWrite.contextId.split('/')[0];
|
|
1577
1596
|
|
|
1578
1597
|
// Case 1: I am the context creator — rootKeyId matches my encryption key
|
|
1579
1598
|
const { keyId, keyUri } = await this.getEncryptionKeyInfo(authorDid);
|
|
1580
|
-
if (contextKeyEntry.
|
|
1599
|
+
if (contextKeyEntry.header.kid === keyId) {
|
|
1581
1600
|
return this.buildKmsDecryptCallback(keyId, keyUri, KeyDerivationScheme.ProtocolContext);
|
|
1582
1601
|
}
|
|
1583
1602
|
|
|
@@ -1638,17 +1657,12 @@ export class AgentDwnApi {
|
|
|
1638
1657
|
return {
|
|
1639
1658
|
rootKeyId : contextKey.rootKeyId,
|
|
1640
1659
|
derivationScheme : contextKey.derivationScheme,
|
|
1641
|
-
decrypt : async (fullDerivationPath,
|
|
1642
|
-
const
|
|
1660
|
+
decrypt : async (fullDerivationPath, jwePayload): Promise<Uint8Array> => {
|
|
1661
|
+
const leafPrivateKeyBytes = await Records.derivePrivateKey(
|
|
1643
1662
|
contextKey, fullDerivationPath,
|
|
1644
1663
|
);
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
ciphertext : eciesPayload.ciphertext,
|
|
1648
|
-
ephemeralPublicKey : eciesPayload.ephemeralPublicKey,
|
|
1649
|
-
initializationVector : eciesPayload.initializationVector,
|
|
1650
|
-
messageAuthenticationCode : eciesPayload.messageAuthenticationCode,
|
|
1651
|
-
});
|
|
1664
|
+
const leafPrivateKeyJwk = await X25519.bytesToPrivateKey({ privateKeyBytes: leafPrivateKeyBytes });
|
|
1665
|
+
return Encryption.ecdhEsUnwrapKey(leafPrivateKeyJwk, jwePayload.ephemeralPublicKey, jwePayload.encryptedKey);
|
|
1652
1666
|
},
|
|
1653
1667
|
};
|
|
1654
1668
|
}
|
|
@@ -1869,18 +1883,22 @@ export class AgentDwnApi {
|
|
|
1869
1883
|
// --- Encrypt to the recipient's ProtocolPath key (cross-DWN delivery) ---
|
|
1870
1884
|
// Manually build encryption input targeting the recipient's key so the
|
|
1871
1885
|
// record is decryptable only by the recipient.
|
|
1886
|
+
const algorithm = ContentEncryptionAlgorithm.A256GCM;
|
|
1872
1887
|
const dataEncryptionKey = crypto.getRandomValues(new Uint8Array(32));
|
|
1873
|
-
const dataEncryptionIV = crypto.getRandomValues(new Uint8Array(
|
|
1888
|
+
const dataEncryptionIV = crypto.getRandomValues(new Uint8Array(AgentDwnApi.ivLength(algorithm)));
|
|
1874
1889
|
|
|
1875
|
-
const { encryptedBytes, dataCid, dataSize } =
|
|
1876
|
-
await this.encryptAndComputeCid(plaintextBytes, dataEncryptionKey, dataEncryptionIV);
|
|
1890
|
+
const { encryptedBytes, dataCid, dataSize, authenticationTag } =
|
|
1891
|
+
await this.encryptAndComputeCid(plaintextBytes, dataEncryptionKey, dataEncryptionIV, algorithm);
|
|
1877
1892
|
|
|
1878
|
-
const encryptionInput =
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1893
|
+
const encryptionInput = {
|
|
1894
|
+
...this.buildEncryptionInput(
|
|
1895
|
+
dataEncryptionKey, dataEncryptionIV,
|
|
1896
|
+
recipientKeyDeliveryPublicKey.rootKeyId,
|
|
1897
|
+
recipientKeyDeliveryPublicKey.publicKeyJwk,
|
|
1898
|
+
KeyDerivationScheme.ProtocolPath,
|
|
1899
|
+
),
|
|
1900
|
+
authenticationTag,
|
|
1901
|
+
} as EncryptionInput;
|
|
1884
1902
|
|
|
1885
1903
|
({ message, reply: { status } } = await this.processRequest({
|
|
1886
1904
|
author : tenantDid,
|
package/src/hd-identity-vault.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { KeyValueStore } from '@enbox/common';
|
|
|
4
4
|
|
|
5
5
|
import { HDKey } from 'ed25519-keygen/hdkey';
|
|
6
6
|
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
7
|
-
import { BearerDid, DidDht } from '@enbox/dids';
|
|
7
|
+
import { BearerDid, DidDht, isPortableDid } from '@enbox/dids';
|
|
8
8
|
import { Convert, MemoryStore } from '@enbox/common';
|
|
9
9
|
import { generateMnemonic, mnemonicToSeed, validateMnemonic } from '@scure/bip39';
|
|
10
10
|
|
|
@@ -14,7 +14,6 @@ import type { IdentityVault, IdentityVaultBackup, IdentityVaultBackupData, Ident
|
|
|
14
14
|
import { AgentCryptoApi } from './crypto-api.js';
|
|
15
15
|
import { CompactJwe } from './prototyping/crypto/jose/jwe-compact.js';
|
|
16
16
|
import { DeterministicKeyGenerator } from './utils-internal.js';
|
|
17
|
-
import { isPortableDid } from './prototyping/dids/utils.js';
|
|
18
17
|
import { LocalKeyManager } from './local-key-manager.js';
|
|
19
18
|
|
|
20
19
|
/**
|
|
@@ -495,10 +494,10 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
|
|
|
495
494
|
privateKeyBytes : signingHdKey.privateKey
|
|
496
495
|
});
|
|
497
496
|
|
|
498
|
-
// Derive the encryption key using index 2 (
|
|
497
|
+
// Derive the encryption key using index 2 (X25519 for ECDH-ES JWE encryption).
|
|
499
498
|
const encryptionHdKey = rootHdKey.derive(`m/44'/0'/1708523827'/0'/2'`);
|
|
500
499
|
const encryptionPrivateKey = await this.crypto.bytesToPrivateKey({
|
|
501
|
-
algorithm : '
|
|
500
|
+
algorithm : 'X25519',
|
|
502
501
|
privateKeyBytes : encryptionHdKey.privateKey
|
|
503
502
|
});
|
|
504
503
|
|
|
@@ -518,7 +517,7 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
|
|
|
518
517
|
purposes : ['assertionMethod', 'authentication']
|
|
519
518
|
},
|
|
520
519
|
{
|
|
521
|
-
algorithm : '
|
|
520
|
+
algorithm : 'X25519',
|
|
522
521
|
id : 'enc',
|
|
523
522
|
purposes : ['keyAgreement']
|
|
524
523
|
}
|
package/src/identity-api.ts
CHANGED
|
@@ -6,10 +6,11 @@ import type { DidMethodCreateOptions } from './did-api.js';
|
|
|
6
6
|
import type { Web5PlatformAgent } from './types/agent.js';
|
|
7
7
|
import type { IdentityMetadata, PortableIdentity } from './types/identity.js';
|
|
8
8
|
|
|
9
|
+
import { isPortableDid } from '@enbox/dids';
|
|
10
|
+
|
|
9
11
|
import { BearerIdentity } from './bearer-identity.js';
|
|
10
12
|
import { getDwnServiceEndpointUrls } from './utils.js';
|
|
11
13
|
import { InMemoryIdentityStore } from './store-identity.js';
|
|
12
|
-
import { isPortableDid } from './prototyping/dids/utils.js';
|
|
13
14
|
|
|
14
15
|
export interface IdentityApiParams<TKeyManager extends AgentKeyManager> {
|
|
15
16
|
agent?: Web5PlatformAgent<TKeyManager>;
|
package/src/index.ts
CHANGED
|
@@ -12,12 +12,10 @@ export * from './bearer-identity.js';
|
|
|
12
12
|
export * from './crypto-api.js';
|
|
13
13
|
export * from './did-api.js';
|
|
14
14
|
export * from './dwn-api.js';
|
|
15
|
-
export * from './dwn-registrar.js';
|
|
16
15
|
export * from './hd-identity-vault.js';
|
|
17
16
|
export * from './identity-api.js';
|
|
18
17
|
export * from './local-key-manager.js';
|
|
19
18
|
export * from './permissions-api.js';
|
|
20
|
-
export * from './rpc-client.js';
|
|
21
19
|
export * from './store-data.js';
|
|
22
20
|
export * from './store-did.js';
|
|
23
21
|
export * from './store-identity.js';
|