secure transmit sensitive data over the internet with RSA encrypt & decrypt algorithm in node.js via 'crypto'

secure transmit sensitive data over the internet with RSA encrypt & decrypt algorithm in node.js via 'crypto'
Photo by David Becker / Unsplash

To securely transmit sensitive data over the internet, such as passwords for login, it's crucial to encrypt or hash the data. HTTPS alone may not be enough. The process involves generating a key pair on the server backend, consisting of a public key and a private key. The server keeps the private key secure and sends the public key to the client as a cookie. On the client side, the public key is used to encrypt data, such as passwords, before sending it to the server. When the server receives the encrypted data, it decrypts it using the private key to obtain the original plain text. If the backend can access the hashed password of the user, there's no need to decrypt it, just compare the hash. However, if external API calls are needed to check the validity of the username and password, encryption on the client side and decryption on the server side after secure transmission over the internet is necessary.

Util functions in typescript

import { KeyPairSyncResult, generateKeyPairSync, privateDecrypt, constants, publicEncrypt } from 'crypto';
import { Request, Response } from 'express';
import { RSA_OAEP_KEY_COOKIE } from './types';

let RSA_OAEP_KEY_PAIR: KeyPairSyncResult<string, string>;

export function generateKeyPair() {
    if (!RSA_OAEP_KEY_PAIR) {
        RSA_OAEP_KEY_PAIR = generateKeyPairSync('rsa', {
            modulusLength: 2048,
            publicKeyEncoding: { type: 'spki', format: 'pem' },
            privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
        });
    }
}

export function setPublicKeyCookie(req: Request, res: Response) {
    res.cookie(RSA_OAEP_KEY_COOKIE, RSA_OAEP_KEY_PAIR.publicKey, { secure: req.secure });
}

export function getPublicKey() {
    return RSA_OAEP_KEY_PAIR.publicKey;
}

export function getPrivateKey() {
    return RSA_OAEP_KEY_PAIR.privateKey;
}

export function decrypt(encryptedText: string): string {
    const buffer = Buffer.from(encryptedText, 'base64');
    const decrypted = privateDecrypt({
        key: RSA_OAEP_KEY_PAIR.privateKey,
        padding: constants.RSA_PKCS1_OAEP_PADDING,
        passphrase: '' // Only needed if the private key is encrypted
    }, buffer);
    return decrypted.toString();
}

export function encrypt(plainText: string): string {
    const buffer = Buffer.from(plainText);
    const decrypted = publicEncrypt({
        key: RSA_OAEP_KEY_PAIR.privateKey,
        padding: constants.RSA_PKCS1_OAEP_PADDING,
        passphrase: '' // Only needed if the private key is encrypted
    }, buffer);
    return decrypted.toString('base64');
}

Unit Tests

import { generateKeyPair, encrypt, decrypt } from ".";

describe("rsaoaep", () => {
    it("should generate RSA-OAEP key pair", () => {
        // Test that the RSA-OAEP key pair is generated
        generateKeyPair();
        const plain_text = "lengerrong";
        const encrypted_text = encrypt(plain_text);
        console.log("encrypted_text", encrypted_text);
        const decrypted_text = decrypt(encrypted_text);
        console.log("decrypted_text", decrypted_text);
        expect(decrypted_text).toEqual(plain_text);
    });
});

you should see the test pass.

  console.log
    encrypted_text I+b8qYByZXHcOENeMoX3mUXS51TSixUMNsC2aujQOaeVwzInftY1yYhqIwlyxgRQlWKZRYBvTrZzwj1ur2/qb1w3q9VBnmurRWCPy3uFTvX73CxdO2Wvqx0V73YyJW6UMLbVVlNBkqgVmwSY25+TzNNPv5Fgd4TY+paLrkNrVEBkMa4upzJI6aIMiU9AfWkWwQu04yBn4JoXj/6k7tCYPeJxDnzI5M4vQdxBxiyyCV1SEo0xTL/Pb2tfzS7MKv6C9fd2if+TH3TxcKcZgmB8+Z0NZY0pawUcR2KFOnionUQedfjpsTIrPpRmyZ9Iistoxo/OTvG1oqdwMuAb80Y0eg==

      at Object.<anonymous> (middleware/rsaoaep/index.test.ts:9:17)

  console.log
    decrypted_text lengerrong

      at Object.<anonymous> (middleware/rsaoaep/index.test.ts:11:17)

(node:73433) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
 PASS   activate  apps/activate/middleware/rsaoaep/index.test.ts
  rsaoaep
    ✓ should generate RSA-OAEP key pair (306 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.288 s

Subscribe to Post, Code and Quiet Time.

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe