Skip to content

Instantly share code, notes, and snippets.

@sondreb
Created March 25, 2025 23:59
Show Gist options
  • Save sondreb/d7ac64573554f3773fb586a21109775c to your computer and use it in GitHub Desktop.
Save sondreb/d7ac64573554f3773fb586a21109775c to your computer and use it in GitHub Desktop.
Data Encryption
import { bytesToHex, hexToBytes, bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
import { secp256k1 } from '@noble/curves/secp256k1';
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
// Encrypting data
function encryptWithPublicKey(publicKey, plaintext) {
// Generate a random ephemeral private key
const ephemeralPrivateKey = secp256k1.utils.randomPrivateKey();
// Derive the ephemeral public key
const ephemeralPublicKey = secp256k1.getPublicKey(ephemeralPrivateKey);
// Compute shared secret using ECDH
const sharedSecret = secp256k1.getSharedSecret(ephemeralPrivateKey, publicKey);
// Use a key derivation step to create a 256-bit key for XChaCha20
const encryptionKey = sharedSecret.slice(0, 32); // First 32 bytes of the shared secret
// Create a random 192-bit nonce (24 bytes)
const nonce = randomBytes(24);
// Encrypt the plaintext with XChaCha20-Poly1305
const cipher = xchacha20poly1305(encryptionKey, nonce);
const ciphertext = cipher.encrypt(new TextEncoder().encode(plaintext));
return {
ephemeralPublicKey, // Include ephemeral public key for decryption
nonce, // Include nonce for decryption
ciphertext,
};
}
// Decrypting data
function decryptWithPrivateKey(privateKey, encryptedData) {
const { ephemeralPublicKey, nonce, ciphertext } = encryptedData;
// Compute shared secret using ECDH
const sharedSecret = secp256k1.getSharedSecret(privateKey, ephemeralPublicKey);
// Use a key derivation step to create a 256-bit key for XChaCha20
const encryptionKey = sharedSecret.slice(0, 32); // First 32 bytes of the shared secret
// Decrypt the ciphertext with XChaCha20-Poly1305
const cipher = xchacha20poly1305(encryptionKey, nonce);
const plaintext = cipher.decrypt(ciphertext);
return new TextDecoder().decode(plaintext);
}
const receiverPrivateKey = secp256k1.utils.randomPrivateKey();
const receiverPublicKey = secp256k1.getPublicKey(receiverPrivateKey);
const receiverPrivateKeyHex = bytesToHex(receiverPrivateKey);
const receiverPublicKeyHex = bytesToHex(receiverPublicKey);
console.log('Private Key:', receiverPrivateKeyHex);
console.log('Public Key:', receiverPublicKeyHex);
const plaintext = 'Hello, XChaCha20-Poly1305!';
console.log('Plaintext:', plaintext);
const encryptedData = encryptWithPublicKey(receiverPublicKey, plaintext);
const encryptedDataHex = {
ephemeralPublicKey: bytesToHex(encryptedData.ephemeralPublicKey),
nonce: bytesToHex(encryptedData.nonce),
ciphertext: bytesToHex(encryptedData.ciphertext),
};
console.log('Encrypted Data:', encryptedDataHex);
const decryptedData = decryptWithPrivateKey(receiverPrivateKey, encryptedData);
console.log('Decrypted Data:', decryptedData);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment