forkoff 1.0.17 → 1.0.18
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/approval.d.ts +1 -0
- package/dist/approval.js +9 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +62 -16
- package/dist/crypto/e2eeManager.d.ts +49 -52
- package/dist/crypto/e2eeManager.js +256 -181
- package/dist/crypto/encryption.d.ts +8 -10
- package/dist/crypto/encryption.js +29 -94
- package/dist/crypto/index.d.ts +10 -0
- package/dist/crypto/index.js +22 -0
- package/dist/crypto/keyExchange.d.ts +6 -20
- package/dist/crypto/keyExchange.js +18 -110
- package/dist/crypto/keyGeneration.d.ts +2 -13
- package/dist/crypto/keyGeneration.js +14 -88
- package/dist/crypto/keyStorage.d.ts +32 -5
- package/dist/crypto/keyStorage.js +152 -8
- package/dist/crypto/sessionPersistence.d.ts +7 -13
- package/dist/crypto/sessionPersistence.js +108 -33
- package/dist/crypto/types.d.ts +24 -3
- package/dist/crypto/types.js +2 -1
- package/dist/crypto/websocketE2EE.d.ts +6 -17
- package/dist/crypto/websocketE2EE.js +21 -38
- package/dist/index.js +203 -280
- package/dist/integration.d.ts +0 -1
- package/dist/integration.js +2 -4
- package/dist/logger.d.ts +15 -0
- package/dist/logger.js +209 -1
- package/dist/server.d.ts +30 -0
- package/dist/server.js +162 -0
- package/dist/startup.js +15 -6
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +94 -1
- package/dist/tools/claude-process.d.ts +8 -0
- package/dist/tools/claude-process.js +199 -26
- package/dist/tools/claude-sessions.d.ts +1 -0
- package/dist/tools/claude-sessions.js +36 -10
- package/dist/tools/detector.js +11 -3
- package/dist/tools/permission-hook.js +94 -27
- package/dist/tools/permission-ipc.d.ts +1 -0
- package/dist/tools/permission-ipc.js +61 -14
- package/dist/transcript-streamer.d.ts +1 -0
- package/dist/transcript-streamer.js +18 -4
- package/dist/usage-tracker.d.ts +45 -0
- package/dist/usage-tracker.js +243 -0
- package/dist/websocket.d.ts +43 -12
- package/dist/websocket.js +418 -214
- package/package.json +4 -3
- package/dist/__tests__/cli-commands.test.d.ts +0 -6
- package/dist/__tests__/cli-commands.test.d.ts.map +0 -1
- package/dist/__tests__/cli-commands.test.js +0 -213
- package/dist/__tests__/cli-commands.test.js.map +0 -1
- package/dist/__tests__/crypto/e2e-integration.test.d.ts +0 -17
- package/dist/__tests__/crypto/e2e-integration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/e2e-integration.test.js +0 -338
- package/dist/__tests__/crypto/e2e-integration.test.js.map +0 -1
- package/dist/__tests__/crypto/e2eeManager.test.d.ts +0 -2
- package/dist/__tests__/crypto/e2eeManager.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/e2eeManager.test.js +0 -242
- package/dist/__tests__/crypto/e2eeManager.test.js.map +0 -1
- package/dist/__tests__/crypto/encryption.test.d.ts +0 -2
- package/dist/__tests__/crypto/encryption.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/encryption.test.js +0 -116
- package/dist/__tests__/crypto/encryption.test.js.map +0 -1
- package/dist/__tests__/crypto/keyExchange.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyExchange.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyExchange.test.js +0 -84
- package/dist/__tests__/crypto/keyExchange.test.js.map +0 -1
- package/dist/__tests__/crypto/keyGeneration.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyGeneration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyGeneration.test.js +0 -61
- package/dist/__tests__/crypto/keyGeneration.test.js.map +0 -1
- package/dist/__tests__/crypto/keyStorage.test.d.ts +0 -2
- package/dist/__tests__/crypto/keyStorage.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/keyStorage.test.js +0 -133
- package/dist/__tests__/crypto/keyStorage.test.js.map +0 -1
- package/dist/__tests__/crypto/websocketIntegration.test.d.ts +0 -2
- package/dist/__tests__/crypto/websocketIntegration.test.d.ts.map +0 -1
- package/dist/__tests__/crypto/websocketIntegration.test.js +0 -259
- package/dist/__tests__/crypto/websocketIntegration.test.js.map +0 -1
- package/dist/__tests__/startup.test.d.ts +0 -11
- package/dist/__tests__/startup.test.d.ts.map +0 -1
- package/dist/__tests__/startup.test.js +0 -241
- package/dist/__tests__/startup.test.js.map +0 -1
- package/dist/__tests__/tools/claude-process.test.d.ts +0 -8
- package/dist/__tests__/tools/claude-process.test.d.ts.map +0 -1
- package/dist/__tests__/tools/claude-process.test.js +0 -430
- package/dist/__tests__/tools/claude-process.test.js.map +0 -1
- package/dist/__tests__/tools/permission-hook.test.d.ts +0 -17
- package/dist/__tests__/tools/permission-hook.test.d.ts.map +0 -1
- package/dist/__tests__/tools/permission-hook.test.js +0 -616
- package/dist/__tests__/tools/permission-hook.test.js.map +0 -1
- package/dist/__tests__/tools/permission-ipc.test.d.ts +0 -11
- package/dist/__tests__/tools/permission-ipc.test.d.ts.map +0 -1
- package/dist/__tests__/tools/permission-ipc.test.js +0 -612
- package/dist/__tests__/tools/permission-ipc.test.js.map +0 -1
- package/dist/__tests__/websocket.test.d.ts +0 -13
- package/dist/__tests__/websocket.test.d.ts.map +0 -1
- package/dist/__tests__/websocket.test.js +0 -204
- package/dist/__tests__/websocket.test.js.map +0 -1
- package/dist/api.d.ts +0 -44
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -76
- package/dist/api.js.map +0 -1
- package/dist/approval.d.ts.map +0 -1
- package/dist/approval.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/crypto/e2eeManager.d.ts.map +0 -1
- package/dist/crypto/e2eeManager.js.map +0 -1
- package/dist/crypto/encryption.d.ts.map +0 -1
- package/dist/crypto/encryption.js.map +0 -1
- package/dist/crypto/keyExchange.d.ts.map +0 -1
- package/dist/crypto/keyExchange.js.map +0 -1
- package/dist/crypto/keyGeneration.d.ts.map +0 -1
- package/dist/crypto/keyGeneration.js.map +0 -1
- package/dist/crypto/keyStorage.d.ts.map +0 -1
- package/dist/crypto/keyStorage.js.map +0 -1
- package/dist/crypto/sessionPersistence.d.ts.map +0 -1
- package/dist/crypto/sessionPersistence.js.map +0 -1
- package/dist/crypto/types.d.ts.map +0 -1
- package/dist/crypto/types.js.map +0 -1
- package/dist/crypto/websocketE2EE.d.ts.map +0 -1
- package/dist/crypto/websocketE2EE.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integration.d.ts.map +0 -1
- package/dist/integration.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/startup.d.ts.map +0 -1
- package/dist/startup.js.map +0 -1
- package/dist/terminal.d.ts.map +0 -1
- package/dist/terminal.js.map +0 -1
- package/dist/tools/__tests__/claude-sessions.test.d.ts +0 -2
- package/dist/tools/__tests__/claude-sessions.test.d.ts.map +0 -1
- package/dist/tools/__tests__/claude-sessions.test.js +0 -306
- package/dist/tools/__tests__/claude-sessions.test.js.map +0 -1
- package/dist/tools/claude-hooks.d.ts.map +0 -1
- package/dist/tools/claude-hooks.js.map +0 -1
- package/dist/tools/claude-process.d.ts.map +0 -1
- package/dist/tools/claude-process.js.map +0 -1
- package/dist/tools/claude-sessions.d.ts.map +0 -1
- package/dist/tools/claude-sessions.js.map +0 -1
- package/dist/tools/detector.d.ts.map +0 -1
- package/dist/tools/detector.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/permission-hook.d.ts.map +0 -1
- package/dist/tools/permission-hook.js.map +0 -1
- package/dist/tools/permission-ipc.d.ts.map +0 -1
- package/dist/tools/permission-ipc.js.map +0 -1
- package/dist/transcript-streamer.d.ts.map +0 -1
- package/dist/transcript-streamer.js.map +0 -1
- package/dist/websocket.d.ts.map +0 -1
- package/dist/websocket.js.map +0 -1
- package/jest.config.js +0 -18
|
@@ -1,111 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
35
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
6
|
exports.encrypt = encrypt;
|
|
37
7
|
exports.decrypt = decrypt;
|
|
38
|
-
const crypto = __importStar(require("crypto"));
|
|
39
|
-
const ALGORITHM = 'aes-256-gcm';
|
|
40
|
-
const NONCE_LENGTH = 12; // 96 bits for AES-GCM
|
|
41
|
-
const AUTH_TAG_LENGTH = 16; // 128 bits for AES-GCM
|
|
42
8
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
9
|
+
* Encryption/Decryption Service
|
|
10
|
+
* Uses NaCl secretbox (XSalsa20-Poly1305) for symmetric encryption.
|
|
11
|
+
* Compatible with mobile app's tweetnacl implementation.
|
|
12
|
+
*/
|
|
13
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
14
|
+
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
15
|
+
/**
|
|
16
|
+
* Encrypt a plaintext string using NaCl secretbox.
|
|
17
|
+
* @param plaintext - The message to encrypt
|
|
18
|
+
* @param key - 32-byte shared secret key
|
|
19
|
+
* @returns EncryptedPayload with Base64-encoded ciphertext and nonce
|
|
48
20
|
*/
|
|
49
21
|
function encrypt(plaintext, key) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Generate random nonce (12 bytes)
|
|
54
|
-
const nonce = crypto.randomBytes(NONCE_LENGTH);
|
|
55
|
-
// Create cipher
|
|
56
|
-
const cipher = crypto.createCipheriv(ALGORITHM, key, nonce);
|
|
57
|
-
// Encrypt
|
|
58
|
-
const ciphertext = Buffer.concat([
|
|
59
|
-
cipher.update(plaintext, 'utf8'),
|
|
60
|
-
cipher.final(),
|
|
61
|
-
]);
|
|
62
|
-
// Get authentication tag
|
|
63
|
-
const authTag = cipher.getAuthTag();
|
|
64
|
-
if (authTag.length !== AUTH_TAG_LENGTH) {
|
|
65
|
-
throw new Error('Auth tag must be 16 bytes');
|
|
66
|
-
}
|
|
22
|
+
const nonce = tweetnacl_1.default.randomBytes(tweetnacl_1.default.secretbox.nonceLength); // 24 bytes
|
|
23
|
+
const messageBytes = (0, tweetnacl_util_1.decodeUTF8)(plaintext);
|
|
24
|
+
const ciphertext = tweetnacl_1.default.secretbox(messageBytes, nonce, key);
|
|
67
25
|
return {
|
|
68
|
-
ciphertext:
|
|
69
|
-
nonce:
|
|
70
|
-
authTag: authTag.toString('base64'),
|
|
26
|
+
ciphertext: (0, tweetnacl_util_1.encodeBase64)(ciphertext),
|
|
27
|
+
nonce: (0, tweetnacl_util_1.encodeBase64)(nonce),
|
|
71
28
|
};
|
|
72
29
|
}
|
|
73
30
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* @param
|
|
77
|
-
* @
|
|
78
|
-
* @returns Decrypted plaintext
|
|
31
|
+
* Decrypt an EncryptedPayload back to plaintext.
|
|
32
|
+
* @param payload - The encrypted payload (ciphertext + nonce)
|
|
33
|
+
* @param key - 32-byte shared secret key (must match encryption key)
|
|
34
|
+
* @returns Decrypted plaintext string
|
|
79
35
|
* @throws Error if decryption fails (wrong key, tampered data, etc.)
|
|
80
36
|
*/
|
|
81
37
|
function decrypt(payload, key) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const nonce = Buffer.from(payload.nonce, 'base64');
|
|
88
|
-
const authTag = Buffer.from(payload.authTag, 'base64');
|
|
89
|
-
if (nonce.length !== NONCE_LENGTH) {
|
|
90
|
-
throw new Error('Nonce must be 12 bytes');
|
|
91
|
-
}
|
|
92
|
-
if (authTag.length !== AUTH_TAG_LENGTH) {
|
|
93
|
-
throw new Error('Auth tag must be 16 bytes');
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
// Create decipher
|
|
97
|
-
const decipher = crypto.createDecipheriv(ALGORITHM, key, nonce);
|
|
98
|
-
// Set auth tag for verification
|
|
99
|
-
decipher.setAuthTag(authTag);
|
|
100
|
-
// Decrypt
|
|
101
|
-
const plaintext = Buffer.concat([
|
|
102
|
-
decipher.update(ciphertext),
|
|
103
|
-
decipher.final(),
|
|
104
|
-
]);
|
|
105
|
-
return plaintext.toString('utf8');
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
throw new Error(`Decryption failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
38
|
+
const ciphertext = (0, tweetnacl_util_1.decodeBase64)(payload.ciphertext);
|
|
39
|
+
const nonce = (0, tweetnacl_util_1.decodeBase64)(payload.nonce);
|
|
40
|
+
const decrypted = tweetnacl_1.default.secretbox.open(ciphertext, nonce, key);
|
|
41
|
+
if (!decrypted) {
|
|
42
|
+
throw new Error('E2EE: Decryption failed - message may be tampered or wrong key');
|
|
109
43
|
}
|
|
44
|
+
return (0, tweetnacl_util_1.encodeUTF8)(decrypted);
|
|
110
45
|
}
|
|
111
46
|
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2EE Crypto Module - Barrel Export
|
|
3
|
+
*/
|
|
4
|
+
export { generateKeyPair } from './keyGeneration';
|
|
5
|
+
export { computeSharedKey } from './keyExchange';
|
|
6
|
+
export { encrypt, decrypt } from './encryption';
|
|
7
|
+
export { storePrivateKey, getPrivateKey, storeSessionKey, getSessionKey, clearSessionKeys } from './keyStorage';
|
|
8
|
+
export { E2EEManager } from './e2eeManager';
|
|
9
|
+
export type { E2EEKeyPair, EncryptedPayload, EncryptedMessage, SessionKeys, KeyExchangeInit, KeyExchangeAck, E2EESessionStatus, } from './types';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.E2EEManager = exports.clearSessionKeys = exports.getSessionKey = exports.storeSessionKey = exports.getPrivateKey = exports.storePrivateKey = exports.decrypt = exports.encrypt = exports.computeSharedKey = exports.generateKeyPair = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* E2EE Crypto Module - Barrel Export
|
|
6
|
+
*/
|
|
7
|
+
var keyGeneration_1 = require("./keyGeneration");
|
|
8
|
+
Object.defineProperty(exports, "generateKeyPair", { enumerable: true, get: function () { return keyGeneration_1.generateKeyPair; } });
|
|
9
|
+
var keyExchange_1 = require("./keyExchange");
|
|
10
|
+
Object.defineProperty(exports, "computeSharedKey", { enumerable: true, get: function () { return keyExchange_1.computeSharedKey; } });
|
|
11
|
+
var encryption_1 = require("./encryption");
|
|
12
|
+
Object.defineProperty(exports, "encrypt", { enumerable: true, get: function () { return encryption_1.encrypt; } });
|
|
13
|
+
Object.defineProperty(exports, "decrypt", { enumerable: true, get: function () { return encryption_1.decrypt; } });
|
|
14
|
+
var keyStorage_1 = require("./keyStorage");
|
|
15
|
+
Object.defineProperty(exports, "storePrivateKey", { enumerable: true, get: function () { return keyStorage_1.storePrivateKey; } });
|
|
16
|
+
Object.defineProperty(exports, "getPrivateKey", { enumerable: true, get: function () { return keyStorage_1.getPrivateKey; } });
|
|
17
|
+
Object.defineProperty(exports, "storeSessionKey", { enumerable: true, get: function () { return keyStorage_1.storeSessionKey; } });
|
|
18
|
+
Object.defineProperty(exports, "getSessionKey", { enumerable: true, get: function () { return keyStorage_1.getSessionKey; } });
|
|
19
|
+
Object.defineProperty(exports, "clearSessionKeys", { enumerable: true, get: function () { return keyStorage_1.clearSessionKeys; } });
|
|
20
|
+
var e2eeManager_1 = require("./e2eeManager");
|
|
21
|
+
Object.defineProperty(exports, "E2EEManager", { enumerable: true, get: function () { return e2eeManager_1.E2EEManager; } });
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Compute a shared secret key from a private key and a remote public key.
|
|
3
|
+
* Uses NaCl's box.before which performs X25519 ECDH + HSalsa20 key derivation.
|
|
3
4
|
*
|
|
4
|
-
* @param
|
|
5
|
-
* @param
|
|
6
|
-
* @returns
|
|
5
|
+
* @param myPrivateKeyB64 - Base64-encoded 32-byte private key
|
|
6
|
+
* @param theirPublicKeyB64 - Base64-encoded 32-byte public key
|
|
7
|
+
* @returns 32-byte shared key suitable for NaCl secretbox encryption
|
|
7
8
|
*/
|
|
8
|
-
export declare function
|
|
9
|
-
/**
|
|
10
|
-
* Derives a session encryption key from a shared secret using HKDF
|
|
11
|
-
*
|
|
12
|
-
* @param sharedSecret - Shared secret from X25519 key exchange
|
|
13
|
-
* @returns Derived session key (32 bytes for AES-256)
|
|
14
|
-
*/
|
|
15
|
-
export declare function deriveSessionKey(sharedSecret: Uint8Array): Uint8Array;
|
|
16
|
-
/**
|
|
17
|
-
* Performs complete key exchange: computes shared secret and derives session key
|
|
18
|
-
*
|
|
19
|
-
* @param myPrivateKey - My Base64-encoded X25519 private key
|
|
20
|
-
* @param theirPublicKey - Their Base64-encoded X25519 public key
|
|
21
|
-
* @returns Derived session encryption key (32 bytes for AES-256-GCM)
|
|
22
|
-
*/
|
|
23
|
-
export declare function performKeyExchange(myPrivateKey: string, theirPublicKey: string): Uint8Array;
|
|
9
|
+
export declare function computeSharedKey(myPrivateKeyB64: string, theirPublicKeyB64: string): Uint8Array;
|
|
24
10
|
//# sourceMappingURL=keyExchange.d.ts.map
|
|
@@ -1,119 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
35
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
37
|
-
exports.deriveSessionKey = deriveSessionKey;
|
|
38
|
-
exports.performKeyExchange = performKeyExchange;
|
|
39
|
-
const crypto = __importStar(require("crypto"));
|
|
6
|
+
exports.computeSharedKey = computeSharedKey;
|
|
40
7
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* @param publicKey - Base64-encoded X25519 public key (32 bytes)
|
|
45
|
-
* @returns Shared secret (32 bytes)
|
|
46
|
-
*/
|
|
47
|
-
function computeSharedSecret(privateKey, publicKey) {
|
|
48
|
-
const privateKeyBytes = Buffer.from(privateKey, 'base64');
|
|
49
|
-
const publicKeyBytes = Buffer.from(publicKey, 'base64');
|
|
50
|
-
if (privateKeyBytes.length !== 32) {
|
|
51
|
-
throw new Error('Private key must be 32 bytes');
|
|
52
|
-
}
|
|
53
|
-
if (publicKeyBytes.length !== 32) {
|
|
54
|
-
throw new Error('Public key must be 32 bytes');
|
|
55
|
-
}
|
|
56
|
-
// Create X25519 private key object from raw bytes
|
|
57
|
-
const privateKeyObject = crypto.createPrivateKey({
|
|
58
|
-
key: Buffer.concat([
|
|
59
|
-
// PKCS#8 header for X25519
|
|
60
|
-
Buffer.from([
|
|
61
|
-
0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e,
|
|
62
|
-
0x04, 0x22, 0x04, 0x20,
|
|
63
|
-
]),
|
|
64
|
-
privateKeyBytes,
|
|
65
|
-
]),
|
|
66
|
-
format: 'der',
|
|
67
|
-
type: 'pkcs8',
|
|
68
|
-
});
|
|
69
|
-
// Create X25519 public key object from raw bytes
|
|
70
|
-
const publicKeyObject = crypto.createPublicKey({
|
|
71
|
-
key: Buffer.concat([
|
|
72
|
-
// SPKI header for X25519
|
|
73
|
-
Buffer.from([
|
|
74
|
-
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00,
|
|
75
|
-
]),
|
|
76
|
-
publicKeyBytes,
|
|
77
|
-
]),
|
|
78
|
-
format: 'der',
|
|
79
|
-
type: 'spki',
|
|
80
|
-
});
|
|
81
|
-
// Perform ECDH to compute shared secret
|
|
82
|
-
const sharedSecret = crypto.diffieHellman({
|
|
83
|
-
privateKey: privateKeyObject,
|
|
84
|
-
publicKey: publicKeyObject,
|
|
85
|
-
});
|
|
86
|
-
return new Uint8Array(sharedSecret);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Derives a session encryption key from a shared secret using HKDF
|
|
90
|
-
*
|
|
91
|
-
* @param sharedSecret - Shared secret from X25519 key exchange
|
|
92
|
-
* @returns Derived session key (32 bytes for AES-256)
|
|
8
|
+
* Key Exchange Service
|
|
9
|
+
* Performs X25519 Diffie-Hellman key exchange using NaCl box.before.
|
|
10
|
+
* Compatible with mobile app's tweetnacl implementation.
|
|
93
11
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
throw new Error('Shared secret must be 32 bytes');
|
|
97
|
-
}
|
|
98
|
-
// Use HKDF-SHA256 to derive session key
|
|
99
|
-
// Info string provides domain separation
|
|
100
|
-
const info = Buffer.from('forkoff-e2ee-session-key-v1', 'utf8');
|
|
101
|
-
const salt = Buffer.alloc(0); // Empty salt (optional for HKDF)
|
|
102
|
-
// Use synchronous HKDF (blocking but fast for 32-byte output)
|
|
103
|
-
const derivedKey = crypto.hkdfSync('sha256', Buffer.from(sharedSecret), salt, info, 32 // Output length: 32 bytes for AES-256
|
|
104
|
-
);
|
|
105
|
-
return new Uint8Array(derivedKey);
|
|
106
|
-
}
|
|
12
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
13
|
+
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
107
14
|
/**
|
|
108
|
-
*
|
|
15
|
+
* Compute a shared secret key from a private key and a remote public key.
|
|
16
|
+
* Uses NaCl's box.before which performs X25519 ECDH + HSalsa20 key derivation.
|
|
109
17
|
*
|
|
110
|
-
* @param
|
|
111
|
-
* @param
|
|
112
|
-
* @returns
|
|
18
|
+
* @param myPrivateKeyB64 - Base64-encoded 32-byte private key
|
|
19
|
+
* @param theirPublicKeyB64 - Base64-encoded 32-byte public key
|
|
20
|
+
* @returns 32-byte shared key suitable for NaCl secretbox encryption
|
|
113
21
|
*/
|
|
114
|
-
function
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
return
|
|
22
|
+
function computeSharedKey(myPrivateKeyB64, theirPublicKeyB64) {
|
|
23
|
+
const myPrivateKey = (0, tweetnacl_util_1.decodeBase64)(myPrivateKeyB64);
|
|
24
|
+
const theirPublicKey = (0, tweetnacl_util_1.decodeBase64)(theirPublicKeyB64);
|
|
25
|
+
return tweetnacl_1.default.box.before(theirPublicKey, myPrivateKey);
|
|
118
26
|
}
|
|
119
27
|
//# sourceMappingURL=keyExchange.js.map
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
import { E2EEKeyPair } from './types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* Uses
|
|
5
|
-
*
|
|
6
|
-
* @returns E2EEKeyPair with Base64-encoded public and private keys (32 bytes each)
|
|
3
|
+
* Generate a new X25519 key pair for Diffie-Hellman key exchange.
|
|
4
|
+
* Uses NaCl's box keypair which generates X25519 keys.
|
|
7
5
|
*/
|
|
8
6
|
export declare function generateKeyPair(): E2EEKeyPair;
|
|
9
|
-
/**
|
|
10
|
-
* Generates a deterministic X25519 key pair from a seed
|
|
11
|
-
* Useful for testing and key derivation
|
|
12
|
-
*
|
|
13
|
-
* @param seed - 32-byte buffer to use as the private key seed
|
|
14
|
-
* @returns E2EEKeyPair with Base64-encoded public and private keys
|
|
15
|
-
* @throws Error if seed is not 32 bytes
|
|
16
|
-
*/
|
|
17
|
-
export declare function generateKeyPairFromSeed(seed: Buffer): E2EEKeyPair;
|
|
18
7
|
//# sourceMappingURL=keyGeneration.d.ts.map
|
|
@@ -1,99 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
35
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
6
|
exports.generateKeyPair = generateKeyPair;
|
|
37
|
-
exports.generateKeyPairFromSeed = generateKeyPairFromSeed;
|
|
38
|
-
const crypto = __importStar(require("crypto"));
|
|
39
7
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @returns E2EEKeyPair with Base64-encoded public and private keys (32 bytes each)
|
|
8
|
+
* Key Generation Service
|
|
9
|
+
* Generates X25519 key pairs for E2EE using tweetnacl.
|
|
10
|
+
* Compatible with mobile app's tweetnacl implementation.
|
|
44
11
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
publicKeyEncoding: {
|
|
48
|
-
type: 'spki',
|
|
49
|
-
format: 'der',
|
|
50
|
-
},
|
|
51
|
-
privateKeyEncoding: {
|
|
52
|
-
type: 'pkcs8',
|
|
53
|
-
format: 'der',
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
// Extract raw 32-byte keys from DER-encoded buffers
|
|
57
|
-
// X25519 public key: last 32 bytes of SPKI
|
|
58
|
-
// X25519 private key: last 32 bytes of PKCS8
|
|
59
|
-
const rawPublicKey = publicKey.slice(-32);
|
|
60
|
-
const rawPrivateKey = privateKey.slice(-32);
|
|
61
|
-
return {
|
|
62
|
-
publicKey: rawPublicKey.toString('base64'),
|
|
63
|
-
privateKey: rawPrivateKey.toString('base64'),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
12
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
13
|
+
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
66
14
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* @param seed - 32-byte buffer to use as the private key seed
|
|
71
|
-
* @returns E2EEKeyPair with Base64-encoded public and private keys
|
|
72
|
-
* @throws Error if seed is not 32 bytes
|
|
15
|
+
* Generate a new X25519 key pair for Diffie-Hellman key exchange.
|
|
16
|
+
* Uses NaCl's box keypair which generates X25519 keys.
|
|
73
17
|
*/
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
throw new Error('Seed must be exactly 32 bytes');
|
|
77
|
-
}
|
|
78
|
-
// In X25519, the private key IS the seed (32 random bytes)
|
|
79
|
-
// The public key is derived: publicKey = privateKey * basepoint
|
|
80
|
-
const privateKeyObject = crypto.createPrivateKey({
|
|
81
|
-
key: Buffer.concat([
|
|
82
|
-
Buffer.from([0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20]),
|
|
83
|
-
seed,
|
|
84
|
-
]),
|
|
85
|
-
format: 'der',
|
|
86
|
-
type: 'pkcs8',
|
|
87
|
-
});
|
|
88
|
-
const publicKeyObject = crypto.createPublicKey(privateKeyObject);
|
|
89
|
-
// Export raw keys
|
|
90
|
-
const publicKeyDER = publicKeyObject.export({ type: 'spki', format: 'der' });
|
|
91
|
-
const privateKeyDER = privateKeyObject.export({ type: 'pkcs8', format: 'der' });
|
|
92
|
-
const rawPublicKey = publicKeyDER.slice(-32);
|
|
93
|
-
const rawPrivateKey = privateKeyDER.slice(-32);
|
|
18
|
+
function generateKeyPair() {
|
|
19
|
+
const keyPair = tweetnacl_1.default.box.keyPair();
|
|
94
20
|
return {
|
|
95
|
-
publicKey:
|
|
96
|
-
privateKey:
|
|
21
|
+
publicKey: (0, tweetnacl_util_1.encodeBase64)(keyPair.publicKey),
|
|
22
|
+
privateKey: (0, tweetnacl_util_1.encodeBase64)(keyPair.secretKey),
|
|
97
23
|
};
|
|
98
24
|
}
|
|
99
25
|
//# sourceMappingURL=keyGeneration.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SessionKeys } from './types';
|
|
1
|
+
import { SessionKeys, SigningKeyPair } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Stores private key in OS keychain
|
|
4
4
|
* @param deviceId - Device ID
|
|
@@ -17,16 +17,16 @@ export declare function getPrivateKey(deviceId: string): Promise<string | null>;
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function deletePrivateKey(deviceId: string): Promise<void>;
|
|
19
19
|
/**
|
|
20
|
-
* Stores session
|
|
20
|
+
* Stores session key in memory
|
|
21
21
|
* Session keys are ephemeral and not persisted to disk
|
|
22
22
|
*
|
|
23
23
|
* @param deviceId - Target device ID
|
|
24
|
-
* @param
|
|
24
|
+
* @param sharedKey - NaCl secretbox shared key (32 bytes)
|
|
25
25
|
* @param sessionId - Unique session identifier
|
|
26
26
|
*/
|
|
27
|
-
export declare function storeSessionKey(deviceId: string,
|
|
27
|
+
export declare function storeSessionKey(deviceId: string, sharedKey: Uint8Array, sessionId: string): void;
|
|
28
28
|
/**
|
|
29
|
-
* Retrieves session
|
|
29
|
+
* Retrieves session key from memory
|
|
30
30
|
* @param deviceId - Target device ID
|
|
31
31
|
* @returns SessionKeys or null if not found
|
|
32
32
|
*/
|
|
@@ -36,4 +36,31 @@ export declare function getSessionKey(deviceId: string): SessionKeys | null;
|
|
|
36
36
|
* Called on disconnect or logout
|
|
37
37
|
*/
|
|
38
38
|
export declare function clearSessionKeys(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Stores the Ed25519 signing key pair in OS keychain
|
|
41
|
+
*/
|
|
42
|
+
export declare function storeSigningKeyPair(deviceId: string, keyPair: SigningKeyPair): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Retrieves the Ed25519 signing key pair from OS keychain
|
|
45
|
+
*/
|
|
46
|
+
export declare function getSigningKeyPair(deviceId: string): Promise<SigningKeyPair | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Load trusted peer keys from disk into memory.
|
|
49
|
+
* Called once at init time. Validates file ownership and permissions.
|
|
50
|
+
*/
|
|
51
|
+
export declare function loadTrustedPeerKeys(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Get the trusted identity public key for a peer device (TOFU).
|
|
54
|
+
* Returns null if no key is stored (first contact).
|
|
55
|
+
*/
|
|
56
|
+
export declare function getTrustedPeerKey(deviceId: string): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Store a peer's identity public key (TOFU — Trust On First Use).
|
|
59
|
+
* Returns false if a DIFFERENT key is already stored (potential MITM).
|
|
60
|
+
*/
|
|
61
|
+
export declare function trustPeerKey(deviceId: string, identityPublicKey: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Remove a peer's trusted identity key (used on re-pair to reset TOFU).
|
|
64
|
+
*/
|
|
65
|
+
export declare function removeTrustedPeerKey(deviceId: string): void;
|
|
39
66
|
//# sourceMappingURL=keyStorage.d.ts.map
|