How to encrypt and decrypt using public-private key pair using crypto module?

I have to write a code in Node js using crypto module (as I am not allowed to use any module apart from MIT licensed). I need to generate a key pair and encrypt some message with the pulic key and decrypt it with private key. The first part i.e generation of key pair is done. I am not getting any clue how to use crypto modue to encrypt and decrypt some message using the same key pair.

Upvotes: 2

Views: 8063

Answers (3)

MindSpiker
MindSpiker

Reputation: 1464

This solution:

  • Creates a public-private key pair
  • Exports those keys to files
  • Opens the public key file and uses it to encrypt text and saves it to a file
  • Opens the private key file and uses it to decrypt the encrypted text file

All the data is converted to base64 strings to make it easy to pass these values around on the web.

It is what I was looking for when digesting this process.

'use strict';

import crypto from 'crypto';
import fs from 'fs';

// Make public/private RSA key pair
let keyPair = await crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 4096,
    publicExponent: new Uint8Array([1, 0, 1]),
    hash: "SHA-512",
  },
  true,
  ["encrypt", "decrypt"]
);

// export public key as base64 string and save to file
const exportedPublicKey = await crypto.subtle.exportKey('spki', keyPair.publicKey);
const expPublicKeyBase64 = Buffer.from(exportedPublicKey).toString('base64');
fs.writeFileSync('./publickey.txt', expPublicKeyBase64);

// export private key as base64 string and save to file
const exportedPrivateKey = await crypto.subtle.exportKey('pkcs8', keyPair.privateKey);
const exportedPrivateKeyBase64 = Buffer.from(exportedPrivateKey).toString('base64');
fs.writeFileSync('./privatekey.txt', exportedPrivateKeyBase64);

// import and make public key from base64 file
const publicKeyBase64Buffer = fs.readFileSync('./publickey.txt');
const publicKeyBase64String = Buffer.from(publicKeyBase64Buffer).toString('ascii');
const publicKeyBuffer = Buffer.from(publicKeyBase64String, 'base64');
const publicCryptoKey = await crypto.subtle.importKey(
  'spki',
  publicKeyBuffer,
  { name: 'RSA-OAEP', hash: "SHA-512" },
  false,
  ["encrypt"]
);

// encrypt some plaintext using public key, convert to base64, and save to file
const plainText = 'abc';
const plainTextUInt8 = (new TextEncoder()).encode(plainText);
const cypherTextBuffer = await crypto.subtle.encrypt(
  { name: "RSA-OAEP", hash: "SHA-512" },
  publicCryptoKey,
  plainTextUInt8
);
const cypherTextBase64 = Buffer.from(cypherTextBuffer).toString('base64');
fs.writeFileSync('./cypherText.txt', cypherTextBase64);

// import and make private key from base64 file
const privateKeyBase64Buffer = fs.readFileSync('./privatekey.txt');
const privateKeyBase64String = Buffer.from(privateKeyBase64Buffer).toString('ascii');
const privateKeyBuffer = Buffer.from(privateKeyBase64String, 'base64');
const privateCryptoKey = await crypto.subtle.importKey(
  'pkcs8',
  privateKeyBuffer,
  { name: 'RSA-OAEP', hash: "SHA-512" },
  false,
  ["decrypt"]
);

// open base64 encrypted file and decrypt using private key
const cypherTxtBase64Buffer = fs.readFileSync('./cypherText.txt');
const cypherTxtBase64String = Buffer.from(cypherTxtBase64Buffer).toString('ascii');
const cypherTxtBuffer = Buffer.from(cypherTxtBase64String, 'base64');
const plainTxtBuff = await crypto.subtle.decrypt('RSA-OAEP', privateCryptoKey, cypherTxtBuffer);
const plainTxt = Buffer.from(plainTxtBuff).toString('ascii');
console.log(plainTxt);

Upvotes: 0

gabriel gras
gabriel gras

Reputation: 91

This should do what you want:

const { generateKeyPairSync, publicEncrypt, privateDecrypt } = require('crypto');

//generate a key pair RSA type encryption with a .pem format
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
  modulusLength: 4096,
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',

  }
});

// print out the generated keys
console.log(`PublicKey: ${publicKey}`);
console.log(`PrivateKey: ${privateKey}`);

//message to be encrypted
var toEncrypt = "my secret text to be encrypted";
var encryptBuffer = Buffer.from(toEncrypt);

//encrypt using public key
var encrypted = publicEncrypt(publicKey,encryptBuffer);

//print out the text and cyphertext
console.log("Text to be encrypted:");
console.log(toEncrypt);
console.log("cipherText:");
console.log(encrypted.toString());

//decrypt the cyphertext using the private key
var decryptBuffer = Buffer.from(encrypted.toString("base64"), "base64");
var decrypted = privateDecrypt(privateKey,decryptBuffer);

//print out the decrypted text
console.log("decripted Text:");
console.log(decrypted.toString());

It generates a key pair that can be used to encrypt and decrypt a message.

Upvotes: 9

CaffeineAddiction
CaffeineAddiction

Reputation: 823

In the Node Documentation for the Crypto lib is the following example:

var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp5');
var bob = crypto.getDiffieHellman('modp5');

alice.generateKeys();
bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);

This example shows how to compute a shared secret which can then be used with .createCipher() and .createDecipher() as shown below:

var encrypt64 = function(aMsg, aSecret) {
  var cipher, tRet;
  cipher = crypto.createCipher('aes-256-cbc', aSecret);
  tRet = cipher.update(aMsg, 'utf8', 'base64');
  tRet += cipher.final('base64');
  return tRet;
};

var decrypt64 = function(aMsg, aSecret) {
  var decipher, tRet;
  decipher = crypto.createDecipher('aes-256-cbc', aSecret);
  tRet = decipher.update(aMsg.replace(/\s/g, "+"), 'base64', 'utf8');
  tRet += decipher.final('utf8');
  return tRet;
};

Upvotes: 0

Related Questions