I've successfully encrypted data with crypto API. Once it's done, I save the initialization-vector and the encrypted data as a single base64 string.
When decrypting, I revert these two information to Uint8Array that match the originals. But the decryption always fails with the following error:
error decrypt Error: OperationError
Here is the code:
// generate key
generateKey (){
crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
}
// encrypt
async encrypt(data, secretKey) {
const initializationVector = crypto.getRandomValues(new Uint8Array(96));
const encodedData = new TextEncoder().encode(JSON.stringify(data));
const encryptedBuffer = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: initializationVector,
tagLength: 128,
},
secretKey,
encodedData
);
const encryptedDataBase64 = btoa(new Uint8Array(encryptedBuffer));
const initializationVectorBase64 = btoa(initializationVector);
return `${encryptedDataBase64}.${initializationVectorBase64}`;
}
// convert base64 string to uint8array
base64ToUint8Array(base64String) {
return new Uint8Array(
atob(base64String)
.split(",")
.map((n) => +n)
);
}
//decrypt
async decrypt(encryptedData, secretKey) {
const { 0: data, 1: iv } = encryptedData.split(".");
const initializationVector = base64ToUint8Array(iv);
const _data = base64ToUint8Array(data);
const decryptedData = await crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: initializationVector,
tagLength: 128,
},
secretKey,
_data
);
return new TextDecoder().decode(decryptedData)
}
I've checked the initialization-vector and the data Uint8Array during the encryption and during the decryption. They match their original versions. So I don't know where I'm doing something wrong here.
Thanks for your help!