feature: add secured message
- encrypt/decrypt every message (require ^0.0.2) Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
parent
4ca8b3b270
commit
2a0841a798
14 changed files with 314 additions and 147 deletions
68
src/lib/core/utils/crypto.ts
Normal file
68
src/lib/core/utils/crypto.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
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 };
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue