- encrypt/decrypt every message (require ^0.0.2) Signed-off-by: pakintada@gmail.com <Pakin>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
export class WebCryptoHelper {
|
|
static async generateKeyPair() {
|
|
const keyPair = await window.crypto.subtle.generateKey(
|
|
{
|
|
name: 'ECDH',
|
|
namedCurve: 'P-256'
|
|
},
|
|
true,
|
|
['deriveKey', 'deriveBits']
|
|
);
|
|
|
|
const exportedPublic = await window.crypto.subtle.exportKey('raw', keyPair.publicKey);
|
|
const publicKeyBase64 = btoa(String.fromCharCode(...new Uint8Array(exportedPublic)));
|
|
|
|
return { privateKey: keyPair.privateKey, publicKeyBase64 };
|
|
}
|
|
|
|
static async deriveSharedKey(clientPrivateKey: any, serverPublicKeyBase64: any) {
|
|
const binarySign = atob(serverPublicKeyBase64);
|
|
const bytes = new Uint8Array(binarySign.length);
|
|
for (let i = 0; i < binarySign.length; i++) {
|
|
bytes[i] = binarySign.charCodeAt(i);
|
|
}
|
|
|
|
const importedServerPublic = await window.crypto.subtle.importKey(
|
|
'raw',
|
|
bytes,
|
|
{ name: 'ECDH', namedCurve: 'P-256' },
|
|
true,
|
|
[]
|
|
);
|
|
return await window.crypto.subtle.deriveKey(
|
|
{ name: 'ECDH', public: importedServerPublic },
|
|
clientPrivateKey,
|
|
{ name: 'AES-GCM', length: 256 },
|
|
true,
|
|
['encrypt', 'decrypt']
|
|
);
|
|
}
|
|
|
|
static async decryptMessage(aesKey: any, ciphertextBase64: any, ivBase64: any) {
|
|
const rawCipher = Uint8Array.from(atob(ciphertextBase64), (c) => c.charCodeAt(0));
|
|
const rawIv = Uint8Array.from(atob(ivBase64), (c) => c.charCodeAt(0));
|
|
const decryptedBuffer = await window.crypto.subtle.decrypt(
|
|
{ name: 'AES-GCM', iv: rawIv },
|
|
aesKey,
|
|
rawCipher
|
|
);
|
|
return new TextDecoder().decode(decryptedBuffer);
|
|
}
|
|
|
|
// Encrypt outgoing messages before sending them to your Axum backend
|
|
static async encryptMessage(aesKey: any, plainText: any) {
|
|
const iv = window.crypto.getRandomValues(new Uint8Array(12)); // 12-byte nonce
|
|
const encodedText = new TextEncoder().encode(plainText);
|
|
|
|
const ciphertextBuffer = await window.crypto.subtle.encrypt(
|
|
{ name: 'AES-GCM', iv: iv },
|
|
aesKey,
|
|
encodedText
|
|
);
|
|
|
|
const ciphertextBase64 = btoa(String.fromCharCode(...new Uint8Array(ciphertextBuffer)));
|
|
const ivBase64 = btoa(String.fromCharCode(...iv));
|
|
|
|
return { ciphertext: ciphertextBase64, iv: ivBase64 };
|
|
}
|
|
}
|