Co-authored-by: Emil Atanasov <heitara@gmail.com> Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
80 lines
1.8 KiB
TypeScript
80 lines
1.8 KiB
TypeScript
export const IV_LENGTH_BYTES = 12;
|
|
|
|
export const createIV = () => {
|
|
const arr = new Uint8Array(IV_LENGTH_BYTES);
|
|
return window.crypto.getRandomValues(arr);
|
|
};
|
|
|
|
export const generateEncryptionKey = async () => {
|
|
const key = await window.crypto.subtle.generateKey(
|
|
{
|
|
name: "AES-GCM",
|
|
length: 128,
|
|
},
|
|
true, // extractable
|
|
["encrypt", "decrypt"],
|
|
);
|
|
return (await window.crypto.subtle.exportKey("jwk", key)).k;
|
|
};
|
|
|
|
export const getImportedKey = (key: string, usage: KeyUsage) =>
|
|
window.crypto.subtle.importKey(
|
|
"jwk",
|
|
{
|
|
alg: "A128GCM",
|
|
ext: true,
|
|
k: key,
|
|
key_ops: ["encrypt", "decrypt"],
|
|
kty: "oct",
|
|
},
|
|
{
|
|
name: "AES-GCM",
|
|
length: 128,
|
|
},
|
|
false, // extractable
|
|
[usage],
|
|
);
|
|
|
|
export const encryptData = async (
|
|
key: string,
|
|
data: Uint8Array | ArrayBuffer | Blob | File | string,
|
|
): Promise<{ encryptedBuffer: ArrayBuffer; iv: Uint8Array }> => {
|
|
const importedKey = await getImportedKey(key, "encrypt");
|
|
const iv = createIV();
|
|
const buffer: ArrayBuffer | Uint8Array =
|
|
typeof data === "string"
|
|
? new TextEncoder().encode(data)
|
|
: data instanceof Uint8Array
|
|
? data
|
|
: data instanceof Blob
|
|
? await data.arrayBuffer()
|
|
: data;
|
|
|
|
const encryptedBuffer = await window.crypto.subtle.encrypt(
|
|
{
|
|
name: "AES-GCM",
|
|
iv,
|
|
},
|
|
importedKey,
|
|
buffer as ArrayBuffer | Uint8Array,
|
|
);
|
|
|
|
return { encryptedBuffer, iv };
|
|
};
|
|
|
|
export const decryptData = async (
|
|
iv: Uint8Array,
|
|
encrypted: Uint8Array | ArrayBuffer,
|
|
privateKey: string,
|
|
): Promise<ArrayBuffer> => {
|
|
const key = await getImportedKey(privateKey, "decrypt");
|
|
return window.crypto.subtle.decrypt(
|
|
{
|
|
name: "AES-GCM",
|
|
iv,
|
|
},
|
|
key,
|
|
encrypted,
|
|
);
|
|
};
|