@ajna-inc/vaults 0.1.0 → 0.1.2
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/build/VaultsApi.d.ts +363 -0
- package/build/VaultsApi.js +450 -248
- package/build/VaultsApi.js.map +1 -0
- package/build/VaultsEvents.d.ts +227 -0
- package/build/VaultsEvents.js +8 -0
- package/build/VaultsEvents.js.map +1 -0
- package/build/VaultsModule.d.ts +64 -0
- package/build/VaultsModule.js +43 -18
- package/build/VaultsModule.js.map +1 -0
- package/build/crypto/wasm/VaultCrypto.d.ts +19 -0
- package/build/crypto/wasm/VaultCrypto.js +29 -42
- package/build/crypto/wasm/VaultCrypto.js.map +1 -0
- package/build/errors/BadSuiteError.d.ts +8 -0
- package/build/errors/BadSuiteError.js +8 -25
- package/build/errors/BadSuiteError.js.map +1 -0
- package/build/errors/DecryptAeadError.d.ts +8 -0
- package/build/errors/DecryptAeadError.js +8 -25
- package/build/errors/DecryptAeadError.js.map +1 -0
- package/build/errors/DecryptKemError.d.ts +8 -0
- package/build/errors/DecryptKemError.js +8 -25
- package/build/errors/DecryptKemError.js.map +1 -0
- package/build/errors/PolicyError.d.ts +8 -0
- package/build/errors/PolicyError.js +8 -25
- package/build/errors/PolicyError.js.map +1 -0
- package/build/errors/VaultError.d.ts +52 -0
- package/build/errors/VaultError.js +19 -30
- package/build/errors/VaultError.js.map +1 -0
- package/build/errors/index.d.ts +5 -0
- package/build/errors/index.js +1 -0
- package/build/errors/index.js.map +1 -0
- package/build/handlers/CreateVaultHandler.d.ts +18 -0
- package/build/handlers/CreateVaultHandler.js +75 -0
- package/build/handlers/CreateVaultHandler.js.map +1 -0
- package/build/handlers/DeleteVaultHandler.d.ts +17 -0
- package/build/handlers/DeleteVaultHandler.js +48 -0
- package/build/handlers/DeleteVaultHandler.js.map +1 -0
- package/build/handlers/DenyAccessHandler.d.ts +15 -0
- package/build/handlers/DenyAccessHandler.js +39 -0
- package/build/handlers/DenyAccessHandler.js.map +1 -0
- package/build/handlers/DenyShareHandler.d.ts +17 -0
- package/build/handlers/DenyShareHandler.js +49 -0
- package/build/handlers/DenyShareHandler.js.map +1 -0
- package/build/handlers/GrantAccessHandler.d.ts +17 -0
- package/build/handlers/GrantAccessHandler.js +59 -0
- package/build/handlers/GrantAccessHandler.js.map +1 -0
- package/build/handlers/ProvideShareHandler.d.ts +17 -0
- package/build/handlers/ProvideShareHandler.js +77 -0
- package/build/handlers/ProvideShareHandler.js.map +1 -0
- package/build/handlers/RequestAccessHandler.d.ts +18 -0
- package/build/handlers/RequestAccessHandler.js +60 -0
- package/build/handlers/RequestAccessHandler.js.map +1 -0
- package/build/handlers/RequestShareHandler.d.ts +19 -0
- package/build/handlers/RequestShareHandler.js +70 -0
- package/build/handlers/RequestShareHandler.js.map +1 -0
- package/build/handlers/RequestStorageHandler.d.ts +53 -0
- package/build/handlers/RequestStorageHandler.js +158 -0
- package/build/handlers/RequestStorageHandler.js.map +1 -0
- package/build/handlers/RetrieveVaultHandler.d.ts +18 -0
- package/build/handlers/RetrieveVaultHandler.js +65 -0
- package/build/handlers/RetrieveVaultHandler.js.map +1 -0
- package/build/handlers/StoreVaultHandler.d.ts +17 -0
- package/build/handlers/StoreVaultHandler.js +77 -0
- package/build/handlers/StoreVaultHandler.js.map +1 -0
- package/build/handlers/UpdateVaultHandler.d.ts +18 -0
- package/build/handlers/UpdateVaultHandler.js +77 -0
- package/build/handlers/UpdateVaultHandler.js.map +1 -0
- package/build/handlers/VaultCreatedAckHandler.d.ts +15 -0
- package/build/handlers/VaultCreatedAckHandler.js +39 -0
- package/build/handlers/VaultCreatedAckHandler.js.map +1 -0
- package/build/handlers/VaultDataHandler.d.ts +19 -0
- package/build/handlers/VaultDataHandler.js +68 -0
- package/build/handlers/VaultDataHandler.js.map +1 -0
- package/build/handlers/VaultProblemReportHandler.d.ts +17 -0
- package/build/handlers/VaultProblemReportHandler.js +40 -0
- package/build/handlers/VaultProblemReportHandler.js.map +1 -0
- package/build/handlers/VaultReferenceHandler.d.ts +33 -0
- package/build/handlers/VaultReferenceHandler.js +169 -0
- package/build/handlers/VaultReferenceHandler.js.map +1 -0
- package/build/handlers/VaultStoredAckHandler.d.ts +15 -0
- package/build/handlers/VaultStoredAckHandler.js +38 -0
- package/build/handlers/VaultStoredAckHandler.js.map +1 -0
- package/build/handlers/index.d.ts +17 -0
- package/build/handlers/index.js +44 -0
- package/build/handlers/index.js.map +1 -0
- package/build/index.d.ts +42 -0
- package/build/index.js +13 -1
- package/build/index.js.map +1 -0
- package/build/messages/CreateVaultMessage.d.ts +39 -0
- package/build/messages/CreateVaultMessage.js +65 -115
- package/build/messages/CreateVaultMessage.js.map +1 -0
- package/build/messages/DeleteVaultMessage.d.ts +22 -0
- package/build/messages/DeleteVaultMessage.js +51 -103
- package/build/messages/DeleteVaultMessage.js.map +1 -0
- package/build/messages/DenyAccessMessage.d.ts +22 -0
- package/build/messages/DenyAccessMessage.js +50 -103
- package/build/messages/DenyAccessMessage.js.map +1 -0
- package/build/messages/DenyShareMessage.d.ts +24 -0
- package/build/messages/DenyShareMessage.js +56 -109
- package/build/messages/DenyShareMessage.js.map +1 -0
- package/build/messages/GrantAccessMessage.d.ts +32 -0
- package/build/messages/GrantAccessMessage.js +63 -115
- package/build/messages/GrantAccessMessage.js.map +1 -0
- package/build/messages/ProvideShareMessage.d.ts +26 -0
- package/build/messages/ProvideShareMessage.js +62 -115
- package/build/messages/ProvideShareMessage.js.map +1 -0
- package/build/messages/ProvideStorageMessage.d.ts +90 -0
- package/build/messages/ProvideStorageMessage.js +193 -0
- package/build/messages/ProvideStorageMessage.js.map +1 -0
- package/build/messages/RequestAccessMessage.d.ts +30 -0
- package/build/messages/RequestAccessMessage.js +57 -109
- package/build/messages/RequestAccessMessage.js.map +1 -0
- package/build/messages/RequestShareMessage.d.ts +24 -0
- package/build/messages/RequestShareMessage.js +56 -109
- package/build/messages/RequestShareMessage.js.map +1 -0
- package/build/messages/RequestStorageMessage.d.ts +50 -0
- package/build/messages/RequestStorageMessage.js +98 -0
- package/build/messages/RequestStorageMessage.js.map +1 -0
- package/build/messages/RetrieveVaultMessage.d.ts +20 -0
- package/build/messages/RetrieveVaultMessage.js +44 -97
- package/build/messages/RetrieveVaultMessage.js.map +1 -0
- package/build/messages/StoreVaultMessage.d.ts +23 -0
- package/build/messages/StoreVaultMessage.js +51 -103
- package/build/messages/StoreVaultMessage.js.map +1 -0
- package/build/messages/UpdateVaultMessage.d.ts +25 -0
- package/build/messages/UpdateVaultMessage.js +58 -109
- package/build/messages/UpdateVaultMessage.js.map +1 -0
- package/build/messages/VaultCreatedAckMessage.d.ts +20 -0
- package/build/messages/VaultCreatedAckMessage.js +44 -97
- package/build/messages/VaultCreatedAckMessage.js.map +1 -0
- package/build/messages/VaultDataMessage.d.ts +34 -0
- package/build/messages/VaultDataMessage.js +59 -110
- package/build/messages/VaultDataMessage.js.map +1 -0
- package/build/messages/VaultProblemReportMessage.d.ts +35 -0
- package/build/messages/VaultProblemReportMessage.js +56 -102
- package/build/messages/VaultProblemReportMessage.js.map +1 -0
- package/build/messages/VaultReferenceMessage.d.ts +66 -0
- package/build/messages/VaultReferenceMessage.js +138 -0
- package/build/messages/VaultReferenceMessage.js.map +1 -0
- package/build/messages/VaultStoredAckMessage.d.ts +33 -0
- package/build/messages/VaultStoredAckMessage.js +51 -104
- package/build/messages/VaultStoredAckMessage.js.map +1 -0
- package/build/messages/index.d.ts +18 -0
- package/build/messages/index.js +6 -1
- package/build/messages/index.js.map +1 -0
- package/build/models/ThresholdSession.d.ts +37 -0
- package/build/models/ThresholdSession.js +1 -0
- package/build/models/ThresholdSession.js.map +1 -0
- package/build/models/VaultDocument.d.ts +22 -0
- package/build/models/VaultDocument.js +1 -0
- package/build/models/VaultDocument.js.map +1 -0
- package/build/models/VaultHeader.d.ts +92 -0
- package/build/models/VaultHeader.js +4 -6
- package/build/models/VaultHeader.js.map +1 -0
- package/build/models/VaultPolicy.d.ts +24 -0
- package/build/models/VaultPolicy.js +1 -0
- package/build/models/VaultPolicy.js.map +1 -0
- package/build/models/index.d.ts +4 -0
- package/build/models/index.js +1 -0
- package/build/models/index.js.map +1 -0
- package/build/repository/KemKeypairRecord.d.ts +37 -0
- package/build/repository/KemKeypairRecord.js +35 -0
- package/build/repository/KemKeypairRecord.js.map +1 -0
- package/build/repository/KemKeypairRepository.d.ts +18 -0
- package/build/repository/KemKeypairRepository.js +50 -0
- package/build/repository/KemKeypairRepository.js.map +1 -0
- package/build/repository/ThresholdSessionRecord.d.ts +93 -0
- package/build/repository/ThresholdSessionRecord.js +58 -92
- package/build/repository/ThresholdSessionRecord.js.map +1 -0
- package/build/repository/ThresholdSessionRepository.d.ts +35 -0
- package/build/repository/ThresholdSessionRepository.js +72 -208
- package/build/repository/ThresholdSessionRepository.js.map +1 -0
- package/build/repository/VaultRecord.d.ts +105 -0
- package/build/repository/VaultRecord.js +94 -115
- package/build/repository/VaultRecord.js.map +1 -0
- package/build/repository/VaultRepository.d.ts +35 -0
- package/build/repository/VaultRepository.js +66 -192
- package/build/repository/VaultRepository.js.map +1 -0
- package/build/repository/index.d.ts +9 -0
- package/build/repository/index.js +7 -1
- package/build/repository/index.js.map +1 -0
- package/build/services/HPKEService.d.ts +67 -0
- package/build/services/HPKEService.js +106 -0
- package/build/services/HPKEService.js.map +1 -0
- package/build/services/KemKeyExchangeService.d.ts +207 -0
- package/build/services/KemKeyExchangeService.js +323 -0
- package/build/services/KemKeyExchangeService.js.map +1 -0
- package/build/services/VaultEncryptionService.d.ts +120 -0
- package/build/services/VaultEncryptionService.js +469 -588
- package/build/services/VaultEncryptionService.js.map +1 -0
- package/build/services/VaultService.d.ts +127 -0
- package/build/services/VaultService.js +224 -376
- package/build/services/VaultService.js.map +1 -0
- package/build/services/VaultSigningService.d.ts +216 -0
- package/build/services/VaultSigningService.js +498 -0
- package/build/services/VaultSigningService.js.map +1 -0
- package/build/services/index.d.ts +9 -0
- package/build/services/index.js +10 -1
- package/build/services/index.js.map +1 -0
- package/build/storage/VaultStorageConfig.d.ts +97 -0
- package/build/storage/VaultStorageConfig.js +22 -0
- package/build/storage/VaultStorageConfig.js.map +1 -0
- package/build/storage/VaultStorageService.d.ts +118 -0
- package/build/storage/VaultStorageService.js +381 -0
- package/build/storage/VaultStorageService.js.map +1 -0
- package/build/storage/index.d.ts +2 -0
- package/build/storage/index.js +21 -0
- package/build/storage/index.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HPKE Service for Vaults
|
|
4
|
+
*
|
|
5
|
+
* Implements RFC 9180 HPKE for sealing ML-KEM public keys during key exchange.
|
|
6
|
+
*
|
|
7
|
+
* Uses:
|
|
8
|
+
* - KEM: DHKEM(P-256, HKDF-SHA256)
|
|
9
|
+
* - KDF: HKDF-SHA256
|
|
10
|
+
* - AEAD: AES-256-GCM
|
|
11
|
+
*/
|
|
12
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
13
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
15
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
16
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.HPKEService = void 0;
|
|
20
|
+
const core_1 = require("@credo-ts/core");
|
|
21
|
+
const core_2 = require("@hpke/core");
|
|
22
|
+
const sha256_1 = require("@noble/hashes/sha256");
|
|
23
|
+
let HPKEService = class HPKEService {
|
|
24
|
+
/**
|
|
25
|
+
* Get CipherSuite for HPKE operations
|
|
26
|
+
*/
|
|
27
|
+
getCipherSuite() {
|
|
28
|
+
return new core_2.CipherSuite({
|
|
29
|
+
kem: new core_2.DhkemP256HkdfSha256(),
|
|
30
|
+
kdf: new core_2.HkdfSha256(),
|
|
31
|
+
aead: new core_2.Aes256Gcm(),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Encrypt payload with HPKE
|
|
36
|
+
*
|
|
37
|
+
* @param recipientPublicKey - Recipient's P-256 public key (raw bytes)
|
|
38
|
+
* @param plaintext - Payload to encrypt
|
|
39
|
+
* @param aad - Additional authenticated data (optional)
|
|
40
|
+
* @returns Encryption result with ciphertext and ephemeral key
|
|
41
|
+
*/
|
|
42
|
+
async encrypt(recipientPublicKey, plaintext, aad) {
|
|
43
|
+
const suite = this.getCipherSuite();
|
|
44
|
+
// Import recipient public key
|
|
45
|
+
const pkR = await suite.kem.importKey('raw', recipientPublicKey, true);
|
|
46
|
+
// Encrypt using HPKE Base mode
|
|
47
|
+
const sender = await suite.createSenderContext({
|
|
48
|
+
recipientPublicKey: pkR,
|
|
49
|
+
});
|
|
50
|
+
const ciphertext = new Uint8Array(await sender.seal(plaintext, aad));
|
|
51
|
+
return {
|
|
52
|
+
ciphertext,
|
|
53
|
+
ephemeralPublicKey: new Uint8Array(sender.enc),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Decrypt payload with HPKE
|
|
58
|
+
*
|
|
59
|
+
* @param recipientPrivateKey - Recipient's P-256 private key (raw bytes)
|
|
60
|
+
* @param ciphertext - Encrypted payload
|
|
61
|
+
* @param ephemeralPublicKey - Ephemeral public key from encryption
|
|
62
|
+
* @param aad - Additional authenticated data (must match encryption)
|
|
63
|
+
* @returns Decryption result with plaintext
|
|
64
|
+
*/
|
|
65
|
+
async decrypt(recipientPrivateKey, ciphertext, ephemeralPublicKey, aad) {
|
|
66
|
+
const suite = this.getCipherSuite();
|
|
67
|
+
// Import recipient private key
|
|
68
|
+
const skR = await suite.kem.importKey('raw', recipientPrivateKey, false);
|
|
69
|
+
// Decrypt using HPKE Base mode
|
|
70
|
+
const recipient = await suite.createRecipientContext({
|
|
71
|
+
recipientKey: skR,
|
|
72
|
+
enc: ephemeralPublicKey,
|
|
73
|
+
});
|
|
74
|
+
const plaintext = new Uint8Array(await recipient.open(ciphertext, aad));
|
|
75
|
+
return { plaintext };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Generate key pair for HPKE (P-256)
|
|
79
|
+
*
|
|
80
|
+
* @returns Object with public and private keys
|
|
81
|
+
*/
|
|
82
|
+
async generateKeyPair() {
|
|
83
|
+
const suite = this.getCipherSuite();
|
|
84
|
+
const keyPair = await suite.kem.generateKeyPair();
|
|
85
|
+
const publicKeyRaw = await suite.kem.serializePublicKey(keyPair.publicKey);
|
|
86
|
+
const privateKeyRaw = await suite.kem.serializePrivateKey(keyPair.privateKey);
|
|
87
|
+
return {
|
|
88
|
+
publicKey: new Uint8Array(publicKeyRaw),
|
|
89
|
+
privateKey: new Uint8Array(privateKeyRaw),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compute digest for AAD binding
|
|
94
|
+
*
|
|
95
|
+
* @param data - Data to hash
|
|
96
|
+
* @returns SHA-256 hash
|
|
97
|
+
*/
|
|
98
|
+
computeDigest(data) {
|
|
99
|
+
return (0, sha256_1.sha256)(data);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
exports.HPKEService = HPKEService;
|
|
103
|
+
exports.HPKEService = HPKEService = __decorate([
|
|
104
|
+
(0, core_1.injectable)()
|
|
105
|
+
], HPKEService);
|
|
106
|
+
//# sourceMappingURL=HPKEService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HPKEService.js","sourceRoot":"","sources":["../../src/services/HPKEService.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;AAEH,yCAA2C;AAC3C,qCAAoF;AACpF,iDAA6C;AAqBtC,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB;;OAEG;IACK,cAAc;QACpB,OAAO,IAAI,kBAAW,CAAC;YACrB,GAAG,EAAE,IAAI,0BAAmB,EAAE;YAC9B,GAAG,EAAE,IAAI,iBAAU,EAAE;YACrB,IAAI,EAAE,IAAI,gBAAS,EAAE;SACtB,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAClB,kBAA8B,EAC9B,SAAqB,EACrB,GAAgB;QAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAEnC,8BAA8B;QAC9B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAA;QAEtE,+BAA+B;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,mBAAmB,CAAC;YAC7C,kBAAkB,EAAE,GAAG;SACxB,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAA;QAEpE,OAAO;YACL,UAAU;YACV,kBAAkB,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;SAC/C,CAAA;IACH,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,OAAO,CAClB,mBAA+B,EAC/B,UAAsB,EACtB,kBAA8B,EAC9B,GAAgB;QAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAEnC,+BAA+B;QAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAA;QAExE,+BAA+B;QAC/B,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,sBAAsB,CAAC;YACnD,YAAY,EAAE,GAAG;YACjB,GAAG,EAAE,kBAAkB;SACxB,CAAC,CAAA;QAEF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAA;QAEvE,OAAO,EAAE,SAAS,EAAE,CAAA;IACtB,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe;QAI1B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QACnC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,CAAA;QAEjD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAC1E,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAE7E,OAAO;YACL,SAAS,EAAE,IAAI,UAAU,CAAC,YAAY,CAAC;YACvC,UAAU,EAAE,IAAI,UAAU,CAAC,aAAa,CAAC;SAC1C,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACI,aAAa,CAAC,IAAgB;QACnC,OAAO,IAAA,eAAM,EAAC,IAAI,CAAC,CAAA;IACrB,CAAC;CACF,CAAA;AAxGY,kCAAW;sBAAX,WAAW;IADvB,IAAA,iBAAU,GAAE;GACA,WAAW,CAwGvB"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KEM Key Exchange Service
|
|
3
|
+
*
|
|
4
|
+
* Exchanges ML-KEM public keys between agents for quantum-safe vault encryption.
|
|
5
|
+
*
|
|
6
|
+
* Key Design:
|
|
7
|
+
* - Uses existing X25519 channel to bootstrap ML-KEM key exchange
|
|
8
|
+
* - Seals ML-KEM public keys in HPKE envelopes (RFC 9180)
|
|
9
|
+
* - Stores peer's ML-KEM keys in connection metadata
|
|
10
|
+
* - Uses signing protocol's provide-artifacts message (sealed-secret@1)
|
|
11
|
+
*
|
|
12
|
+
* Flow:
|
|
13
|
+
* 1. Agent A generates ML-KEM keypair
|
|
14
|
+
* 2. Agent A seals their ML-KEM public key using peer's X25519 key
|
|
15
|
+
* 3. Agent A sends sealed key via provide-artifacts message
|
|
16
|
+
* 4. Agent B unwraps the ML-KEM key using their X25519 private key
|
|
17
|
+
* 5. Agent B stores Agent A's ML-KEM key in connection metadata
|
|
18
|
+
* 6. Agent B can now encrypt vaults to Agent A's ML-KEM key
|
|
19
|
+
*/
|
|
20
|
+
import type { AgentContext, Logger } from '@credo-ts/core';
|
|
21
|
+
import { ConnectionRepository } from '@credo-ts/core';
|
|
22
|
+
import { HPKEService } from './HPKEService';
|
|
23
|
+
import { KemKeypairRepository } from '../repository/KemKeypairRepository';
|
|
24
|
+
/**
|
|
25
|
+
* ML-KEM keypair with derived key ID
|
|
26
|
+
*/
|
|
27
|
+
export interface KemKeypairWithKid {
|
|
28
|
+
/** Key identifier (derived from public key hash) */
|
|
29
|
+
kid: string;
|
|
30
|
+
/** ML-KEM public key (1184 bytes for ML-KEM-768) */
|
|
31
|
+
publicKey: Uint8Array;
|
|
32
|
+
/** ML-KEM secret key (2400 bytes for ML-KEM-768) */
|
|
33
|
+
secretKey: Uint8Array;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* ML-KEM public key info (no secret key)
|
|
37
|
+
*/
|
|
38
|
+
export interface KemPublicKeyInfo {
|
|
39
|
+
/** Key identifier */
|
|
40
|
+
kid: string;
|
|
41
|
+
/** ML-KEM public key */
|
|
42
|
+
publicKey: Uint8Array;
|
|
43
|
+
/** Timestamp when the key was stored */
|
|
44
|
+
storedAt?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sealed artifact containing ML-KEM public key
|
|
48
|
+
* Encrypted with HPKE to recipient's X25519 key
|
|
49
|
+
*/
|
|
50
|
+
export interface SealedKemKeyArtifact {
|
|
51
|
+
/** Artifact type identifier */
|
|
52
|
+
type: 'sealed-ml-kem-key@1';
|
|
53
|
+
/** HPKE envelope suite */
|
|
54
|
+
envelope: 'envelope-hpke@1';
|
|
55
|
+
/** Base64url-encoded ciphertext */
|
|
56
|
+
ciphertext: string;
|
|
57
|
+
/** Base64url-encoded ephemeral public key */
|
|
58
|
+
ephemeralPublicKey: string;
|
|
59
|
+
/** Key ID of the sealed ML-KEM key */
|
|
60
|
+
kid: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Connection metadata key for ML-KEM keys
|
|
64
|
+
*/
|
|
65
|
+
export declare const KEM_KEY_METADATA_KEY = "vaults/kem-key";
|
|
66
|
+
/**
|
|
67
|
+
* Metadata stored in connection for peer's KEM key
|
|
68
|
+
*/
|
|
69
|
+
export interface KemKeyMetadata {
|
|
70
|
+
/** Key identifier */
|
|
71
|
+
kid: string;
|
|
72
|
+
/** Base64url-encoded ML-KEM public key */
|
|
73
|
+
publicKey: string;
|
|
74
|
+
/** When the key was stored */
|
|
75
|
+
storedAt: string;
|
|
76
|
+
/** Optional: when the key exchange session was initiated */
|
|
77
|
+
exchangeSessionId?: string;
|
|
78
|
+
}
|
|
79
|
+
export declare class KemKeyExchangeService {
|
|
80
|
+
private logger;
|
|
81
|
+
private connectionRepository;
|
|
82
|
+
private hpkeService;
|
|
83
|
+
private kemKeypairRepository;
|
|
84
|
+
constructor(logger: Logger, connectionRepository: ConnectionRepository, hpkeService: HPKEService, kemKeypairRepository: KemKeypairRepository);
|
|
85
|
+
/**
|
|
86
|
+
* Generate a new ML-KEM-768 keypair
|
|
87
|
+
*
|
|
88
|
+
* @returns Keypair with derived key ID
|
|
89
|
+
*/
|
|
90
|
+
generateKemKeypair(): KemKeypairWithKid;
|
|
91
|
+
/**
|
|
92
|
+
* Create a sealed artifact containing our ML-KEM public key
|
|
93
|
+
*
|
|
94
|
+
* This creates an artifact suitable for sending via provide-artifacts message.
|
|
95
|
+
* The ML-KEM public key is sealed using HPKE (RFC 9180) to the recipient's P-256 public key.
|
|
96
|
+
*
|
|
97
|
+
* @param keypair - Our ML-KEM keypair
|
|
98
|
+
* @param recipientPublicKey - Recipient's P-256 public key for HPKE encryption
|
|
99
|
+
* @returns Sealed artifact ready for transmission
|
|
100
|
+
*/
|
|
101
|
+
createKemKeyArtifact(keypair: KemKeypairWithKid, recipientPublicKey: Uint8Array): Promise<SealedKemKeyArtifact>;
|
|
102
|
+
/**
|
|
103
|
+
* Unwrap a sealed KEM key artifact
|
|
104
|
+
*
|
|
105
|
+
* Decrypts the sealed artifact using HPKE to extract the peer's ML-KEM public key.
|
|
106
|
+
*
|
|
107
|
+
* @param artifact - Sealed artifact received from peer
|
|
108
|
+
* @param recipientSecretKey - Our P-256 private key to decrypt
|
|
109
|
+
* @returns Peer's ML-KEM public key info
|
|
110
|
+
*/
|
|
111
|
+
unwrapKemKeyArtifact(artifact: SealedKemKeyArtifact, recipientSecretKey: Uint8Array): Promise<KemPublicKeyInfo>;
|
|
112
|
+
/**
|
|
113
|
+
* Store peer's ML-KEM public key in connection metadata
|
|
114
|
+
*
|
|
115
|
+
* This allows retrieving the peer's KEM key later for vault encryption.
|
|
116
|
+
*
|
|
117
|
+
* @param agentContext - Agent context
|
|
118
|
+
* @param connectionId - Connection record ID
|
|
119
|
+
* @param keyInfo - Peer's ML-KEM public key info
|
|
120
|
+
*/
|
|
121
|
+
storePeerKemKey(agentContext: AgentContext, connectionId: string, keyInfo: KemPublicKeyInfo): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Retrieve peer's ML-KEM public key from connection metadata
|
|
124
|
+
*
|
|
125
|
+
* @param agentContext - Agent context
|
|
126
|
+
* @param connectionId - Connection record ID
|
|
127
|
+
* @returns Peer's KEM key info, or null if not found
|
|
128
|
+
*/
|
|
129
|
+
getPeerKemKey(agentContext: AgentContext, connectionId: string): Promise<KemPublicKeyInfo | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Delete peer's ML-KEM public key from connection metadata
|
|
132
|
+
*
|
|
133
|
+
* @param agentContext - Agent context
|
|
134
|
+
* @param connectionId - Connection record ID
|
|
135
|
+
*/
|
|
136
|
+
deletePeerKemKey(agentContext: AgentContext, connectionId: string): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Check if a connection has a peer KEM key
|
|
139
|
+
*
|
|
140
|
+
* @param agentContext - Agent context
|
|
141
|
+
* @param connectionId - Connection record ID
|
|
142
|
+
* @returns True if peer has KEM key stored
|
|
143
|
+
*/
|
|
144
|
+
hasPeerKemKey(agentContext: AgentContext, connectionId: string): Promise<boolean>;
|
|
145
|
+
/**
|
|
146
|
+
* Store a local KEM keypair (including secret key) for a connection
|
|
147
|
+
*
|
|
148
|
+
* Call this after generateKemKeypair() to persist the keypair so it can
|
|
149
|
+
* be retrieved later for vault decryption.
|
|
150
|
+
*
|
|
151
|
+
* @param agentContext - Agent context
|
|
152
|
+
* @param connectionId - Connection to associate the keypair with
|
|
153
|
+
* @param keypair - Full ML-KEM keypair
|
|
154
|
+
*/
|
|
155
|
+
storeLocalKeypair(agentContext: AgentContext, connectionId: string, keypair: KemKeypairWithKid): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Get the local KEM keypair for a connection
|
|
158
|
+
*
|
|
159
|
+
* @param agentContext - Agent context
|
|
160
|
+
* @param connectionId - Connection record ID
|
|
161
|
+
* @returns Full keypair including secret key, or null if not found
|
|
162
|
+
*/
|
|
163
|
+
getLocalKeypair(agentContext: AgentContext, connectionId: string): Promise<KemKeypairWithKid | null>;
|
|
164
|
+
/**
|
|
165
|
+
* Find a local keypair by its key identifier (kid)
|
|
166
|
+
*
|
|
167
|
+
* This is the primary lookup used during vault decryption: extract recipient
|
|
168
|
+
* kids from vault header, then find which local keypair matches.
|
|
169
|
+
*
|
|
170
|
+
* @param agentContext - Agent context
|
|
171
|
+
* @param kid - Key identifier to search for
|
|
172
|
+
* @returns Keypair and associated connectionId, or null
|
|
173
|
+
*/
|
|
174
|
+
findKeypairByKid(agentContext: AgentContext, kid: string): Promise<{
|
|
175
|
+
keypair: KemKeypairWithKid;
|
|
176
|
+
connectionId: string;
|
|
177
|
+
} | null>;
|
|
178
|
+
/**
|
|
179
|
+
* Find a local keypair matching any of the given recipient kids
|
|
180
|
+
*
|
|
181
|
+
* Used to find which local key can decrypt a vault when the vault header
|
|
182
|
+
* lists multiple possible recipients.
|
|
183
|
+
*
|
|
184
|
+
* @param agentContext - Agent context
|
|
185
|
+
* @param kids - Set of key identifiers from vault recipients
|
|
186
|
+
* @returns Matching keypair and connectionId, or null
|
|
187
|
+
*/
|
|
188
|
+
findKeypairByRecipientKids(agentContext: AgentContext, kids: Set<string>): Promise<{
|
|
189
|
+
keypair: KemKeypairWithKid;
|
|
190
|
+
connectionId: string;
|
|
191
|
+
} | null>;
|
|
192
|
+
/**
|
|
193
|
+
* Check if a local keypair exists for a connection
|
|
194
|
+
*
|
|
195
|
+
* @param agentContext - Agent context
|
|
196
|
+
* @param connectionId - Connection record ID
|
|
197
|
+
* @returns True if local keypair exists
|
|
198
|
+
*/
|
|
199
|
+
hasLocalKeypair(agentContext: AgentContext, connectionId: string): Promise<boolean>;
|
|
200
|
+
/**
|
|
201
|
+
* Delete the local keypair for a connection
|
|
202
|
+
*
|
|
203
|
+
* @param agentContext - Agent context
|
|
204
|
+
* @param connectionId - Connection record ID
|
|
205
|
+
*/
|
|
206
|
+
deleteLocalKeypair(agentContext: AgentContext, connectionId: string): Promise<void>;
|
|
207
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KEM Key Exchange Service
|
|
4
|
+
*
|
|
5
|
+
* Exchanges ML-KEM public keys between agents for quantum-safe vault encryption.
|
|
6
|
+
*
|
|
7
|
+
* Key Design:
|
|
8
|
+
* - Uses existing X25519 channel to bootstrap ML-KEM key exchange
|
|
9
|
+
* - Seals ML-KEM public keys in HPKE envelopes (RFC 9180)
|
|
10
|
+
* - Stores peer's ML-KEM keys in connection metadata
|
|
11
|
+
* - Uses signing protocol's provide-artifacts message (sealed-secret@1)
|
|
12
|
+
*
|
|
13
|
+
* Flow:
|
|
14
|
+
* 1. Agent A generates ML-KEM keypair
|
|
15
|
+
* 2. Agent A seals their ML-KEM public key using peer's X25519 key
|
|
16
|
+
* 3. Agent A sends sealed key via provide-artifacts message
|
|
17
|
+
* 4. Agent B unwraps the ML-KEM key using their X25519 private key
|
|
18
|
+
* 5. Agent B stores Agent A's ML-KEM key in connection metadata
|
|
19
|
+
* 6. Agent B can now encrypt vaults to Agent A's ML-KEM key
|
|
20
|
+
*/
|
|
21
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
22
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
24
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
|
+
};
|
|
27
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
28
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
29
|
+
};
|
|
30
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
31
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.KemKeyExchangeService = exports.KEM_KEY_METADATA_KEY = void 0;
|
|
35
|
+
const core_1 = require("@credo-ts/core");
|
|
36
|
+
const VaultCrypto_1 = require("../crypto/wasm/VaultCrypto");
|
|
37
|
+
const HPKEService_1 = require("./HPKEService");
|
|
38
|
+
const KemKeypairRepository_1 = require("../repository/KemKeypairRepository");
|
|
39
|
+
const KemKeypairRecord_1 = require("../repository/KemKeypairRecord");
|
|
40
|
+
/**
|
|
41
|
+
* Connection metadata key for ML-KEM keys
|
|
42
|
+
*/
|
|
43
|
+
exports.KEM_KEY_METADATA_KEY = 'vaults/kem-key';
|
|
44
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
45
|
+
// Service
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
47
|
+
let KemKeyExchangeService = class KemKeyExchangeService {
|
|
48
|
+
constructor(logger, connectionRepository, hpkeService, kemKeypairRepository) {
|
|
49
|
+
this.logger = logger;
|
|
50
|
+
this.connectionRepository = connectionRepository;
|
|
51
|
+
this.hpkeService = hpkeService;
|
|
52
|
+
this.kemKeypairRepository = kemKeypairRepository;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate a new ML-KEM-768 keypair
|
|
56
|
+
*
|
|
57
|
+
* @returns Keypair with derived key ID
|
|
58
|
+
*/
|
|
59
|
+
generateKemKeypair() {
|
|
60
|
+
this.logger.debug('Generating ML-KEM-768 keypair');
|
|
61
|
+
const keypair = (0, VaultCrypto_1.kemGenerateKeypair)();
|
|
62
|
+
const kid = (0, VaultCrypto_1.deriveKid)(keypair.publicKey);
|
|
63
|
+
this.logger.debug(`Generated ML-KEM keypair with kid: ${kid.substring(0, 20)}...`);
|
|
64
|
+
return {
|
|
65
|
+
kid,
|
|
66
|
+
publicKey: keypair.publicKey,
|
|
67
|
+
secretKey: keypair.secretKey,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a sealed artifact containing our ML-KEM public key
|
|
72
|
+
*
|
|
73
|
+
* This creates an artifact suitable for sending via provide-artifacts message.
|
|
74
|
+
* The ML-KEM public key is sealed using HPKE (RFC 9180) to the recipient's P-256 public key.
|
|
75
|
+
*
|
|
76
|
+
* @param keypair - Our ML-KEM keypair
|
|
77
|
+
* @param recipientPublicKey - Recipient's P-256 public key for HPKE encryption
|
|
78
|
+
* @returns Sealed artifact ready for transmission
|
|
79
|
+
*/
|
|
80
|
+
async createKemKeyArtifact(keypair, recipientPublicKey) {
|
|
81
|
+
this.logger.debug(`Creating sealed KEM key artifact for kid: ${keypair.kid.substring(0, 20)}...`);
|
|
82
|
+
// Prepare payload: { kid, publicKey }
|
|
83
|
+
const payload = JSON.stringify({
|
|
84
|
+
kid: keypair.kid,
|
|
85
|
+
publicKey: (0, VaultCrypto_1.toBase64Url)(keypair.publicKey),
|
|
86
|
+
});
|
|
87
|
+
const payloadBytes = new TextEncoder().encode(payload);
|
|
88
|
+
// Create AAD binding the artifact to the key ID
|
|
89
|
+
const aad = new TextEncoder().encode(`sealed-ml-kem-key:${keypair.kid}`);
|
|
90
|
+
// Encrypt using HPKE
|
|
91
|
+
const result = await this.hpkeService.encrypt(recipientPublicKey, payloadBytes, aad);
|
|
92
|
+
return {
|
|
93
|
+
type: 'sealed-ml-kem-key@1',
|
|
94
|
+
envelope: 'envelope-hpke@1',
|
|
95
|
+
ciphertext: (0, VaultCrypto_1.toBase64Url)(result.ciphertext),
|
|
96
|
+
ephemeralPublicKey: (0, VaultCrypto_1.toBase64Url)(result.ephemeralPublicKey),
|
|
97
|
+
kid: keypair.kid,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Unwrap a sealed KEM key artifact
|
|
102
|
+
*
|
|
103
|
+
* Decrypts the sealed artifact using HPKE to extract the peer's ML-KEM public key.
|
|
104
|
+
*
|
|
105
|
+
* @param artifact - Sealed artifact received from peer
|
|
106
|
+
* @param recipientSecretKey - Our P-256 private key to decrypt
|
|
107
|
+
* @returns Peer's ML-KEM public key info
|
|
108
|
+
*/
|
|
109
|
+
async unwrapKemKeyArtifact(artifact, recipientSecretKey) {
|
|
110
|
+
this.logger.debug(`Unwrapping KEM key artifact: ${artifact.kid.substring(0, 20)}...`);
|
|
111
|
+
const ciphertext = (0, VaultCrypto_1.fromBase64Url)(artifact.ciphertext);
|
|
112
|
+
const ephemeralPublicKey = (0, VaultCrypto_1.fromBase64Url)(artifact.ephemeralPublicKey);
|
|
113
|
+
// Create AAD (must match encryption)
|
|
114
|
+
const aad = new TextEncoder().encode(`sealed-ml-kem-key:${artifact.kid}`);
|
|
115
|
+
// Decrypt using HPKE
|
|
116
|
+
const result = await this.hpkeService.decrypt(recipientSecretKey, ciphertext, ephemeralPublicKey, aad);
|
|
117
|
+
const payload = JSON.parse(new TextDecoder().decode(result.plaintext));
|
|
118
|
+
return {
|
|
119
|
+
kid: payload.kid,
|
|
120
|
+
publicKey: (0, VaultCrypto_1.fromBase64Url)(payload.publicKey),
|
|
121
|
+
storedAt: new Date().toISOString(),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Store peer's ML-KEM public key in connection metadata
|
|
126
|
+
*
|
|
127
|
+
* This allows retrieving the peer's KEM key later for vault encryption.
|
|
128
|
+
*
|
|
129
|
+
* @param agentContext - Agent context
|
|
130
|
+
* @param connectionId - Connection record ID
|
|
131
|
+
* @param keyInfo - Peer's ML-KEM public key info
|
|
132
|
+
*/
|
|
133
|
+
async storePeerKemKey(agentContext, connectionId, keyInfo) {
|
|
134
|
+
this.logger.debug(`Storing peer KEM key for connection ${connectionId}: ${keyInfo.kid.substring(0, 20)}...`);
|
|
135
|
+
// Get connection record
|
|
136
|
+
const connection = await this.connectionRepository.getById(agentContext, connectionId);
|
|
137
|
+
// Store KEM key in metadata
|
|
138
|
+
const metadata = {
|
|
139
|
+
kid: keyInfo.kid,
|
|
140
|
+
publicKey: (0, VaultCrypto_1.toBase64Url)(keyInfo.publicKey),
|
|
141
|
+
storedAt: keyInfo.storedAt ?? new Date().toISOString(),
|
|
142
|
+
};
|
|
143
|
+
connection.metadata.set(exports.KEM_KEY_METADATA_KEY, metadata);
|
|
144
|
+
// Save connection
|
|
145
|
+
await this.connectionRepository.update(agentContext, connection);
|
|
146
|
+
this.logger.info(`Stored peer KEM key for connection ${connectionId}`);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Retrieve peer's ML-KEM public key from connection metadata
|
|
150
|
+
*
|
|
151
|
+
* @param agentContext - Agent context
|
|
152
|
+
* @param connectionId - Connection record ID
|
|
153
|
+
* @returns Peer's KEM key info, or null if not found
|
|
154
|
+
*/
|
|
155
|
+
async getPeerKemKey(agentContext, connectionId) {
|
|
156
|
+
this.logger.debug(`Retrieving peer KEM key for connection ${connectionId}`);
|
|
157
|
+
// Get connection record
|
|
158
|
+
const connection = await this.connectionRepository.getById(agentContext, connectionId);
|
|
159
|
+
// Get KEM key from metadata
|
|
160
|
+
const metadata = connection.metadata.get(exports.KEM_KEY_METADATA_KEY);
|
|
161
|
+
if (!metadata) {
|
|
162
|
+
this.logger.debug(`No peer KEM key found for connection ${connectionId}`);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
kid: metadata.kid,
|
|
167
|
+
publicKey: (0, VaultCrypto_1.fromBase64Url)(metadata.publicKey),
|
|
168
|
+
storedAt: metadata.storedAt,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Delete peer's ML-KEM public key from connection metadata
|
|
173
|
+
*
|
|
174
|
+
* @param agentContext - Agent context
|
|
175
|
+
* @param connectionId - Connection record ID
|
|
176
|
+
*/
|
|
177
|
+
async deletePeerKemKey(agentContext, connectionId) {
|
|
178
|
+
this.logger.debug(`Deleting peer KEM key for connection ${connectionId}`);
|
|
179
|
+
// Get connection record
|
|
180
|
+
const connection = await this.connectionRepository.getById(agentContext, connectionId);
|
|
181
|
+
// Delete KEM key from metadata
|
|
182
|
+
connection.metadata.delete(exports.KEM_KEY_METADATA_KEY);
|
|
183
|
+
// Save connection
|
|
184
|
+
await this.connectionRepository.update(agentContext, connection);
|
|
185
|
+
this.logger.info(`Deleted peer KEM key for connection ${connectionId}`);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Check if a connection has a peer KEM key
|
|
189
|
+
*
|
|
190
|
+
* @param agentContext - Agent context
|
|
191
|
+
* @param connectionId - Connection record ID
|
|
192
|
+
* @returns True if peer has KEM key stored
|
|
193
|
+
*/
|
|
194
|
+
async hasPeerKemKey(agentContext, connectionId) {
|
|
195
|
+
const keyInfo = await this.getPeerKemKey(agentContext, connectionId);
|
|
196
|
+
return keyInfo !== null;
|
|
197
|
+
}
|
|
198
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
199
|
+
// Local Keypair Storage
|
|
200
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
201
|
+
/**
|
|
202
|
+
* Store a local KEM keypair (including secret key) for a connection
|
|
203
|
+
*
|
|
204
|
+
* Call this after generateKemKeypair() to persist the keypair so it can
|
|
205
|
+
* be retrieved later for vault decryption.
|
|
206
|
+
*
|
|
207
|
+
* @param agentContext - Agent context
|
|
208
|
+
* @param connectionId - Connection to associate the keypair with
|
|
209
|
+
* @param keypair - Full ML-KEM keypair
|
|
210
|
+
*/
|
|
211
|
+
async storeLocalKeypair(agentContext, connectionId, keypair) {
|
|
212
|
+
this.logger.debug(`Storing local KEM keypair for connection ${connectionId}: kid=${keypair.kid.substring(0, 20)}...`);
|
|
213
|
+
// Check for existing keypair on this connection
|
|
214
|
+
const existing = await this.kemKeypairRepository.findByConnectionId(agentContext, connectionId);
|
|
215
|
+
if (existing) {
|
|
216
|
+
this.logger.debug(`Updating existing keypair for connection ${connectionId}`);
|
|
217
|
+
existing.kid = keypair.kid;
|
|
218
|
+
existing.publicKey = (0, VaultCrypto_1.toBase64Url)(keypair.publicKey);
|
|
219
|
+
existing.secretKey = (0, VaultCrypto_1.toBase64Url)(keypair.secretKey);
|
|
220
|
+
await this.kemKeypairRepository.update(agentContext, existing);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const record = new KemKeypairRecord_1.KemKeypairRecord({
|
|
224
|
+
connectionId,
|
|
225
|
+
kid: keypair.kid,
|
|
226
|
+
publicKey: (0, VaultCrypto_1.toBase64Url)(keypair.publicKey),
|
|
227
|
+
secretKey: (0, VaultCrypto_1.toBase64Url)(keypair.secretKey),
|
|
228
|
+
});
|
|
229
|
+
await this.kemKeypairRepository.save(agentContext, record);
|
|
230
|
+
this.logger.info(`Stored local KEM keypair for connection ${connectionId}`);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Get the local KEM keypair for a connection
|
|
234
|
+
*
|
|
235
|
+
* @param agentContext - Agent context
|
|
236
|
+
* @param connectionId - Connection record ID
|
|
237
|
+
* @returns Full keypair including secret key, or null if not found
|
|
238
|
+
*/
|
|
239
|
+
async getLocalKeypair(agentContext, connectionId) {
|
|
240
|
+
const record = await this.kemKeypairRepository.findByConnectionId(agentContext, connectionId);
|
|
241
|
+
if (!record) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
kid: record.kid,
|
|
246
|
+
publicKey: (0, VaultCrypto_1.fromBase64Url)(record.publicKey),
|
|
247
|
+
secretKey: (0, VaultCrypto_1.fromBase64Url)(record.secretKey),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Find a local keypair by its key identifier (kid)
|
|
252
|
+
*
|
|
253
|
+
* This is the primary lookup used during vault decryption: extract recipient
|
|
254
|
+
* kids from vault header, then find which local keypair matches.
|
|
255
|
+
*
|
|
256
|
+
* @param agentContext - Agent context
|
|
257
|
+
* @param kid - Key identifier to search for
|
|
258
|
+
* @returns Keypair and associated connectionId, or null
|
|
259
|
+
*/
|
|
260
|
+
async findKeypairByKid(agentContext, kid) {
|
|
261
|
+
const record = await this.kemKeypairRepository.findByKid(agentContext, kid);
|
|
262
|
+
if (!record) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
keypair: {
|
|
267
|
+
kid: record.kid,
|
|
268
|
+
publicKey: (0, VaultCrypto_1.fromBase64Url)(record.publicKey),
|
|
269
|
+
secretKey: (0, VaultCrypto_1.fromBase64Url)(record.secretKey),
|
|
270
|
+
},
|
|
271
|
+
connectionId: record.connectionId,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Find a local keypair matching any of the given recipient kids
|
|
276
|
+
*
|
|
277
|
+
* Used to find which local key can decrypt a vault when the vault header
|
|
278
|
+
* lists multiple possible recipients.
|
|
279
|
+
*
|
|
280
|
+
* @param agentContext - Agent context
|
|
281
|
+
* @param kids - Set of key identifiers from vault recipients
|
|
282
|
+
* @returns Matching keypair and connectionId, or null
|
|
283
|
+
*/
|
|
284
|
+
async findKeypairByRecipientKids(agentContext, kids) {
|
|
285
|
+
for (const kid of kids) {
|
|
286
|
+
const result = await this.findKeypairByKid(agentContext, kid);
|
|
287
|
+
if (result) {
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Check if a local keypair exists for a connection
|
|
295
|
+
*
|
|
296
|
+
* @param agentContext - Agent context
|
|
297
|
+
* @param connectionId - Connection record ID
|
|
298
|
+
* @returns True if local keypair exists
|
|
299
|
+
*/
|
|
300
|
+
async hasLocalKeypair(agentContext, connectionId) {
|
|
301
|
+
const record = await this.kemKeypairRepository.findByConnectionId(agentContext, connectionId);
|
|
302
|
+
return record !== null;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Delete the local keypair for a connection
|
|
306
|
+
*
|
|
307
|
+
* @param agentContext - Agent context
|
|
308
|
+
* @param connectionId - Connection record ID
|
|
309
|
+
*/
|
|
310
|
+
async deleteLocalKeypair(agentContext, connectionId) {
|
|
311
|
+
await this.kemKeypairRepository.deleteByConnectionId(agentContext, connectionId);
|
|
312
|
+
this.logger.info(`Deleted local KEM keypair for connection ${connectionId}`);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
exports.KemKeyExchangeService = KemKeyExchangeService;
|
|
316
|
+
exports.KemKeyExchangeService = KemKeyExchangeService = __decorate([
|
|
317
|
+
(0, core_1.injectable)(),
|
|
318
|
+
__param(0, (0, core_1.inject)(core_1.InjectionSymbols.Logger)),
|
|
319
|
+
__metadata("design:paramtypes", [Object, core_1.ConnectionRepository,
|
|
320
|
+
HPKEService_1.HPKEService,
|
|
321
|
+
KemKeypairRepository_1.KemKeypairRepository])
|
|
322
|
+
], KemKeyExchangeService);
|
|
323
|
+
//# sourceMappingURL=KemKeyExchangeService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KemKeyExchangeService.js","sourceRoot":"","sources":["../../src/services/KemKeyExchangeService.ts"],"names":[],"mappings":"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"}
|