@tuskydp/cli 0.3.0 → 0.4.0
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/CHANGELOG.md +19 -0
- package/dist/src/commands/account.d.ts.map +1 -1
- package/dist/src/commands/account.js +0 -1
- package/dist/src/commands/account.js.map +1 -1
- package/dist/src/commands/auth.d.ts.map +1 -1
- package/dist/src/commands/auth.js +8 -5
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/download.d.ts.map +1 -1
- package/dist/src/commands/download.js +2 -59
- package/dist/src/commands/download.js.map +1 -1
- package/dist/src/commands/export.d.ts +5 -26
- package/dist/src/commands/export.d.ts.map +1 -1
- package/dist/src/commands/export.js +6 -46
- package/dist/src/commands/export.js.map +1 -1
- package/dist/src/commands/files.js +2 -2
- package/dist/src/commands/files.js.map +1 -1
- package/dist/src/commands/mcp.d.ts.map +1 -1
- package/dist/src/commands/mcp.js +15 -9
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/sui.d.ts +3 -0
- package/dist/src/commands/sui.d.ts.map +1 -0
- package/dist/src/commands/sui.js +64 -0
- package/dist/src/commands/sui.js.map +1 -0
- package/dist/src/commands/trash.js +1 -1
- package/dist/src/commands/trash.js.map +1 -1
- package/dist/src/commands/upload.d.ts.map +1 -1
- package/dist/src/commands/upload.js +3 -49
- package/dist/src/commands/upload.js.map +1 -1
- package/dist/src/commands/vault.d.ts.map +1 -1
- package/dist/src/commands/vault.js +2 -24
- package/dist/src/commands/vault.js.map +1 -1
- package/dist/src/config.d.ts +2 -2
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +2 -3
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.js +2 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/resolve.d.ts.map +1 -1
- package/dist/src/lib/resolve.js +4 -5
- package/dist/src/lib/resolve.js.map +1 -1
- package/dist/src/mcp/context.d.ts +1 -9
- package/dist/src/mcp/context.d.ts.map +1 -1
- package/dist/src/mcp/context.js +1 -2
- package/dist/src/mcp/context.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +0 -58
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/account.d.ts.map +1 -1
- package/dist/src/mcp/tools/account.js +1 -3
- package/dist/src/mcp/tools/account.js.map +1 -1
- package/dist/src/mcp/tools/files.d.ts +2 -3
- package/dist/src/mcp/tools/files.d.ts.map +1 -1
- package/dist/src/mcp/tools/files.js +18 -56
- package/dist/src/mcp/tools/files.js.map +1 -1
- package/dist/src/mcp/tools/vaults.js +2 -2
- package/dist/src/mcp/tools/vaults.js.map +1 -1
- package/dist/src/tui/files-panel.d.ts +0 -1
- package/dist/src/tui/files-panel.d.ts.map +1 -1
- package/dist/src/tui/files-panel.js +1 -2
- package/dist/src/tui/files-panel.js.map +1 -1
- package/dist/src/tui/index.d.ts.map +1 -1
- package/dist/src/tui/index.js +7 -42
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/overview.d.ts.map +1 -1
- package/dist/src/tui/overview.js +2 -6
- package/dist/src/tui/overview.js.map +1 -1
- package/dist/src/tui/trash-screen.js +1 -1
- package/dist/src/tui/trash-screen.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/seal.test.ts +7 -54
- package/src/commands/account.ts +0 -1
- package/src/commands/auth.ts +7 -5
- package/src/commands/download.ts +2 -63
- package/src/commands/export.ts +7 -67
- package/src/commands/files.ts +2 -2
- package/src/commands/mcp.ts +16 -10
- package/src/commands/sui.ts +69 -0
- package/src/commands/trash.ts +1 -1
- package/src/commands/upload.ts +3 -59
- package/src/commands/vault.ts +2 -23
- package/src/config.ts +3 -4
- package/src/index.ts +2 -4
- package/src/lib/resolve.ts +3 -4
- package/src/mcp/context.ts +1 -11
- package/src/mcp/server.ts +0 -69
- package/src/mcp/tools/account.ts +1 -3
- package/src/mcp/tools/files.ts +19 -70
- package/src/mcp/tools/vaults.ts +3 -3
- package/src/tui/files-panel.ts +1 -3
- package/src/tui/index.ts +7 -51
- package/src/tui/overview.ts +2 -5
- package/src/tui/trash-screen.ts +1 -1
- package/dist/src/commands/decrypt.d.ts +0 -15
- package/dist/src/commands/decrypt.d.ts.map +0 -1
- package/dist/src/commands/decrypt.js +0 -256
- package/dist/src/commands/decrypt.js.map +0 -1
- package/dist/src/commands/encryption.d.ts +0 -3
- package/dist/src/commands/encryption.d.ts.map +0 -1
- package/dist/src/commands/encryption.js +0 -254
- package/dist/src/commands/encryption.js.map +0 -1
- package/dist/src/crypto.d.ts +0 -32
- package/dist/src/crypto.d.ts.map +0 -1
- package/dist/src/crypto.js +0 -121
- package/dist/src/crypto.js.map +0 -1
- package/dist/src/lib/keyring.d.ts +0 -4
- package/dist/src/lib/keyring.d.ts.map +0 -1
- package/dist/src/lib/keyring.js +0 -49
- package/dist/src/lib/keyring.js.map +0 -1
- package/src/__tests__/crypto.test.ts +0 -315
- package/src/commands/decrypt.ts +0 -309
- package/src/commands/encryption.ts +0 -305
- package/src/crypto.ts +0 -165
- package/src/lib/keyring.ts +0 -50
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `tusky decrypt` — Decrypt a file downloaded from Walrus.
|
|
3
|
-
*
|
|
4
|
-
* Works in two modes:
|
|
5
|
-
* 1. With --export <manifest.json> — reads wrappedKey/iv from the export
|
|
6
|
-
* manifest, derives master key from passphrase + salt. Fully offline.
|
|
7
|
-
* 2. Without --export — fetches encryption params from the Tusky API and
|
|
8
|
-
* looks up the file metadata by ID. Requires API access.
|
|
9
|
-
*
|
|
10
|
-
* In both modes, the passphrase is resolved from:
|
|
11
|
-
* --passphrase flag > TUSKYDP_PASSWORD env var > interactive prompt
|
|
12
|
-
*/
|
|
13
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
14
|
-
import { resolve, basename } from 'path';
|
|
15
|
-
import chalk from 'chalk';
|
|
16
|
-
import ora from 'ora';
|
|
17
|
-
import inquirer from 'inquirer';
|
|
18
|
-
import { getApiUrl, getApiKey } from '../config.js';
|
|
19
|
-
import { createSDKClient } from '../sdk.js';
|
|
20
|
-
import { loadMasterKey } from '../lib/keyring.js';
|
|
21
|
-
import { deriveMasterKey, verifyPassphrase, unwrapMasterKey, decryptBuffer, } from '../crypto.js';
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Helpers
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
/**
|
|
26
|
-
* Resolve the master key. Priority:
|
|
27
|
-
* 1. Session keyring (~/.tusky/session.enc)
|
|
28
|
-
* 2. Passphrase derivation (requires API or --salt/--encrypted-master-key)
|
|
29
|
-
*/
|
|
30
|
-
async function resolveMasterKey(options) {
|
|
31
|
-
// Try session keyring first
|
|
32
|
-
const sessionKey = loadMasterKey();
|
|
33
|
-
if (sessionKey)
|
|
34
|
-
return sessionKey;
|
|
35
|
-
// Need passphrase
|
|
36
|
-
let passphrase = options.passphrase ?? process.env.TUSKYDP_PASSWORD;
|
|
37
|
-
if (!passphrase) {
|
|
38
|
-
const answers = await inquirer.prompt([{
|
|
39
|
-
type: 'password',
|
|
40
|
-
name: 'passphrase',
|
|
41
|
-
message: 'Enter encryption passphrase:',
|
|
42
|
-
mask: '*',
|
|
43
|
-
}]);
|
|
44
|
-
passphrase = answers.passphrase;
|
|
45
|
-
}
|
|
46
|
-
if (!options.salt) {
|
|
47
|
-
throw new Error('Cannot derive master key: salt is required. Use --export with an export manifest, or ensure the Tusky API is accessible.');
|
|
48
|
-
}
|
|
49
|
-
const salt = Buffer.from(options.salt, 'base64');
|
|
50
|
-
const wrappingKey = deriveMasterKey(passphrase, salt);
|
|
51
|
-
// Verify if we have a verifier
|
|
52
|
-
if (options.verifier) {
|
|
53
|
-
const verifierBuf = Buffer.from(options.verifier, 'base64');
|
|
54
|
-
if (!verifyPassphrase(wrappingKey, verifierBuf)) {
|
|
55
|
-
throw new Error('Invalid passphrase.');
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// Unwrap master key if account has one
|
|
59
|
-
if (options.encryptedMasterKey) {
|
|
60
|
-
return unwrapMasterKey(Buffer.from(options.encryptedMasterKey, 'base64'), wrappingKey);
|
|
61
|
-
}
|
|
62
|
-
// Legacy: wrapping key IS the master key
|
|
63
|
-
return wrappingKey;
|
|
64
|
-
}
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
// Command registration
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
async function readStdin() {
|
|
69
|
-
return new Promise((resolve, reject) => {
|
|
70
|
-
const chunks = [];
|
|
71
|
-
process.stdin.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
72
|
-
process.stdin.on('end', () => resolve(Buffer.concat(chunks)));
|
|
73
|
-
process.stdin.on('error', reject);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
export function registerDecryptCommand(program) {
|
|
77
|
-
program
|
|
78
|
-
.command('decrypt [encrypted-file]')
|
|
79
|
-
.description('Decrypt a file downloaded from Walrus using your encryption passphrase')
|
|
80
|
-
.option('-o, --output <path>', 'Output path for decrypted file')
|
|
81
|
-
.option('--stdin', 'Read ciphertext from stdin (for sandboxed agents without filesystem access)')
|
|
82
|
-
.option('--stdout', 'Write plaintext to stdout instead of a file')
|
|
83
|
-
.option('--file-id <id>', 'Tusky file ID (to look up wrappedKey/iv from API)')
|
|
84
|
-
.option('--export <path>', 'Path to tusky-export.json manifest (for offline decryption)')
|
|
85
|
-
.option('--passphrase <passphrase>', 'Encryption passphrase (also reads TUSKYDP_PASSWORD env var)')
|
|
86
|
-
.option('--wrapped-key <key>', 'Per-file wrapped key (base64, from export manifest)')
|
|
87
|
-
.option('--iv <iv>', 'Per-file encryption IV (base64, from export manifest)')
|
|
88
|
-
.option('--checksum <sha256>', 'Expected plaintext SHA-256 checksum (hex)')
|
|
89
|
-
.action(async (encryptedFile, options) => {
|
|
90
|
-
// When piping to stdout, send spinner to stderr to avoid polluting the binary stream
|
|
91
|
-
const spinnerStream = options.stdout ? process.stderr : process.stdout;
|
|
92
|
-
const spinner = ora({ text: 'Preparing decryption...', stream: spinnerStream });
|
|
93
|
-
spinner.start();
|
|
94
|
-
try {
|
|
95
|
-
// Resolve ciphertext source: --stdin, or file path
|
|
96
|
-
let ciphertext;
|
|
97
|
-
let defaultFileName = 'decrypted';
|
|
98
|
-
if (options.stdin) {
|
|
99
|
-
spinner.text = 'Reading ciphertext from stdin...';
|
|
100
|
-
ciphertext = await readStdin();
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
if (!encryptedFile) {
|
|
104
|
-
spinner.fail('Provide an encrypted file path, or use --stdin to read from stdin.');
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const inputPath = resolve(encryptedFile);
|
|
108
|
-
if (!existsSync(inputPath)) {
|
|
109
|
-
spinner.fail(`File not found: ${inputPath}`);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
defaultFileName = basename(inputPath).replace(/\.enc$/, '');
|
|
113
|
-
ciphertext = readFileSync(inputPath);
|
|
114
|
-
}
|
|
115
|
-
let wrappedKey;
|
|
116
|
-
let iv;
|
|
117
|
-
let checksum = options.checksum;
|
|
118
|
-
let fileName = defaultFileName;
|
|
119
|
-
let encryptionParams = {};
|
|
120
|
-
// ── Mode 1: Export manifest ──────────────────────────────────
|
|
121
|
-
if (options.export) {
|
|
122
|
-
spinner.text = 'Reading export manifest...';
|
|
123
|
-
const manifestPath = resolve(options.export);
|
|
124
|
-
if (!existsSync(manifestPath)) {
|
|
125
|
-
spinner.fail(`Export manifest not found: ${manifestPath}`);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
129
|
-
let exportedFile;
|
|
130
|
-
if (options.fileId) {
|
|
131
|
-
exportedFile = manifest.files.find((f) => f.fileId === options.fileId);
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
exportedFile = manifest.files.find((f) => f.name === defaultFileName || f.name === encryptedFile);
|
|
135
|
-
if (!exportedFile && manifest.files.length === 1) {
|
|
136
|
-
exportedFile = manifest.files[0];
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (!exportedFile) {
|
|
140
|
-
spinner.fail(options.fileId
|
|
141
|
-
? `File ID ${options.fileId} not found in export manifest.`
|
|
142
|
-
: `Could not match "${defaultFileName}" to a file in the export manifest. Use --file-id to specify.`);
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
if (!exportedFile.encrypted) {
|
|
146
|
-
spinner.fail(`File "${exportedFile.name}" is not encrypted (public vault). No decryption needed.`);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (!exportedFile.wrappedKey || !exportedFile.encryptionIv) {
|
|
150
|
-
spinner.fail(`File "${exportedFile.name}" is missing encryption metadata in the export.`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
wrappedKey = exportedFile.wrappedKey;
|
|
154
|
-
iv = exportedFile.encryptionIv;
|
|
155
|
-
checksum = checksum ?? exportedFile.plaintextChecksumSha256 ?? undefined;
|
|
156
|
-
fileName = exportedFile.name;
|
|
157
|
-
// Read account-level encryption params from manifest
|
|
158
|
-
if (manifest.encryption) {
|
|
159
|
-
encryptionParams = {
|
|
160
|
-
salt: manifest.encryption.salt ?? undefined,
|
|
161
|
-
verifier: manifest.encryption.verifier ?? undefined,
|
|
162
|
-
encryptedMasterKey: manifest.encryption.encryptedMasterKey ?? undefined,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
// ── Mode 2: Direct flags ─────────────────────────────────────
|
|
166
|
-
}
|
|
167
|
-
else if (options.wrappedKey && options.iv) {
|
|
168
|
-
wrappedKey = options.wrappedKey;
|
|
169
|
-
iv = options.iv;
|
|
170
|
-
// ── Mode 3: Fetch from API ───────────────────────────────────
|
|
171
|
-
}
|
|
172
|
-
else if (options.fileId) {
|
|
173
|
-
spinner.text = 'Fetching file metadata from API...';
|
|
174
|
-
const apiUrl = getApiUrl(program.opts().apiUrl);
|
|
175
|
-
const apiKey = getApiKey(program.opts().apiKey);
|
|
176
|
-
const sdk = createSDKClient(apiUrl, apiKey);
|
|
177
|
-
const file = await sdk.files.get(options.fileId);
|
|
178
|
-
if (!file.encrypted) {
|
|
179
|
-
spinner.fail('This file is not encrypted. No decryption needed.');
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (!file.wrappedKey || !file.encryptionIv) {
|
|
183
|
-
spinner.fail('File is missing encryption metadata.');
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
wrappedKey = file.wrappedKey;
|
|
187
|
-
iv = file.encryptionIv;
|
|
188
|
-
checksum = checksum ?? file.plaintextChecksumSha256 ?? undefined;
|
|
189
|
-
fileName = file.name;
|
|
190
|
-
// Also fetch encryption params for master key derivation
|
|
191
|
-
const params = await sdk.account.getEncryptionParams();
|
|
192
|
-
encryptionParams = {
|
|
193
|
-
salt: params.salt ?? undefined,
|
|
194
|
-
verifier: params.verifier ?? undefined,
|
|
195
|
-
encryptedMasterKey: params.encryptedMasterKey ?? undefined,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
spinner.fail('Need encryption metadata. Use one of:\n' +
|
|
200
|
-
' --export <manifest.json> (offline, from tusky export)\n' +
|
|
201
|
-
' --file-id <id> (online, fetches from API)\n' +
|
|
202
|
-
' --wrapped-key <key> --iv <iv> (manual, base64 values)');
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
// If we don't have encryption params yet, try API
|
|
206
|
-
if (!encryptionParams.salt) {
|
|
207
|
-
try {
|
|
208
|
-
const apiUrl = getApiUrl(program.opts().apiUrl);
|
|
209
|
-
const apiKey = getApiKey(program.opts().apiKey);
|
|
210
|
-
const sdk = createSDKClient(apiUrl, apiKey);
|
|
211
|
-
const params = await sdk.account.getEncryptionParams();
|
|
212
|
-
encryptionParams = {
|
|
213
|
-
salt: params.salt ?? undefined,
|
|
214
|
-
verifier: params.verifier ?? undefined,
|
|
215
|
-
encryptedMasterKey: params.encryptedMasterKey ?? undefined,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
// API unavailable — that's ok if we have a session key
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
// Resolve master key
|
|
223
|
-
spinner.text = 'Deriving encryption key...';
|
|
224
|
-
const masterKey = await resolveMasterKey({
|
|
225
|
-
passphrase: options.passphrase,
|
|
226
|
-
...encryptionParams,
|
|
227
|
-
});
|
|
228
|
-
// Decrypt
|
|
229
|
-
spinner.text = 'Decrypting...';
|
|
230
|
-
const plaintext = decryptBuffer(ciphertext, wrappedKey, iv, masterKey, checksum);
|
|
231
|
-
if (options.stdout) {
|
|
232
|
-
spinner.stop();
|
|
233
|
-
process.stdout.write(plaintext);
|
|
234
|
-
if (checksum) {
|
|
235
|
-
process.stderr.write(chalk.dim(' Integrity check passed (SHA-256)\n'));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
// Write to disk
|
|
240
|
-
const outputPath = options.output ? resolve(options.output) : resolve(fileName);
|
|
241
|
-
writeFileSync(outputPath, plaintext);
|
|
242
|
-
spinner.succeed(`Decrypted -> ${outputPath} (${plaintext.length} bytes)`);
|
|
243
|
-
if (checksum) {
|
|
244
|
-
console.log(chalk.dim(' Integrity check passed (SHA-256)'));
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
catch (err) {
|
|
249
|
-
spinner.fail(`Decryption failed: ${err.message}`);
|
|
250
|
-
if (err.message.includes('Unsupported state') || err.message.includes('auth tag')) {
|
|
251
|
-
console.log(chalk.dim(' This usually means the passphrase is incorrect or the file is corrupted.'));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
//# sourceMappingURL=decrypt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decrypt.js","sourceRoot":"","sources":["../../../src/commands/decrypt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../src/commands/encryption.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,QAgS1D"}
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { getSDKClientFromParent } from '../sdk.js';
|
|
4
|
-
import { deriveMasterKey, computeVerifier, verifyPassphrase, generateSalt, generateMasterKey, generateRecoveryKey, wrapMasterKey, unwrapMasterKey, } from '../crypto.js';
|
|
5
|
-
import { storeMasterKey, loadMasterKey } from '../lib/keyring.js';
|
|
6
|
-
export function registerEncryptionCommands(program) {
|
|
7
|
-
const encryption = program.command('encryption').description('Manage E2E encryption');
|
|
8
|
-
encryption.command('setup')
|
|
9
|
-
.description('Set encryption passphrase (first time only)')
|
|
10
|
-
.action(async () => {
|
|
11
|
-
const sdk = getSDKClientFromParent(encryption);
|
|
12
|
-
// Check if already set up
|
|
13
|
-
const { setupComplete } = await sdk.account.getEncryptionParams();
|
|
14
|
-
if (setupComplete) {
|
|
15
|
-
console.log(chalk.yellow('Encryption is already set up.'));
|
|
16
|
-
console.log(chalk.dim('Use: tusky encryption change-passphrase'));
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
// Get passphrase
|
|
20
|
-
const answers = await inquirer.prompt([
|
|
21
|
-
{
|
|
22
|
-
type: 'password',
|
|
23
|
-
name: 'passphrase',
|
|
24
|
-
message: 'Enter encryption passphrase:',
|
|
25
|
-
mask: '*',
|
|
26
|
-
validate: (input) => input.length >= 8 || 'Passphrase must be at least 8 characters',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
type: 'password',
|
|
30
|
-
name: 'confirm',
|
|
31
|
-
message: 'Confirm passphrase:',
|
|
32
|
-
mask: '*',
|
|
33
|
-
},
|
|
34
|
-
]);
|
|
35
|
-
if (answers.passphrase !== answers.confirm) {
|
|
36
|
-
console.error(chalk.red('Passphrases do not match.'));
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
// Generate random master key and derive wrapping key from passphrase
|
|
40
|
-
const masterKey = generateMasterKey();
|
|
41
|
-
const salt = generateSalt();
|
|
42
|
-
const wrappingKey = deriveMasterKey(answers.passphrase, salt);
|
|
43
|
-
const verifier = computeVerifier(wrappingKey);
|
|
44
|
-
// Wrap master key with wrapping key (for passphrase unlock)
|
|
45
|
-
const encryptedMasterKey = wrapMasterKey(masterKey, wrappingKey);
|
|
46
|
-
// Wrap master key with recovery key (for recovery flow)
|
|
47
|
-
const recoveryKeyRaw = generateRecoveryKey();
|
|
48
|
-
const wrappedMasterKeyBackup = wrapMasterKey(masterKey, recoveryKeyRaw);
|
|
49
|
-
const recoveryKeyBase64 = recoveryKeyRaw.toString('base64');
|
|
50
|
-
// Send to server
|
|
51
|
-
await sdk.account.setupEncryption({
|
|
52
|
-
salt: salt.toString('base64'),
|
|
53
|
-
verifier: verifier.toString('base64'),
|
|
54
|
-
encryptedMasterKey: encryptedMasterKey.toString('base64'),
|
|
55
|
-
wrappedMasterKeyBackup: wrappedMasterKeyBackup.toString('base64'),
|
|
56
|
-
});
|
|
57
|
-
// Store master key in session
|
|
58
|
-
storeMasterKey(masterKey);
|
|
59
|
-
// Display recovery key
|
|
60
|
-
console.log('');
|
|
61
|
-
console.log(chalk.yellow.bold('SAVE YOUR RECOVERY KEY — it will not be shown again:'));
|
|
62
|
-
console.log('');
|
|
63
|
-
console.log(chalk.bold(` ${recoveryKeyBase64}`));
|
|
64
|
-
console.log('');
|
|
65
|
-
const confirmSaved = await inquirer.prompt([{
|
|
66
|
-
type: 'confirm',
|
|
67
|
-
name: 'saved',
|
|
68
|
-
message: 'Have you saved your recovery key?',
|
|
69
|
-
default: false,
|
|
70
|
-
}]);
|
|
71
|
-
if (!confirmSaved.saved) {
|
|
72
|
-
console.log(chalk.yellow('Please save your recovery key before continuing!'));
|
|
73
|
-
console.log(chalk.bold(` ${recoveryKeyBase64}`));
|
|
74
|
-
}
|
|
75
|
-
console.log(chalk.green('Encryption configured successfully.'));
|
|
76
|
-
});
|
|
77
|
-
encryption.command('unlock')
|
|
78
|
-
.description('Unlock encryption for this session')
|
|
79
|
-
.option('--passphrase <passphrase>', 'Passphrase (non-interactive; also reads TUSKYDP_PASSWORD env var)')
|
|
80
|
-
.action(async (options) => {
|
|
81
|
-
const sdk = getSDKClientFromParent(encryption);
|
|
82
|
-
const { setupComplete, salt, verifier, encryptedMasterKey } = await sdk.account.getEncryptionParams();
|
|
83
|
-
if (!setupComplete) {
|
|
84
|
-
console.error(chalk.red('Encryption not set up. Run: tusky encryption setup'));
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// Resolve passphrase: flag > env var > interactive prompt
|
|
88
|
-
let passphrase = options.passphrase ?? process.env.TUSKYDP_PASSWORD;
|
|
89
|
-
if (!passphrase) {
|
|
90
|
-
const answers = await inquirer.prompt([{
|
|
91
|
-
type: 'password',
|
|
92
|
-
name: 'passphrase',
|
|
93
|
-
message: 'Enter encryption passphrase:',
|
|
94
|
-
mask: '*',
|
|
95
|
-
}]);
|
|
96
|
-
passphrase = answers.passphrase;
|
|
97
|
-
}
|
|
98
|
-
const saltBuffer = Buffer.from(salt, 'base64');
|
|
99
|
-
const verifierBuffer = Buffer.from(verifier, 'base64');
|
|
100
|
-
const wrappingKey = deriveMasterKey(passphrase, saltBuffer);
|
|
101
|
-
if (!verifyPassphrase(wrappingKey, verifierBuffer)) {
|
|
102
|
-
console.error(chalk.red('Invalid passphrase.'));
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
// Unwrap the real master key (or fall back to legacy where wrapping key = master key)
|
|
106
|
-
let masterKey;
|
|
107
|
-
if (encryptedMasterKey) {
|
|
108
|
-
masterKey = unwrapMasterKey(Buffer.from(encryptedMasterKey, 'base64'), wrappingKey);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
masterKey = wrappingKey;
|
|
112
|
-
}
|
|
113
|
-
storeMasterKey(masterKey);
|
|
114
|
-
console.log(chalk.green('Encryption session unlocked.'));
|
|
115
|
-
});
|
|
116
|
-
encryption.command('status')
|
|
117
|
-
.description('Show encryption status')
|
|
118
|
-
.action(async () => {
|
|
119
|
-
const sdk = getSDKClientFromParent(encryption);
|
|
120
|
-
const { setupComplete } = await sdk.account.getEncryptionParams();
|
|
121
|
-
const sessionActive = loadMasterKey() !== null;
|
|
122
|
-
console.log(`Encryption setup: ${setupComplete ? chalk.green('Complete') : chalk.yellow('Not set up')}`);
|
|
123
|
-
console.log(`Session unlocked: ${sessionActive ? chalk.green('Yes') : chalk.yellow('No')}`);
|
|
124
|
-
});
|
|
125
|
-
encryption.command('change-passphrase')
|
|
126
|
-
.description('Change encryption passphrase')
|
|
127
|
-
.action(async () => {
|
|
128
|
-
const sdk = getSDKClientFromParent(encryption);
|
|
129
|
-
const { setupComplete, salt, verifier, encryptedMasterKey } = await sdk.account.getEncryptionParams();
|
|
130
|
-
if (!setupComplete) {
|
|
131
|
-
console.error(chalk.red('Encryption not set up. Run: tusky encryption setup'));
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const answers = await inquirer.prompt([
|
|
135
|
-
{
|
|
136
|
-
type: 'password',
|
|
137
|
-
name: 'currentPassphrase',
|
|
138
|
-
message: 'Enter current passphrase:',
|
|
139
|
-
mask: '*',
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
type: 'password',
|
|
143
|
-
name: 'newPassphrase',
|
|
144
|
-
message: 'Enter new passphrase:',
|
|
145
|
-
mask: '*',
|
|
146
|
-
validate: (input) => input.length >= 8 || 'Passphrase must be at least 8 characters',
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
type: 'password',
|
|
150
|
-
name: 'confirmNew',
|
|
151
|
-
message: 'Confirm new passphrase:',
|
|
152
|
-
mask: '*',
|
|
153
|
-
},
|
|
154
|
-
]);
|
|
155
|
-
if (answers.newPassphrase !== answers.confirmNew) {
|
|
156
|
-
console.error(chalk.red('New passphrases do not match.'));
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// Verify current passphrase
|
|
160
|
-
const currentSalt = Buffer.from(salt, 'base64');
|
|
161
|
-
const currentVerifier = Buffer.from(verifier, 'base64');
|
|
162
|
-
const currentWrappingKey = deriveMasterKey(answers.currentPassphrase, currentSalt);
|
|
163
|
-
if (!verifyPassphrase(currentWrappingKey, currentVerifier)) {
|
|
164
|
-
console.error(chalk.red('Invalid current passphrase.'));
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
// Unwrap the real master key (or use wrapping key as legacy fallback)
|
|
168
|
-
let masterKey;
|
|
169
|
-
if (encryptedMasterKey) {
|
|
170
|
-
masterKey = unwrapMasterKey(Buffer.from(encryptedMasterKey, 'base64'), currentWrappingKey);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
masterKey = currentWrappingKey;
|
|
174
|
-
}
|
|
175
|
-
// Derive new wrapping key, re-wrap master key
|
|
176
|
-
const newSalt = generateSalt();
|
|
177
|
-
const newWrappingKey = deriveMasterKey(answers.newPassphrase, newSalt);
|
|
178
|
-
const newVerifier = computeVerifier(newWrappingKey);
|
|
179
|
-
const newEncryptedMasterKey = wrapMasterKey(masterKey, newWrappingKey);
|
|
180
|
-
// Generate new recovery key and wrap master key with it
|
|
181
|
-
const newRecoveryKey = generateRecoveryKey();
|
|
182
|
-
const newWrappedBackup = wrapMasterKey(masterKey, newRecoveryKey);
|
|
183
|
-
await sdk.account.resetEncryption({
|
|
184
|
-
salt: newSalt.toString('base64'),
|
|
185
|
-
verifier: newVerifier.toString('base64'),
|
|
186
|
-
encryptedMasterKey: newEncryptedMasterKey.toString('base64'),
|
|
187
|
-
wrappedMasterKeyBackup: newWrappedBackup.toString('base64'),
|
|
188
|
-
});
|
|
189
|
-
storeMasterKey(masterKey);
|
|
190
|
-
console.log(chalk.yellow.bold('NEW RECOVERY KEY (save it!):'));
|
|
191
|
-
console.log(chalk.bold(` ${newRecoveryKey.toString('base64')}`));
|
|
192
|
-
console.log(chalk.green('Passphrase changed successfully.'));
|
|
193
|
-
});
|
|
194
|
-
encryption.command('recover')
|
|
195
|
-
.description('Recover master key with recovery key')
|
|
196
|
-
.action(async () => {
|
|
197
|
-
const sdk = getSDKClientFromParent(encryption);
|
|
198
|
-
const answers = await inquirer.prompt([
|
|
199
|
-
{
|
|
200
|
-
type: 'input',
|
|
201
|
-
name: 'recoveryKey',
|
|
202
|
-
message: 'Enter your recovery key (base64):',
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
type: 'password',
|
|
206
|
-
name: 'newPassphrase',
|
|
207
|
-
message: 'Enter new passphrase:',
|
|
208
|
-
mask: '*',
|
|
209
|
-
validate: (input) => input.length >= 8 || 'Passphrase must be at least 8 characters',
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
type: 'password',
|
|
213
|
-
name: 'confirmNew',
|
|
214
|
-
message: 'Confirm new passphrase:',
|
|
215
|
-
mask: '*',
|
|
216
|
-
},
|
|
217
|
-
]);
|
|
218
|
-
if (answers.newPassphrase !== answers.confirmNew) {
|
|
219
|
-
console.error(chalk.red('Passphrases do not match.'));
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
// Get wrapped master key backup from server
|
|
223
|
-
const { wrappedMasterKeyBackup } = await sdk.account.getRecoveryData();
|
|
224
|
-
const wrappedData = Buffer.from(wrappedMasterKeyBackup, 'base64');
|
|
225
|
-
const recoveryKeyRaw = Buffer.from(answers.recoveryKey, 'base64');
|
|
226
|
-
let masterKey;
|
|
227
|
-
try {
|
|
228
|
-
masterKey = unwrapMasterKey(wrappedData, recoveryKeyRaw);
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
console.error(chalk.red('Invalid recovery key.'));
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
// Derive new wrapping key from new passphrase, wrap the RECOVERED master key
|
|
235
|
-
const newSalt = generateSalt();
|
|
236
|
-
const newWrappingKey = deriveMasterKey(answers.newPassphrase, newSalt);
|
|
237
|
-
const newVerifier = computeVerifier(newWrappingKey);
|
|
238
|
-
const newEncryptedMasterKey = wrapMasterKey(masterKey, newWrappingKey);
|
|
239
|
-
// Generate new recovery key and wrap master key with it
|
|
240
|
-
const newRecoveryKey = generateRecoveryKey();
|
|
241
|
-
const newWrappedBackup = wrapMasterKey(masterKey, newRecoveryKey);
|
|
242
|
-
await sdk.account.resetEncryption({
|
|
243
|
-
salt: newSalt.toString('base64'),
|
|
244
|
-
verifier: newVerifier.toString('base64'),
|
|
245
|
-
encryptedMasterKey: newEncryptedMasterKey.toString('base64'),
|
|
246
|
-
wrappedMasterKeyBackup: newWrappedBackup.toString('base64'),
|
|
247
|
-
});
|
|
248
|
-
storeMasterKey(masterKey);
|
|
249
|
-
console.log(chalk.yellow.bold('NEW RECOVERY KEY (save it!):'));
|
|
250
|
-
console.log(chalk.bold(` ${newRecoveryKey.toString('base64')}`));
|
|
251
|
-
console.log(chalk.green('Recovery successful. Passphrase reset.'));
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
//# sourceMappingURL=encryption.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.js","sourceRoot":"","sources":["../../../src/commands/encryption.ts"],"names":[],"mappings":"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"}
|
package/dist/src/crypto.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export interface FileMeta {
|
|
2
|
-
/** Original filename */
|
|
3
|
-
n: string;
|
|
4
|
-
/** Original MIME type */
|
|
5
|
-
m: string;
|
|
6
|
-
}
|
|
7
|
-
export declare function deriveMasterKey(passphrase: string, salt: Buffer): Buffer;
|
|
8
|
-
export declare function computeVerifier(masterKey: Buffer): Buffer;
|
|
9
|
-
export declare function verifyPassphrase(masterKey: Buffer, expectedVerifier: Buffer): boolean;
|
|
10
|
-
export declare function generateSalt(): Buffer;
|
|
11
|
-
export declare function generateRecoveryKey(): Buffer;
|
|
12
|
-
export declare function generateMasterKey(): Buffer;
|
|
13
|
-
export declare function wrapMasterKey(masterKey: Buffer, recoveryKey: Buffer): Buffer;
|
|
14
|
-
export declare function unwrapMasterKey(wrappedData: Buffer, recoveryKey: Buffer): Buffer;
|
|
15
|
-
export declare function encryptBuffer(plaintext: Buffer, masterKey: Buffer): {
|
|
16
|
-
ciphertext: Buffer;
|
|
17
|
-
wrappedKey: string;
|
|
18
|
-
iv: string;
|
|
19
|
-
plaintextChecksum: string;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Encrypt filename + MIME type together using master key (AES-256-GCM).
|
|
23
|
-
* Format: base64([iv(12) | ciphertext | authTag(16)])
|
|
24
|
-
*/
|
|
25
|
-
export declare function encryptMetadata(name: string, mimeType: string, masterKey: Buffer): string;
|
|
26
|
-
/**
|
|
27
|
-
* Decrypt an encryptedName blob produced by encryptMetadata.
|
|
28
|
-
* Returns the original { name, mimeType }.
|
|
29
|
-
*/
|
|
30
|
-
export declare function decryptMetadata(encryptedBase64: string, masterKey: Buffer): FileMeta;
|
|
31
|
-
export declare function decryptBuffer(ciphertext: Buffer, wrappedKeyBase64: string, ivBase64: string, masterKey: Buffer, expectedChecksum?: string): Buffer;
|
|
32
|
-
//# sourceMappingURL=crypto.d.ts.map
|
package/dist/src/crypto.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,QAAQ;IACvB,wBAAwB;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,yBAAyB;IACzB,CAAC,EAAE,MAAM,CAAC;CACX;AAMD,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAMrF;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAM5E;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAOhF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CA2BA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CASpF;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,CA6BR"}
|