e2e

Implementing End-to-End Encryption in a Node.js Chat App

building a lightweight chat app with Node.js and Socket.io—nothing crazy, just something to pass messages in real-time. Then came the “fun” idea: why not add end-to-end encryption?

Honestly, it sounded terrifying at first. But after a lot of trial, error, and late-night Googling, I got it working—and guess what? You can too.

Why Even Bother?

Yes, HTTPS is good. But once a message hits your server, it’s readable unless you encrypt it before sending.

End-to-end encryption (E2EE) means:

  • The message is encrypted before it leaves the sender’s browser.
  • Only the recipient can decrypt it using their private key.
  • Even your own server is clueless about what’s inside.

Privacy win.

What I Used

  • Node.js — backend
  • Socket.io — real-time communication
  • Crypto (Node’s built-in module) — for key generation and encryption
  • HTML + vanilla JS — front-end
  • Google — the real MVP

Read more about tech blogs.

Step 1: Generating RSA Key Pairs

Each user needs a public/private key pair. Public keys get shared. Private keys? Treat them like your Netflix password: private and sacred.

const { generateKeyPairSync } = require('crypto');

const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});

console.log("Public:", publicKey);
console.log("Private:", privateKey);

Note: I temporarily stored the private key in localStorage (not ideal—just for demo).

Step 2: Encrypting Messages with the Receiver’s Public Key

Before sending a message, the sender encrypts it using the receiver’s public key.

const { publicEncrypt } = require('crypto');

function encrypt(publicKey, message) {
const buffer = Buffer.from(message, 'utf8');
const encrypted = publicEncrypt(publicKey, buffer);
return encrypted.toString('base64');
}

Simple, right? The real challenge is ensuring you have the correct key for the intended receiver.

Step 3: Decrypting Messages with the Receiver’s Private Key

On the receiving end, we decrypt using the recipient’s private key:

const { privateDecrypt } = require('crypto');

function decrypt(privateKey, encryptedData) {
const buffer = Buffer.from(encryptedData, 'base64');
const decrypted = privateDecrypt(privateKey, buffer);
return decrypted.toString('utf8');
}

Voilà. Alice encrypts with Bob’s public key, and only Bob’s private key can unlock it.

The Server’s Role? Just Forward Stuff

The chat server acts like a clueless postman. No peeking allowed.

const io = require('socket.io')(3000, {
cors: { origin: "*" }
});

io.on('connection', socket => {
socket.on('send-message', ({ to, data }) => {
socket.to(to).emit('receive-message', data);
});
});

Because the message is already encrypted, the server doesn’t (and can’t) understand it.

A Few Gotchas

  • Key Safety: If your private key leaks, you’re toast. Store it securely (not localStorage in production).
  • Key Exchange: Be careful with public key sharing. Verify it—QR codes or hashes can help.
  • Message Size Limits: RSA is not ideal for large data. Use RSA to securely share a symmetric AES key, then encrypt actual messages with AES.

Want to work on real project please visit Internboot.com

What I’d Do Differently Next Time

Use ECDH (Elliptic Curve Diffie-Hellman) instead of RSA—lighter and faster.

  • Move encryption to the front-end completely.
  • Add key verification using fingerprints or hashes.

But for a working demo? This setup delivers.

Final Thoughts: E2EE Isn’t Magic, It’s Math

Once you understand public/private keys, implementing encryption is less about wizardry and more about wiring. Is it perfect? Nope. But it works—and that’s a start.

If you’re building your own version, don’t stop at the basics. Explore:

  • Perfect Forward Secrecy
  • Hybrid encryption
  • Decentralized key servers
  • Password-based key derivation (PBKDF2 or scrypt)

Want the full source code? Let me know—I’ll drop it on GitHub or send it your way.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *