Files
WebDrop/web/src/core-bridge/worker/credentialCipher.ts
T

16 lines
1.3 KiB
TypeScript

export interface EncryptedLogin { key: CryptoKey; iv: Uint8Array; ciphertext: ArrayBuffer }
export interface LoginFields { username: string; password: string }
const encoder = new TextEncoder();
export async function encryptLogin(fields: LoginFields, endpoint: string): Promise<EncryptedLogin> {
const key = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
const iv = crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv, additionalData: encoder.encode(`webdrop-login:${endpoint}`) }, key, encoder.encode(JSON.stringify(fields)));
return { key, iv, ciphertext };
}
export async function decryptLogin(value: EncryptedLogin, endpoint: string): Promise<LoginFields> {
const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: Uint8Array.from(value.iv).buffer, additionalData: encoder.encode(`webdrop-login:${endpoint}`) }, value.key, value.ciphertext);
const fields = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(plaintext)) as LoginFields;
if (typeof fields.username !== 'string' || !/^[a-z0-9_-]{3,32}$/.test(fields.username) || typeof fields.password !== 'string' || fields.password.length > 1024) throw new Error('本机登录资料格式无效');
return fields;
}