Added end to end encryption
This commit is contained in:
parent
9153ba841d
commit
575e9e2010
131 changed files with 2289 additions and 1670 deletions
95
src/services/crypto/crypto.ts
Normal file
95
src/services/crypto/crypto.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { ICryptoEncrypted, ICryptoData } from "./types";
|
||||
|
||||
const importKey = async (key: Uint8Array<ArrayBuffer>): Promise<CryptoKey> => {
|
||||
return await crypto.subtle.importKey(
|
||||
"raw",
|
||||
key,
|
||||
{ name: "AES-GCM" },
|
||||
false,
|
||||
["encrypt", "decrypt"],
|
||||
);
|
||||
};
|
||||
|
||||
const deriveKey = async (password: string): Promise<CryptoKey> => {
|
||||
const salt = "NEXLINK_FIXED_SALT";
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
const passwordKey = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
encoder.encode(password),
|
||||
"PBKDF2",
|
||||
false,
|
||||
["deriveKey"],
|
||||
);
|
||||
|
||||
return crypto.subtle.deriveKey(
|
||||
{
|
||||
name: "PBKDF2",
|
||||
salt: encoder.encode(salt),
|
||||
iterations: 100000,
|
||||
hash: "SHA-256",
|
||||
},
|
||||
passwordKey,
|
||||
{ name: "AES-GCM", length: 256 },
|
||||
true,
|
||||
["encrypt", "decrypt"],
|
||||
);
|
||||
};
|
||||
|
||||
const encryptData = async <T>(
|
||||
cryptoData: ICryptoData<T>,
|
||||
): Promise<ArrayBuffer> => {
|
||||
const encoded = new TextEncoder().encode(JSON.stringify(cryptoData.data));
|
||||
const encrypted = await crypto.subtle.encrypt(
|
||||
{ name: "AES-GCM", iv: cryptoData.iv },
|
||||
cryptoData.key,
|
||||
encoded,
|
||||
);
|
||||
|
||||
return encrypted;
|
||||
};
|
||||
|
||||
const decryptData = async <T>(cryptoData: ICryptoEncrypted): Promise<T> => {
|
||||
const decrypted = await crypto.subtle.decrypt(
|
||||
{ name: "AES-GCM", iv: cryptoData.iv },
|
||||
cryptoData.key,
|
||||
cryptoData.encryptedData,
|
||||
);
|
||||
const decoded = JSON.parse(new TextDecoder().decode(decrypted));
|
||||
|
||||
return decoded as T;
|
||||
};
|
||||
|
||||
const generateIv = (): Uint8Array<ArrayBuffer> => {
|
||||
return crypto.getRandomValues(new Uint8Array(12));
|
||||
};
|
||||
|
||||
const hexToBytes = (hex: string): ArrayBuffer | undefined => {
|
||||
if (hex.length % 2 !== 0) {
|
||||
return;
|
||||
}
|
||||
const bytes = new Uint8Array(hex.length / 2);
|
||||
for (let i = 0; i < hex.length; i++) {
|
||||
bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
||||
}
|
||||
return bytes.buffer;
|
||||
};
|
||||
|
||||
const bytesToHex = (bytes: ArrayBuffer): string => {
|
||||
const bytesUint8 = new Uint8Array(bytes);
|
||||
let hex = "";
|
||||
for (const byte of bytesUint8) {
|
||||
hex += byte.toString(16).padStart(2, "0");
|
||||
}
|
||||
return hex;
|
||||
};
|
||||
|
||||
export {
|
||||
importKey,
|
||||
deriveKey,
|
||||
encryptData,
|
||||
decryptData,
|
||||
generateIv,
|
||||
hexToBytes,
|
||||
bytesToHex,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue