(encryptedText: string)
| 96 | } |
| 97 | |
| 98 | export async function decrypt(encryptedText: string): Promise<string> { |
| 99 | if (!encryptedText) { |
| 100 | throw new Error("Cannot decrypt empty or null text"); |
| 101 | } |
| 102 | |
| 103 | try { |
| 104 | const encrypted = Buffer.from(encryptedText, "base64"); |
| 105 | |
| 106 | const salt = encrypted.subarray(0, SALT_LENGTH); |
| 107 | const iv = encrypted.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH); |
| 108 | const content = encrypted.subarray(SALT_LENGTH + IV_LENGTH); |
| 109 | |
| 110 | const key = await deriveKey(salt); |
| 111 | |
| 112 | const decrypted = await crypto.subtle.decrypt( |
| 113 | { |
| 114 | name: ALGORITHM.name, |
| 115 | iv, |
| 116 | }, |
| 117 | key, |
| 118 | content, |
| 119 | ); |
| 120 | |
| 121 | return new TextDecoder().decode(decrypted); |
| 122 | } catch (error: unknown) { |
| 123 | if (error instanceof Error) { |
| 124 | throw new Error(`Decryption failed: ${error.message}`); |
| 125 | } |
| 126 | throw new Error("Decryption failed"); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | const PASSWORD_KEY_LENGTH = 32; |
| 131 | const PASSWORD_ITERATIONS = 100000; |
no test coverage detected