Phase d cleanup

This commit is contained in:
Zerebos
2026-05-23 22:16:40 -04:00
parent 074147f64f
commit 0e93908bb2
29 changed files with 388 additions and 1413 deletions
+12 -8
View File
@@ -15,15 +15,17 @@ interface StoredVault {
data: string;
}
function toB64(buf: ArrayBuffer): string {
return btoa(String.fromCharCode(...new Uint8Array(buf)));
function toB64(data: ArrayBuffer | Uint8Array): string {
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
return btoa(String.fromCharCode(...bytes));
}
function fromB64(s: string): Uint8Array {
return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
function fromB64(s: string): ArrayBuffer {
const bytes = Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
}
async function deriveKey(pin: string, salt: Uint8Array): Promise<CryptoKey> {
async function deriveKey(pin: string, salt: ArrayBuffer): Promise<CryptoKey> {
const enc = new TextEncoder();
const keyMat = await crypto.subtle.importKey("raw", enc.encode(pin), "PBKDF2", false, ["deriveKey"]);
return crypto.subtle.deriveKey(
@@ -42,7 +44,7 @@ export function vaultExists(): boolean {
export async function lockVault(pin: string, payload: VaultPayload): Promise<void> {
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(pin, salt);
const key = await deriveKey(pin, salt.buffer.slice(salt.byteOffset, salt.byteOffset + salt.byteLength));
const enc = new TextEncoder();
const cipher = await crypto.subtle.encrypt(
@@ -65,10 +67,12 @@ export async function unlockVault(pin: string): Promise<VaultPayload | null> {
try {
const stored = JSON.parse(raw) as StoredVault;
const key = await deriveKey(pin, fromB64(stored.salt));
const iv = new Uint8Array(fromB64(stored.iv));
const cipher = fromB64(stored.data);
const plain = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: fromB64(stored.iv) },
{ name: "AES-GCM", iv },
key,
fromB64(stored.data),
cipher,
);
return JSON.parse(new TextDecoder().decode(plain)) as VaultPayload;
} catch {