2024-04-16 13:29:56 +05:00
|
|
|
import {
|
|
|
|
hexStringToUint8Array,
|
|
|
|
hexToString,
|
|
|
|
stringToHex,
|
|
|
|
uint8ArrayToHexString
|
|
|
|
} from '.'
|
2024-05-14 16:48:09 +02:00
|
|
|
import { DecryptionError } from '../types/errors/DecryptionError'
|
2024-04-08 17:45:51 +05:00
|
|
|
|
|
|
|
const ENCRYPTION_ALGO_NAME = 'AES-GCM'
|
|
|
|
|
|
|
|
export const generateEncryptionKey = async () => {
|
|
|
|
const cryptoKey = await window.crypto.subtle.generateKey(
|
|
|
|
{ name: ENCRYPTION_ALGO_NAME, length: 128 },
|
|
|
|
true,
|
|
|
|
['encrypt', 'decrypt']
|
|
|
|
)
|
|
|
|
|
|
|
|
const key = await window.crypto.subtle.exportKey('jwk', cryptoKey)
|
|
|
|
|
|
|
|
const jsonString = JSON.stringify(key)
|
|
|
|
const hexKey = stringToHex(jsonString)
|
|
|
|
|
2024-04-16 13:29:56 +05:00
|
|
|
const iv = uint8ArrayToHexString(
|
2024-04-08 17:45:51 +05:00
|
|
|
window.crypto.getRandomValues(new Uint8Array(16))
|
|
|
|
)
|
|
|
|
|
|
|
|
return `${hexKey}?iv=${iv}`
|
|
|
|
}
|
|
|
|
|
|
|
|
export const importKey = async (key: string) => {
|
|
|
|
const splittedKey = key.split('?iv=')
|
|
|
|
const keyString = hexToString(splittedKey[0])
|
|
|
|
const jsonWebKey = JSON.parse(keyString)
|
2024-04-16 13:29:56 +05:00
|
|
|
const iv = hexStringToUint8Array(splittedKey[1])
|
2024-04-08 17:45:51 +05:00
|
|
|
|
|
|
|
const cryptoKey = await window.crypto.subtle.importKey(
|
|
|
|
'jwk',
|
|
|
|
jsonWebKey,
|
|
|
|
{ name: ENCRYPTION_ALGO_NAME },
|
|
|
|
true,
|
|
|
|
['encrypt', 'decrypt']
|
|
|
|
)
|
|
|
|
|
|
|
|
return { cryptoKey, iv }
|
|
|
|
}
|
|
|
|
|
|
|
|
export const encryptArrayBuffer = async (
|
|
|
|
arrayBuffer: ArrayBuffer,
|
|
|
|
key: string
|
|
|
|
) => {
|
|
|
|
const { cryptoKey, iv } = await importKey(key)
|
|
|
|
|
|
|
|
// Encrypt the data
|
|
|
|
const encryptedData = await window.crypto.subtle.encrypt(
|
|
|
|
{ name: ENCRYPTION_ALGO_NAME, iv },
|
|
|
|
cryptoKey,
|
|
|
|
arrayBuffer
|
|
|
|
)
|
|
|
|
|
|
|
|
return encryptedData
|
|
|
|
}
|
|
|
|
|
|
|
|
export const decryptArrayBuffer = async (
|
|
|
|
encryptedData: ArrayBuffer,
|
|
|
|
key: string
|
|
|
|
) => {
|
2024-05-14 16:48:09 +02:00
|
|
|
try {
|
|
|
|
const { cryptoKey, iv } = await importKey(key)
|
2024-05-15 11:50:21 +03:00
|
|
|
|
2024-05-14 16:48:09 +02:00
|
|
|
// Decrypt the data
|
|
|
|
const decryptedData = await window.crypto.subtle.decrypt(
|
|
|
|
{ name: ENCRYPTION_ALGO_NAME, iv },
|
|
|
|
cryptoKey,
|
|
|
|
encryptedData
|
|
|
|
)
|
2024-05-15 11:50:21 +03:00
|
|
|
|
2024-05-14 16:48:09 +02:00
|
|
|
return decryptedData
|
|
|
|
} catch (err) {
|
|
|
|
throw new DecryptionError(err)
|
|
|
|
}
|
2024-04-08 17:45:51 +05:00
|
|
|
}
|