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.

This commit is contained in:
Thomas Oberndörfer 2014-03-28 21:39:54 +01:00
parent b9c597a41a
commit 1c818f2410
5 changed files with 49 additions and 15 deletions

View File

@ -893,6 +893,11 @@ function readArmored(armoredText) {
* @static * @static
*/ */
function generate(keyType, numBits, userId, passphrase) { 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 packetlist = new packet.List();
var secretKeyPacket = new packet.SecretKey(); var secretKeyPacket = new packet.SecretKey();
@ -909,9 +914,23 @@ function generate(keyType, numBits, userId, passphrase) {
var signaturePacket = new packet.Signature(); var signaturePacket = new packet.Signature();
signaturePacket.signatureType = enums.signature.cert_generic; signaturePacket.signatureType = enums.signature.cert_generic;
signaturePacket.publicKeyAlgorithm = keyType; signaturePacket.publicKeyAlgorithm = keyType;
//TODO we should load preferred hash from config, or as input to this function signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
signaturePacket.hashAlgorithm = enums.hash.sha256;
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; 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); signaturePacket.sign(secretKeyPacket, dataToSign);
var secretSubkeyPacket = new packet.SecretSubkey(); var secretSubkeyPacket = new packet.SecretSubkey();
@ -925,8 +944,7 @@ function generate(keyType, numBits, userId, passphrase) {
var subkeySignaturePacket = new packet.Signature(); var subkeySignaturePacket = new packet.Signature();
subkeySignaturePacket.signatureType = enums.signature.subkey_binding; subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
subkeySignaturePacket.publicKeyAlgorithm = keyType; subkeySignaturePacket.publicKeyAlgorithm = keyType;
//TODO we should load preferred hash from config, or as input to this function subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
subkeySignaturePacket.hashAlgorithm = enums.hash.sha256;
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage]; subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
subkeySignaturePacket.sign(secretKeyPacket, dataToSign); subkeySignaturePacket.sign(secretKeyPacket, dataToSign);

View File

@ -204,7 +204,7 @@ function verifyClearSignedMessage(publicKeys, msg, callback) {
* @param {String} userId assumes already in form of "User Name <username@email.com>" * @param {String} userId assumes already in form of "User Name <username@email.com>"
* @param {String} passphrase The passphrase used to encrypt the resulting private key * @param {String} passphrase The passphrase used to encrypt the resulting private key
* @param {function} callback (optional) callback(error, result) for async style * @param {function} callback (optional) callback(error, result) for async style
* @return {Object} {key: Array<module:key~Key>, privateKeyArmored: Array<String>, publicKeyArmored: Array<String>} * @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String}
* @static * @static
*/ */
function generateKeyPair(keyType, numBits, userId, passphrase, callback) { function generateKeyPair(keyType, numBits, userId, passphrase, callback) {

View File

@ -294,7 +294,7 @@ Signature.prototype.write_all_sub_packets = function () {
} }
if (this.preferredCompressionAlgorithms !== null) { if (this.preferredCompressionAlgorithms !== null) {
bytes = util.bin2str(this.preferredCompressionAlgorithms); 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) { if (this.keyServerPreferences !== null) {
bytes = util.bin2str(this.keyServerPreferences); bytes = util.bin2str(this.keyServerPreferences);
@ -411,12 +411,7 @@ Signature.prototype.read_sub_packet = function (bytes) {
break; break;
case 11: case 11:
// Preferred Symmetric Algorithms // Preferred Symmetric Algorithms
this.preferredSymmetricAlgorithms = []; read_array.call(this, 'preferredSymmetricAlgorithms', bytes.substr(mypos));
while (mypos != bytes.length) {
this.preferredSymmetricAlgorithms.push(bytes.charCodeAt(mypos++));
}
break; break;
case 12: case 12:
// Revocation Key // Revocation Key
@ -458,7 +453,7 @@ Signature.prototype.read_sub_packet = function (bytes) {
break; break;
case 22: case 22:
// Preferred Compression Algorithms // Preferred Compression Algorithms
read_array.call(this, 'preferredCompressionAlgorithms ', bytes.substr(mypos)); read_array.call(this, 'preferredCompressionAlgorithms', bytes.substr(mypos));
break; break;
case 23: case 23:
// Key Server Preferences // Key Server Preferences

View File

@ -476,5 +476,26 @@ describe('Key', function() {
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher); 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]);
});
}); });

View File

@ -398,7 +398,7 @@ describe('High level API', function() {
describe('Key generation', function() { describe('Key generation', function() {
it('Generate 1024-bit RSA/RSA key async', function (done) { it('Generate 1024-bit RSA/RSA key async', function (done) {
openpgp.generateKeyPair(3, 1024, 'Test McTestington <test@example.com>', 'hello world', function(err, data) { openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington <test@example.com>', 'hello world', function(err, data) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(data).to.exist; expect(data).to.exist;
expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/); 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 () { it('Generate 1024-bit RSA/RSA key sync', function () {
var key = openpgp.generateKeyPair(3, 1024, 'Test McTestington <test@example.com>', 'hello world'); var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington <test@example.com>', 'hello world');
expect(key).to.exist; expect(key).to.exist;
expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/); expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/); expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);