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,15 @@
|
||||
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;
|
||||
}
|
||||
Reference in new issue
Block a user