Files
EdgeSSH/tests/encryption.test.ts

30 lines
1.6 KiB
TypeScript

import assert from 'node:assert/strict';
import { test } from 'node:test';
import { encryptHost, decryptHost, base64 } from '../src/accounts/crypto.ts';
const key = base64(crypto.getRandomValues(new Uint8Array(32)));
test('host credentials round trip, ciphertext never contains plaintext', async () => {
const input = { password: 'private-password-秘密', privateKey: 'private-key', host: 'server.example' };
const encrypted = await encryptHost(input, key, 'owner-a', 'host-a');
assert.deepEqual(await decryptHost(encrypted, key, 'owner-a', 'host-a'), input);
assert.equal(encrypted.includes(input.password), false);
assert.equal(encrypted.includes(input.host), false);
assert.notEqual(await encryptHost(input, key, 'owner-a', 'host-a'), encrypted);
});
test('ciphertext is bound to both Access identity and host id', async () => {
const encrypted = await encryptHost({ password: 'secret' }, key, 'owner-a', 'host-a');
await assert.rejects(decryptHost(encrypted, key, 'owner-b', 'host-a'));
await assert.rejects(decryptHost(encrypted, key, 'owner-a', 'host-b'));
});
test('wrong keys, malformed secrets and tampered ciphertext fail closed', async () => {
const encrypted = await encryptHost({ password: 'secret' }, key, 'owner', 'host');
await assert.rejects(decryptHost(encrypted, base64(crypto.getRandomValues(new Uint8Array(32))), 'owner', 'host'));
await assert.rejects(encryptHost({}, base64(new Uint8Array(16)), 'owner', 'host'));
const parts = encrypted.split('.');
parts[2] = (parts[2][0] === 'A' ? 'B' : 'A') + parts[2].slice(1);
await assert.rejects(decryptHost(parts.join('.'), key, 'owner', 'host'));
});