From 22e4540ed9b87c7dd25be048f56d8b6c4fcbced9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Obernd=C3=B6rfer?= Date: Tue, 18 Mar 2014 17:45:15 +0100 Subject: [PATCH] OP-01-007 Algorithm Preferences ignored upon Encryption (Low) --- src/key.js | 34 ++++++++++++++++++++++++++++++++++ src/message.js | 13 ++++++------- test/general/key.js | 24 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/key.js b/src/key.js index 4bc4b58a..703a051d 100644 --- a/src/key.js +++ b/src/key.js @@ -939,6 +939,40 @@ function generate(keyType, numBits, userId, passphrase) { return new Key(packetlist); } +/** + * Returns the preferred symmetric algorithm for a set of keys + * @param {Array} keys Set of keys + * @return {enums.symmetric} Preferred symmetric algorithm + */ +function getPreferredSymAlgo(keys) { + var prioMap = {}; + for (var i = 0; i < keys.length; i++) { + var primaryUser = keys[i].getPrimaryUser(); + if (!primaryUser || !primaryUser.selfCertificate.preferredSymmetricAlgorithms) { + return config.encryption_cipher; + } + primaryUser.selfCertificate.preferredSymmetricAlgorithms.forEach(function(algo, index) { + var entry = prioMap[algo] || (prioMap[algo] = {prio: 0, count: 0, algo: algo}); + entry.prio += 64 >> index; + entry.count++; + }); + } + var prefAlgo = {prio: 0, algo: config.encryption_cipher}; + for (var algo in prioMap) { + try { + if (algo !== enums.symmetric.plaintext && + algo !== enums.symmetric.idea && // not implemented + enums.read(enums.symmetric, algo) && // known algorithm + prioMap[algo].count === keys.length && // available for all keys + prioMap[algo].prio > prefAlgo.prio) { + prefAlgo = prioMap[algo]; + } + } catch (e) {} + } + return prefAlgo.algo; +} + exports.Key = Key; exports.readArmored = readArmored; exports.generate = generate; +exports.getPreferredSymAlgo = getPreferredSymAlgo; diff --git a/src/message.js b/src/message.js index 06041788..f71a2250 100644 --- a/src/message.js +++ b/src/message.js @@ -28,7 +28,8 @@ var packet = require('./packet'), enums = require('./enums.js'), armor = require('./encoding/armor.js'), config = require('./config'), - crypto = require('./crypto'); + crypto = require('./crypto'), + keyModule = require('./key.js'); /** * @class @@ -144,8 +145,8 @@ Message.prototype.getText = function() { */ Message.prototype.encrypt = function(keys) { var packetlist = new packet.List(); - //TODO get preferred algo from signature - var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, config.encryption_cipher)); + var symAlgo = keyModule.getPreferredSymAlgo(keys); + var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, symAlgo)); keys.forEach(function(key) { var encryptionKeyPacket = key.getEncryptionKeyPacket(); if (encryptionKeyPacket) { @@ -153,8 +154,7 @@ Message.prototype.encrypt = function(keys) { pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId(); pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; pkESKeyPacket.sessionKey = sessionKey; - //TODO get preferred algo from signature - pkESKeyPacket.sessionKeyAlgorithm = enums.read(enums.symmetric, config.encryption_cipher); + pkESKeyPacket.sessionKeyAlgorithm = enums.read(enums.symmetric, symAlgo); pkESKeyPacket.encrypt(encryptionKeyPacket); packetlist.push(pkESKeyPacket); } else { @@ -168,8 +168,7 @@ Message.prototype.encrypt = function(keys) { symEncryptedPacket = new packet.SymmetricallyEncrypted(); } symEncryptedPacket.packets = this.packets; - //TODO get preferred algo from signature - symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey); + symEncryptedPacket.encrypt(enums.read(enums.symmetric, symAlgo), sessionKey); packetlist.push(symEncryptedPacket); // remove packets after encryption symEncryptedPacket.packets = new packet.List(); diff --git a/test/general/key.js b/test/general/key.js index 0f377d69..69be263b 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -454,5 +454,29 @@ describe('Key', function() { expect(dest.update.bind(dest, source)).to.throw('Cannot update public key with private key if subkey mismatch'); }); + it('getPreferredSymAlgo() - one key - AES256', function() { + var key1 = openpgp.key.readArmored(twoKeys).keys[0]; + var prefAlgo = openpgp.key.getPreferredSymAlgo([key1]); + expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256); + }); + + it('getPreferredSymAlgo() - two key - AES192', function() { + var keys = openpgp.key.readArmored(twoKeys).keys; + var key1 = keys[0]; + var key2 = keys[1]; + key2.getPrimaryUser().selfCertificate.preferredSymmetricAlgorithms = [6,8,3]; + var prefAlgo = openpgp.key.getPreferredSymAlgo([key1, key2]); + expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes192); + }); + + it('getPreferredSymAlgo() - two key - one without pref', function() { + var keys = openpgp.key.readArmored(twoKeys).keys; + var key1 = keys[0]; + var key2 = keys[1]; + key2.getPrimaryUser().selfCertificate.preferredSymmetricAlgorithms = null; + var prefAlgo = openpgp.key.getPreferredSymAlgo([key1, key2]); + expect(prefAlgo).to.equal(openpgp.config.encryption_cipher); + }); + });