import { encodeJSONAsBinary, decodeJSONFromBinary } from "encoding/json/index"; import { JSONValue } from "encoding/json/types"; import { AESEncryptor } from "encryption/low-level/symmetric/aes/data"; import { b64Encode, b64Decode } from "encoding/base64"; export interface EncryptedData { iv: string; data: string; algorithm: AesKeyAlgorithm; } export interface SymmetricDataEncryptorI { encrypt(jsonableInput: JSONValue): Promise; decrypt(encryptedObject: EncryptedData): Promise; } export function SymmetricDataEncryptor( dek: CryptoKey ): SymmetricDataEncryptorI { const aes = AESEncryptor(dek); return { async encrypt(jsonableInput: JSONValue): Promise { const { iv, data } = await aes.encryptBinary( encodeJSONAsBinary(jsonableInput) ); return { iv: b64Encode(iv), // TODO: Decide if length of encrypted data could give anything away data: b64Encode(data), // While we don't actually use the algorithm at the moment, we may want to // change this one day algorithm: aes.getAlgorithm() }; }, async decrypt(encryptedObject: EncryptedData): Promise { const { iv, data } = encryptedObject; return decodeJSONFromBinary( await aes.decryptBinary(b64Decode(iv), b64Decode(data)) ); } }; } SymmetricDataEncryptor.getDefaultAlgorithm = AESEncryptor.getDefaultAlgorithm; SymmetricDataEncryptor.generateKey = AESEncryptor.generateKey;