Packages: core (BIP39/32/44/49/84/86 derivation, WIF), keystore (PBKDF2 + AES-GCM), psbt, p2p (BIP157/158 SPV daemon, Dandelion++ broadcast with relay-echo verification), blockbook, rpc, electrum, net, bns, web-ui (React/Vite), mobile (Expo). ops/ holds the nginx vhost, systemd unit and push.sh deploy script for digibyte.x/web.
59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
// Smoke test — encrypt a seed, decrypt it back, negative-test a wrong
|
|
// passphrase, exercise the Keystore class over InMemoryAdapter.
|
|
//
|
|
// npm test -w @dgb-wallet/keystore
|
|
|
|
import { Keystore, InMemoryAdapter, encryptString, decryptString } from '../src/index.js';
|
|
|
|
const SEED = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
const PASS = 'correct horse battery staple';
|
|
|
|
async function main(): Promise<void> {
|
|
// 1. Raw encrypt/decrypt round-trip.
|
|
const t0 = Date.now();
|
|
const blob = await encryptString(SEED, PASS);
|
|
const encMs = Date.now() - t0;
|
|
const back = await decryptString(blob, PASS);
|
|
const decMs = Date.now() - t0 - encMs;
|
|
if (back !== SEED) throw new Error('round-trip mismatch');
|
|
console.log(`✅ round-trip: encrypt=${encMs}ms decrypt=${decMs}ms (PBKDF2 iter=${blob.kdf.iter})`);
|
|
|
|
// 2. Wrong passphrase rejected.
|
|
try {
|
|
await decryptString(blob, 'wrong passphrase');
|
|
throw new Error('wrong passphrase should have failed');
|
|
} catch (e) {
|
|
if (!(e as Error).message.includes('decrypt failed')) throw e;
|
|
console.log(`✅ wrong passphrase → ${(e as Error).message}`);
|
|
}
|
|
|
|
// 3. Keystore save/list/unlock/delete over in-memory adapter.
|
|
const ks = new Keystore(new InMemoryAdapter());
|
|
await ks.save('primary', SEED, PASS);
|
|
const list = await ks.list();
|
|
if (list.length !== 1 || list[0].label !== 'primary') throw new Error('list mismatch');
|
|
const unlocked = await ks.unlock('primary', PASS);
|
|
if (unlocked !== SEED) throw new Error('unlock mismatch');
|
|
await ks.delete('primary');
|
|
if ((await ks.list()).length !== 0) throw new Error('delete failed');
|
|
console.log('✅ keystore save/list/unlock/delete');
|
|
|
|
// 4. Overwrite guard.
|
|
await ks.save('primary', SEED, PASS);
|
|
try {
|
|
await ks.save('primary', 'different seed', PASS);
|
|
throw new Error('overwrite guard failed to trigger');
|
|
} catch (e) {
|
|
if (!(e as Error).message.includes('already exists')) throw e;
|
|
console.log(`✅ overwrite guard → ${(e as Error).message}`);
|
|
}
|
|
await ks.save('primary', 'newer', PASS, true);
|
|
const overwritten = await ks.unlock('primary', PASS);
|
|
if (overwritten !== 'newer') throw new Error('overwrite=true did not replace');
|
|
console.log('✅ overwrite=true replaces existing');
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error('❌', e);
|
|
process.exit(1);
|
|
});
|