77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import { storageGet, storageSave } from '@/utils/platform'
|
|
|
|
const getIv = async() => {
|
|
let iv = (await storageGet('iv'))?.iv
|
|
if(!iv){
|
|
iv = crypto.getRandomValues(new Uint8Array(16));
|
|
const jsonIv = JSON.stringify(iv)
|
|
await storageSave('iv', jsonIv)
|
|
return iv
|
|
}else {
|
|
iv = new Uint8Array(Object.values(JSON.parse(iv)));
|
|
}
|
|
return iv
|
|
}
|
|
|
|
const getSalt = async() => {
|
|
let salt = (await storageGet('salt'))?.salt
|
|
|
|
if(!salt){
|
|
salt = crypto.getRandomValues(new Uint8Array(16));
|
|
const jsonSalt = JSON.stringify(salt)
|
|
await storageSave('salt', jsonSalt)
|
|
return salt
|
|
}else {
|
|
salt = new Uint8Array(Object.values(JSON.parse(salt)));
|
|
}
|
|
return salt
|
|
}
|
|
|
|
async function getKey(passwordBytes: Uint8Array) {
|
|
|
|
const salt = await getSalt()
|
|
|
|
const initialKey = await crypto.subtle.importKey(
|
|
"raw",
|
|
passwordBytes,
|
|
{ name: "PBKDF2" },
|
|
false,
|
|
["deriveKey"]
|
|
);
|
|
|
|
return crypto.subtle.deriveKey(
|
|
{ name: "PBKDF2", salt, iterations: 50000, hash: "SHA-256" },
|
|
initialKey,
|
|
{ name: "AES-GCM", length: 256 },
|
|
false,
|
|
["encrypt", "decrypt"]
|
|
);
|
|
}
|
|
|
|
export const getCryptoParams = async(password: string): Promise<{ key: CryptoKey, iv: any }> => {
|
|
const enc = new TextEncoder()
|
|
const encKey = enc.encode(password)
|
|
return { key: await getKey(encKey), iv:await getIv() }
|
|
}
|
|
|
|
export const encrypt = async (data: string, cryptoParams: { key: CryptoKey, iv: any }) => {
|
|
const enc = new TextEncoder()
|
|
const encData = enc.encode(data)
|
|
const encResult = await crypto.subtle.encrypt(
|
|
{
|
|
name: "AES-GCM",
|
|
iv: cryptoParams.iv,
|
|
},
|
|
cryptoParams.key,
|
|
encData,
|
|
)
|
|
return JSON.stringify(new Uint8Array(encResult))
|
|
}
|
|
|
|
export const decrypt = async (encryptedData: string, cryptoParams: { key: CryptoKey, iv: any }) => {
|
|
const encryptedUint = new Uint8Array(Object.values(JSON.parse(encryptedData)));
|
|
const contentBytes = new Uint8Array(
|
|
await crypto.subtle.decrypt({ name: "AES-GCM", iv:cryptoParams.iv }, cryptoParams.key, encryptedUint)
|
|
);
|
|
return new TextDecoder().decode(contentBytes)
|
|
} |