diff --git a/src/key.js b/src/key.js index b3ad870a..04cb2593 100644 --- a/src/key.js +++ b/src/key.js @@ -906,7 +906,8 @@ function readArmored(armoredText) { * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] to indicate what type of key to make. * RSA is 1. See {@link http://tools.ietf.org/html/rfc4880#section-9.1} * @param {Integer} options.numBits number of bits for the key creation. - * @param {String} options.userId assumes already in form of "User Name " + * @param {String|Array} options.userId assumes already in form of "User Name " + If array is used, the first userId is set as primary user Id * @param {String} options.passphrase The passphrase used to encrypt the resulting private key * @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked * @return {module:key~Key} @@ -924,6 +925,9 @@ function generate(options) { if (!options.passphrase) { options.unlocked = true; } + if (String.prototype.isPrototypeOf(options.userId) || typeof options.userId === 'string') { + options.userId = [options.userId]; + } // generate var genSecretKey = generateSecretKey(); @@ -951,35 +955,47 @@ function generate(options) { packetlist = new packet.List(); - userIdPacket = new packet.Userid(); - userIdPacket.read(options.userId); + packetlist.push(secretKeyPacket); - dataToSign = {}; - dataToSign.userid = userIdPacket; - dataToSign.key = secretKeyPacket; - signaturePacket = new packet.Signature(); - signaturePacket.signatureType = enums.signature.cert_generic; - signaturePacket.publicKeyAlgorithm = options.keyType; - 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); - if (config.integrity_protect) { - signaturePacket.features = []; - signaturePacket.features.push(1); // Modification Detection - } - signaturePacket.sign(secretKeyPacket, dataToSign); + options.userId.forEach(function(userId, index) { + + userIdPacket = new packet.Userid(); + userIdPacket.read(userId); + + dataToSign = {}; + dataToSign.userid = userIdPacket; + dataToSign.key = secretKeyPacket; + signaturePacket = new packet.Signature(); + signaturePacket.signatureType = enums.signature.cert_generic; + signaturePacket.publicKeyAlgorithm = options.keyType; + 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); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + if (config.integrity_protect) { + signaturePacket.features = []; + signaturePacket.features.push(1); // Modification Detection + } + signaturePacket.sign(secretKeyPacket, dataToSign); + + packetlist.push(userIdPacket); + packetlist.push(signaturePacket); + + }); dataToSign = {}; dataToSign.key = secretKeyPacket; @@ -991,9 +1007,6 @@ function generate(options) { subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage]; subkeySignaturePacket.sign(secretKeyPacket, dataToSign); - packetlist.push(secretKeyPacket); - packetlist.push(userIdPacket); - packetlist.push(signaturePacket); packetlist.push(secretSubkeyPacket); packetlist.push(subkeySignaturePacket); diff --git a/test/general/key.js b/test/general/key.js index 75e4a8f6..e3be1c32 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -666,5 +666,31 @@ var pgp_desktop_priv = }); }); + it('Generate key - single userid', function(done) { + var userId = 'single user'; + var opt = {numBits: 512, userId: userId, passphrase: '123'}; + openpgp.generateKeyPair(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal(userId); + done(); + }).catch(done); + }); + + it('Generate key - multi userid', function(done) { + var userId1 = 'first user'; + var userId2 = 'second user'; + var opt = {numBits: 512, userId: [userId1, userId2], passphrase: '123'}; + openpgp.generateKeyPair(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(2); + expect(key.users[0].userId.userid).to.equal(userId1); + expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; + expect(key.users[1].userId.userid).to.equal(userId2); + expect(key.users[1].selfCertifications[0].isPrimaryUserID).to.be.null; + done(); + }).catch(done); + }); + });