Add configuration files, database migrations, and authentication implementation scaffolding
This commit is contained in:
62
web/dashboard/src/lib/crypto.ts
Normal file
62
web/dashboard/src/lib/crypto.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Zero-Knowledge Cryptography Utility
|
||||
* Uses the Web Crypto API for hardware-accelerated AES-GCM.
|
||||
*/
|
||||
|
||||
export async function importKey(keyData: Uint8Array): Promise<CryptoKey> {
|
||||
return await self.crypto.subtle.importKey(
|
||||
"raw",
|
||||
keyData,
|
||||
{ name: "AES-GCM" },
|
||||
false,
|
||||
["decrypt", "encrypt"]
|
||||
);
|
||||
}
|
||||
|
||||
export async function decryptLog(
|
||||
encryptedData: Uint8Array,
|
||||
key: CryptoKey
|
||||
): Promise<string> {
|
||||
// Our Go implementation sends [Nonce (12 bytes)][Ciphertext]
|
||||
const nonce = encryptedData.slice(0, 12);
|
||||
const ciphertext = encryptedData.slice(12);
|
||||
|
||||
const decrypted = await self.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: nonce,
|
||||
},
|
||||
key,
|
||||
ciphertext
|
||||
);
|
||||
|
||||
return new TextDecoder().decode(decrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a 256-bit key from a password and salt using PBKDF2.
|
||||
* (Used if WebAuthn is not providing a raw key directly)
|
||||
*/
|
||||
export async function deriveKey(password: string, salt: string): Promise<Uint8Array> {
|
||||
const enc = new TextEncoder();
|
||||
const keyMaterial = await self.crypto.subtle.importKey(
|
||||
"raw",
|
||||
enc.encode(password),
|
||||
"PBKDF2",
|
||||
false,
|
||||
["deriveBits", "deriveKey"]
|
||||
);
|
||||
|
||||
const keyBits = await self.crypto.subtle.deriveBits(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: enc.encode(salt),
|
||||
iterations: 100000,
|
||||
hash: "SHA-256",
|
||||
},
|
||||
keyMaterial,
|
||||
256
|
||||
);
|
||||
|
||||
return new Uint8Array(keyBits);
|
||||
}
|
||||
Reference in New Issue
Block a user