(key: Buffer, payload: string)
| 60 | }); |
| 61 | |
| 62 | const decryptSecret = (key: Buffer, payload: string): Effect.Effect<string, StorageError> => |
| 63 | Effect.try({ |
| 64 | // A malformed payload, a wrong key, or tampered bytes all surface here: |
| 65 | // GCM verification fails in `decipher.final()`, and bad base64/arity throws |
| 66 | // before that — both land in the StorageError channel. |
| 67 | try: () => { |
| 68 | const parts = payload.split("."); |
| 69 | const iv = Buffer.from(parts[1] ?? "", "base64"); |
| 70 | const tag = Buffer.from(parts[2] ?? "", "base64"); |
| 71 | const ciphertext = Buffer.from(parts[3] ?? "", "base64"); |
| 72 | const decipher = createDecipheriv("aes-256-gcm", key, iv); |
| 73 | decipher.setAuthTag(tag); |
| 74 | return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8"); |
| 75 | }, |
| 76 | catch: (cause) => new StorageError({ message: "Failed to decrypt secret", cause }), |
| 77 | }); |
| 78 | |
| 79 | const ENCRYPTED_PROVIDER_KEY = ProviderKey.make("encrypted"); |
| 80 |
no test coverage detected