From 4d6a34faa1f960bfef1f28173c8451e519e7580d Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 21 Apr 2015 16:12:20 +0200 Subject: [PATCH] Implement Symmetric-Key Message Encryption using a passphrase See https://tools.ietf.org/html/rfc4880#section-3.7.2.2 --- src/message.js | 54 +++++++++++++++++++++++++++++++++++++++++++ test/general/basic.js | 19 +++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/message.js b/src/message.js index 0c55602c..2f73f969 100644 --- a/src/message.js +++ b/src/message.js @@ -177,6 +177,60 @@ Message.prototype.encrypt = function(keys) { return new Message(packetlist); }; +/** + * Encrypt the message symmetrically using a passphrase. + * https://tools.ietf.org/html/rfc4880#section-3.7.2.2 + * @param {String} passphrase + * @return {Array} new message with encrypted content + */ +Message.prototype.symEncrypt = function(passphrase) { + if (!passphrase) { + throw new Error('The passphrase cannot be empty!'); + } + + var algo = enums.read(enums.symmetric, config.encryption_cipher); + var packetlist = new packet.List(); + + // create a Symmetric-key Encrypted Session Key (ESK) + var symESKPacket = new packet.SymEncryptedSessionKey(); + symESKPacket.sessionKeyAlgorithm = algo; + symESKPacket.decrypt(passphrase); // generate the session key + packetlist.push(symESKPacket); + + // create integrity protected packet + var symEncryptedPacket = new packet.SymEncryptedIntegrityProtected(); + symEncryptedPacket.packets = this.packets; + symEncryptedPacket.encrypt(algo, symESKPacket.sessionKey); + packetlist.push(symEncryptedPacket); + + // remove packets after encryption + symEncryptedPacket.packets = new packet.List(); + return new Message(packetlist); +}; + +/** + * Decrypt the message symmetrically using a passphrase. + * https://tools.ietf.org/html/rfc4880#section-3.7.2.2 + * @param {String} passphrase + * @return {Array} new message with decrypted content + */ +Message.prototype.symDecrypt = function(passphrase) { + var symEncryptedPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey, enums.packet.symEncryptedIntegrityProtected); + + // decrypt Symmetric-key Encrypted Session Key (ESK) + var symESKPacket = symEncryptedPacketlist[0]; + symESKPacket.decrypt(passphrase); + + // decrypt integrity protected packet + var symEncryptedPacket = symEncryptedPacketlist[1]; + symEncryptedPacket.decrypt(symESKPacket.sessionKeyAlgorithm, symESKPacket.sessionKey); + + var resultMsg = new Message(symEncryptedPacket.packets); + // remove packets after decryption + symEncryptedPacket.packets = new packet.List(); + return resultMsg; +}; + /** * Sign the message (the literal data packet of the message) * @param {Array} privateKey private keys with decrypted secret key data for signing diff --git a/test/general/basic.js b/test/general/basic.js index a1e4c6d4..27ba1b50 100644 --- a/test/general/basic.js +++ b/test/general/basic.js @@ -323,6 +323,25 @@ describe('Basic', function() { }); + describe('Encrypt message symmetrically using passphrase', function() { + it('should encrypt/decrypt successfully', function() { + var passphrase = 'passphrase'; + var plaintext = 'secret stuff'; + + // encrypt + var msg = openpgp.message.fromText(plaintext); + msg = msg.symEncrypt(passphrase); + var encrypted = msg.armor(); + + // decrypt + var msg2 = openpgp.message.readArmored(encrypted); + msg2 = msg2.symDecrypt(passphrase); + var decrypted = msg2.getText(); + + expect(decrypted).to.equal(plaintext); + }); + }); + describe("Message 3DES decryption", function() { var pgp_msg = ['-----BEGIN PGP MESSAGE-----',