hnschat-web/assets/js/e2ee.js

124 lines
2.4 KiB
JavaScript
Raw Permalink Normal View History

2024-04-17 08:26:30 +10:00
export class e2ee {
async generateKeys() {
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 };
}
async importKey(x, y, d) {
const privateKey = await window.crypto.subtle.importKey(
"jwk",
{
kty: "EC",
crv: "P-256",
x: x,
y: y,
d: d,
ext: true,
},
{
name: "ECDH",
namedCurve: "P-256",
},
true,
["deriveKey", "deriveBits"]
);
const privateKeyJwk = await window.crypto.subtle.exportKey(
"jwk",
privateKey
);
return privateKeyJwk;
}
async deriveKey(publicKeyJwk, privateKeyJwk) {
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"]
);
};
async encryptMessage(text, derivedKey, conversation) {
const encodedText = new TextEncoder().encode(text);
const encryptedData = await window.crypto.subtle.encrypt(
{ name: "AES-GCM", iv: new TextEncoder().encode(conversation) },
derivedKey,
encodedText
);
const uintArray = new Uint8Array(encryptedData);
const string = String.fromCharCode.apply(null, uintArray);
const base64Data = btoa(string);
return base64Data;
};
async decryptMessage(text, derivedKey, conversation) {
try {
const initializationVector = new Uint8Array(new TextEncoder().encode(conversation)).buffer;
const string = atob(text);
const uintArray = new Uint8Array(
[...string].map((char) => char.charCodeAt(0))
);
const algorithm = {
name: "AES-GCM",
iv: initializationVector,
};
const decryptedData = await window.crypto.subtle.decrypt(
algorithm,
derivedKey,
uintArray
);
return new TextDecoder().decode(decryptedData);
}
catch {
return text;
}
};
}