Skip to content

Instantly share code, notes, and snippets.

@prashant1k99
Created December 24, 2023 06:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prashant1k99/eb0da546ec6cb57ea477459e322c30e4 to your computer and use it in GitHub Desktop.
Save prashant1k99/eb0da546ec6cb57ea477459e322c30e4 to your computer and use it in GitHub Desktop.
e2ee in Browser
const ENCRYPTION_KEY: any = 'your-encryption-key-here' // Must be 256 bits (32 characters) || Please use the above created shared key
const SharedKey = () => {
if (ENCRYPTION_KEY instanceof CryptoKey) return ENCRYPTION_KEY
return window.crypto.subtle.importKey(
'raw',
new TextEncoder().encode(ENCRYPTION_KEY),
'AES-GCM',
false,
['encrypt', 'decrypt']
)
}
async function encrypt(text: string) {
let iv = window.crypto.getRandomValues(new Uint8Array(16))
let cipher = await window.crypto.subtle.encrypt(
{
name: 'AES-GCM',
iv: iv,
},
await SharedKey(),
new TextEncoder().encode(text)
)
let encrypted = new Uint8Array(cipher)
return {
iv: Array.from(iv, (byte) => ('00' + byte.toString(16)).slice(-2)).join(''),
encryptedData: Array.from(encrypted, (byte) =>
('00' + byte.toString(16)).slice(-2)
).join(''),
}
}
async function decrypt(iv: string, encryptedData: string) {
let encryptionMatches = encryptedData.match(/.{1,2}/g)
let ivMatches = iv.match(/.{1,2}/g)
if (!encryptionMatches || !ivMatches) {
throw new Error('Invalid encrypted data or IV')
}
let decrypted = await window.crypto.subtle.decrypt(
{
name: 'AES-GCM',
iv: new Uint8Array(ivMatches.map((byte) => parseInt(byte, 16))),
},
await SharedKey(),
new Uint8Array(encryptionMatches.map((byte) => parseInt(byte, 16)))
)
return new TextDecoder().decode(decrypted)
}
export const generateKeyPairs = async () => {
const keyPair = await window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256",
},
true,
["deriveKey", "deriveBits"]
);
const publicKeyJwk = await window.crypto.subtle.exportKey(
"jwk",
keyPair.publicKey
);
const privateKeyJwk = await window.crypto.subtle.exportKey(
"jwk",
keyPair.privateKey
);
return { publicKeyJwk, privateKeyJwk };
};
export const generateSharedSecretKey = async (publicKeyJwk: JsonWebKey, privateKeyJwk: JsonWebKey) => {
try {
const publicKey = await window.crypto.subtle.importKey(
"jwk",
publicKeyJwk,
{
name: "ECDH",
namedCurve: "P-256",
},
true,
[]
);
const privateKey = await window.crypto.subtle.importKey(
"jwk",
privateKeyJwk,
{
name: "ECDH",
namedCurve: "P-256",
},
true,
["deriveKey", "deriveBits"]
);
return await window.crypto.subtle.deriveKey(
{ name: "ECDH", public: publicKey },
privateKey,
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
} catch (error) {
console.error("An error occurred while importing the keys:", error);
throw error; // re-throw the error if you want it to propagate
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment