feat(auth): remember encrypted local login credentials
This commit is contained in:
1 parent
f6cfb12716
commit
b65e32885f
9 files changed
+148
-30
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { decryptLogin, encryptLogin } from './credentialCipher';
|
||||
|
||||
describe('local encrypted login fields', () => {
|
||||
const endpoint = 'https://drop.test/api/v1/';
|
||||
const fields = { username: 'alice', password: 'a-test-password' };
|
||||
it('restores fields using a non-exportable key while keeping plaintext out of the record', async () => {
|
||||
const value = await encryptLogin(fields, endpoint);
|
||||
expect(value.key.extractable).toBe(false);
|
||||
expect(new TextDecoder().decode(value.ciphertext)).not.toContain(fields.password);
|
||||
expect(await decryptLogin(value, endpoint)).toEqual(fields);
|
||||
await expect(crypto.subtle.exportKey('raw', value.key)).rejects.toThrow();
|
||||
});
|
||||
it('binds a saved credential to its API server and rejects tampering', async () => {
|
||||
const value = await encryptLogin(fields, endpoint);
|
||||
await expect(decryptLogin(value, 'https://other.test/api/v1/')).rejects.toThrow();
|
||||
const bytes = new Uint8Array(value.ciphertext); bytes[0] = (bytes[0] ?? 0) ^ 1;
|
||||
await expect(decryptLogin({ ...value, ciphertext: bytes.buffer }, endpoint)).rejects.toThrow();
|
||||
});
|
||||
it('uses independent random encryption material for repeated saves', async () => {
|
||||
const first = await encryptLogin(fields, endpoint); const second = await encryptLogin(fields, endpoint);
|
||||
expect(first.iv).not.toEqual(second.iv); expect(new Uint8Array(first.ciphertext)).not.toEqual(new Uint8Array(second.ciphertext));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user