Skip to content

Instantly share code, notes, and snippets.

@mixinmax
Created March 12, 2015 19:23
Show Gist options
  • Select an option

  • Save mixinmax/9fdd52933f4a5f8ec10d to your computer and use it in GitHub Desktop.

Select an option

Save mixinmax/9fdd52933f4a5f8ec10d to your computer and use it in GitHub Desktop.
Takes the binary output from rsa-encrypt.js and checks the signature, decrypts the symmetric key, and decrypts the message
'use strict';
// set up required modules
var fs = require('fs');
var args = require('minimist')(process.argv.slice(2));
// the ursa module is imported to wrap OpenSSL and provide RSA decryption for
// the digital signing aswell as decrypting the symmetric key. URSA cannot do
// symmetric decryption natively, so we need another module for that
var ursa = require('ursa');
// the crypto module allows for the decryption of the message using the
// symmetric key from the binary file
var crypto = require('crypto');
// make sure the proper amount of arguments exist
// this line could probably be a bit shorter...
if (!args.hasOwnProperty('in') || !args.hasOwnProperty('public') || !args.hasOwnProperty('private')) {
console.log("Usage: node decrypt.js --in=inputFile --public=publickey --private=privatekey");
process.exit(1);
}
console.log("\nNSA's Standard Decryption Utility");
console.log("with no backdoors (we swear)\n");
// wrap the whole program in a try/catch statement in case there has been
// tampering with the encrypted data. this would result in buffer size issues
// which would cause the program to crash without informing the user to the
// possible interception of their message
try {
// read the three sections of the file into memory
// the first 512 bytes are the signature, the next 512 bytes are the encrypted
// symmetric key - everything else is the ciphertext
var fd = fs.openSync(args.in, 'r');
var filesize = fs.statSync(args.in)['size'];
var sig = new Buffer(256);
fs.readSync(fd, sig, 0, 256, 0);
var enc_token = new Buffer(256);
fs.readSync(fd, enc_token, 0, 256, 256);
var enc_msg = new Buffer(filesize-512);
fs.readSync(fd, enc_msg, 0, filesize-512, 512);
// create the public and private keys
var key = ursa.createPrivateKey(fs.readFileSync(args.private));
var crt = ursa.createPublicKey(fs.readFileSync(args.public));
// decrypt the symmetric key using our private key
var token = key.decrypt(enc_token, 'hex', 'hex');
token = new Buffer(token, 'hex');
// decrypt the message using the symmetric key
var decipher = crypto.createDecipher('aes-256-cbc', token)
var msg = decipher.update(enc_msg, 'hex', 'hex')
msg += decipher.final('hex');
msg = new Buffer(msg, 'hex');
// verify the signature of the message using the other user's public key
var check = crt.hashAndVerify('sha256', msg, sig, 'hex', true, ursa.RSA_PKCS1_SALT_LEN_HLEN)
// if the signature doesn't match - we have a problem
if (check == false) {
console.log("Warning! The message's signature is not correct. Aborting.\n")
process.exit(1);
}
// output the message to a file
fs.writeFile('message.txt', msg.toString('utf8'));
console.log("Success! Everything checks out");
console.log("Your plaintext message was saved to ./message.txt\n");
} catch (e) {
console.log("\nWarning! It seems the message has been tampered with. Aborting.\n");
process.exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment