From 1c818f2410bb098299d41006b41b0099f3daebe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Obernd=C3=B6rfer?= Date: Fri, 28 Mar 2014 21:39:54 +0100 Subject: [PATCH] OP-01-006 Generated keys have no stored algorithm preference (Medium). Set preferences for symmetric, hash and compression algorithms. Fix preferred_compression_algorithms subpacket reading. --- src/key.js | 26 ++++++++++++++++++++++---- src/openpgp.js | 2 +- src/packet/signature.js | 11 +++-------- test/general/key.js | 21 +++++++++++++++++++++ test/worker/api.js | 4 ++-- 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/key.js b/src/key.js index 703a051d..e6678fcc 100644 --- a/src/key.js +++ b/src/key.js @@ -893,6 +893,11 @@ function readArmored(armoredText) { * @static */ function generate(keyType, numBits, userId, passphrase) { + // RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated + if (keyType !== enums.publicKey.rsa_encrypt_sign) { + throw new Error('Only RSA Encrypt or Sign supported'); + } + var packetlist = new packet.List(); var secretKeyPacket = new packet.SecretKey(); @@ -909,9 +914,23 @@ function generate(keyType, numBits, userId, passphrase) { var signaturePacket = new packet.Signature(); signaturePacket.signatureType = enums.signature.cert_generic; signaturePacket.publicKeyAlgorithm = keyType; - //TODO we should load preferred hash from config, or as input to this function - signaturePacket.hashAlgorithm = enums.hash.sha256; + signaturePacket.hashAlgorithm = config.prefer_hash_algorithm; signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; + signaturePacket.preferredSymmetricAlgorithms = []; + signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes256); + signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192); + signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes128); + signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5); + signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes); + signaturePacket.preferredHashAlgorithms = []; + signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256); + signaturePacket.preferredHashAlgorithms.push(enums.hash.sha1); + signaturePacket.preferredHashAlgorithms.push(enums.hash.sha512); + signaturePacket.preferredCompressionAlgorithms = []; + signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zlib); + signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zip); + signaturePacket.features = []; + signaturePacket.features.push(1); // Modification Detection signaturePacket.sign(secretKeyPacket, dataToSign); var secretSubkeyPacket = new packet.SecretSubkey(); @@ -925,8 +944,7 @@ function generate(keyType, numBits, userId, passphrase) { var subkeySignaturePacket = new packet.Signature(); subkeySignaturePacket.signatureType = enums.signature.subkey_binding; subkeySignaturePacket.publicKeyAlgorithm = keyType; - //TODO we should load preferred hash from config, or as input to this function - subkeySignaturePacket.hashAlgorithm = enums.hash.sha256; + subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm; subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage]; subkeySignaturePacket.sign(secretKeyPacket, dataToSign); diff --git a/src/openpgp.js b/src/openpgp.js index 30924aec..95e66db8 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -204,7 +204,7 @@ function verifyClearSignedMessage(publicKeys, msg, callback) { * @param {String} userId assumes already in form of "User Name " * @param {String} passphrase The passphrase used to encrypt the resulting private key * @param {function} callback (optional) callback(error, result) for async style - * @return {Object} {key: Array, privateKeyArmored: Array, publicKeyArmored: Array} + * @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String} * @static */ function generateKeyPair(keyType, numBits, userId, passphrase, callback) { diff --git a/src/packet/signature.js b/src/packet/signature.js index 607a0528..efa6c515 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -294,7 +294,7 @@ Signature.prototype.write_all_sub_packets = function () { } if (this.preferredCompressionAlgorithms !== null) { bytes = util.bin2str(this.preferredCompressionAlgorithms); - result += write_sub_packet(sub.preferred_hash_algorithms, bytes); + result += write_sub_packet(sub.preferred_compression_algorithms, bytes); } if (this.keyServerPreferences !== null) { bytes = util.bin2str(this.keyServerPreferences); @@ -411,12 +411,7 @@ Signature.prototype.read_sub_packet = function (bytes) { break; case 11: // Preferred Symmetric Algorithms - this.preferredSymmetricAlgorithms = []; - - while (mypos != bytes.length) { - this.preferredSymmetricAlgorithms.push(bytes.charCodeAt(mypos++)); - } - + read_array.call(this, 'preferredSymmetricAlgorithms', bytes.substr(mypos)); break; case 12: // Revocation Key @@ -458,7 +453,7 @@ Signature.prototype.read_sub_packet = function (bytes) { break; case 22: // Preferred Compression Algorithms - read_array.call(this, 'preferredCompressionAlgorithms ', bytes.substr(mypos)); + read_array.call(this, 'preferredCompressionAlgorithms', bytes.substr(mypos)); break; case 23: // Key Server Preferences diff --git a/test/general/key.js b/test/general/key.js index 0a206c8c..89432efa 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -476,5 +476,26 @@ describe('Key', function() { expect(prefAlgo).to.equal(openpgp.config.encryption_cipher); }); + it('Preferences of generated key', function() { + var testPref = function(key) { + // key flags + var keyFlags = openpgp.enums.keyFlags; + expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys); + expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data); + expect(key.subKeys[0].bindingSignature.keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication); + expect(key.subKeys[0].bindingSignature.keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage); + var sym = openpgp.enums.symmetric; + expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes192, sym.aes128, sym.cast5, sym.tripledes]); + var hash = openpgp.enums.hash; + expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha1, hash.sha512]); + var compr = openpgp.enums.compression; + expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]); + expect(key.users[0].selfCertifications[0].features).to.eql([1]); // modification detection + } + var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 512, 'test', 'hello'); + testPref(key.key); + testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]); + }); + }); diff --git a/test/worker/api.js b/test/worker/api.js index d5063d19..b40cef9b 100644 --- a/test/worker/api.js +++ b/test/worker/api.js @@ -398,7 +398,7 @@ describe('High level API', function() { describe('Key generation', function() { it('Generate 1024-bit RSA/RSA key async', function (done) { - openpgp.generateKeyPair(3, 1024, 'Test McTestington ', 'hello world', function(err, data) { + openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington ', 'hello world', function(err, data) { expect(err).to.not.exist; expect(data).to.exist; expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/); @@ -409,7 +409,7 @@ describe('High level API', function() { }); it('Generate 1024-bit RSA/RSA key sync', function () { - var key = openpgp.generateKeyPair(3, 1024, 'Test McTestington ', 'hello world'); + var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington ', 'hello world'); expect(key).to.exist; expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/); expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);