First Commit
This commit is contained in:
36
client/crypto.js
Normal file
36
client/crypto.js
Normal file
@@ -0,0 +1,36 @@
|
||||
export async function deriveKey(passphrase, saltBytes) {
|
||||
const enc = new TextEncoder();
|
||||
const keyMaterial = await crypto.subtle.importKey("raw", enc.encode(passphrase), { name: "PBKDF2" }, false, ["deriveKey"]);
|
||||
return crypto.subtle.deriveKey(
|
||||
{ name: "PBKDF2", salt: saltBytes, iterations: 120_000, hash: "SHA-256" },
|
||||
keyMaterial,
|
||||
{ name: "AES-GCM", length: 256 },
|
||||
false,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
}
|
||||
export async function encryptString(plaintext, passphrase) {
|
||||
const enc = new TextEncoder();
|
||||
const salt = crypto.getRandomValues(new Uint8Array(16));
|
||||
const iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
const key = await deriveKey(passphrase, salt);
|
||||
const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, enc.encode(plaintext));
|
||||
const version = new Uint8Array([1]);
|
||||
const out = new Uint8Array(1 + 16 + 12 + ct.byteLength);
|
||||
out.set(version, 0); out.set(salt, 1); out.set(iv, 17); out.set(new Uint8Array(ct), 29);
|
||||
return out;
|
||||
}
|
||||
export async function decryptToString(payload, passphrase) {
|
||||
const dec = new TextDecoder();
|
||||
if (!(payload instanceof Uint8Array)) payload = new Uint8Array(payload);
|
||||
if (payload.length < 29) throw new Error("ciphertext too short");
|
||||
if (payload[0] !== 1) throw new Error("unknown version");
|
||||
const salt = payload.slice(1, 17), iv = payload.slice(17, 29), ct = payload.slice(29);
|
||||
const key = await deriveKey(passphrase, salt);
|
||||
const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ct);
|
||||
return dec.decode(pt);
|
||||
}
|
||||
export function toBlob(data) {
|
||||
if (data instanceof Uint8Array) return new Blob([data], { type: "application/octet-stream" });
|
||||
return new Blob([data], { type: "application/json;charset=utf-8" });
|
||||
}
|
Reference in New Issue
Block a user