diff --git a/src/key.js b/src/key.js index e681a5ad..6bcbf8b0 100644 --- a/src/key.js +++ b/src/key.js @@ -842,6 +842,12 @@ Key.prototype.addSubkey = async function(options = {}) { if (!this.isPrivate()) { throw new Error("Cannot add a subkey to a public key"); } + if (options.passphrase) { + throw new Error("Subkey could not be encrypted here, please encrypt whole key"); + } + if (util.getWebCryptoAll() && options.rsaBits < 2048) { + throw new Error('When using webCrypto rsaBits should be 2048 or 4096, found: ' + options.rsaBits); + } const secretKeyPacket = this.primaryKey; if (!secretKeyPacket.isDecrypted()) { throw new Error("Key is not decrypted"); diff --git a/test/general/key.js b/test/general/key.js index 7295c107..af8fdc4f 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -1896,6 +1896,7 @@ function versionSpecificTests() { expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; expect(key.getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign'); expect(key.getAlgorithmInfo().bits).to.equal(opt.numBits); + expect(key.getAlgorithmInfo().rsaBits).to.equal(key.getAlgorithmInfo().bits); expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); }); }); @@ -2868,11 +2869,17 @@ VYGdb3eNlV8CfoEC }); describe('addSubkey functionality testing', function(){ - it('create and add a new rsa subkey to a rsa key', async function() { + let rsaBits; + let rsaOpt = {}; + if (openpgp.util.getWebCryptoAll()) { + rsaBits = 2048; + rsaOpt = { rsaBits: rsaBits }; + } + it('create and add a new rsa subkey to stored rsa key', async function() { const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; await privateKey.decrypt('hello world'); const total = privateKey.subKeys.length; - let newPrivateKey = await privateKey.addSubkey(); + let newPrivateKey = await privateKey.addSubkey(rsaOpt); const armoredKey = newPrivateKey.armor(); newPrivateKey = (await openpgp.key.readArmored(armoredKey)).keys[0]; const subKey = newPrivateKey.subKeys[total]; @@ -2880,17 +2887,24 @@ describe('addSubkey functionality testing', function(){ expect(newPrivateKey.subKeys.length).to.be.equal(total+1); const subkeyN = subKey.keyPacket.params[0]; const pkN = privateKey.primaryKey.params[0]; - expect(subkeyN.byteLength()).to.be.equal(pkN.byteLength()); + expect(subkeyN.byteLength()).to.be.equal(rsaBits ? (rsaBits / 8) : pkN.byteLength()); expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsa_encrypt_sign'); - expect(subKey.getAlgorithmInfo().rsaBits).to.be.equal(1024); + expect(subKey.getAlgorithmInfo().rsaBits).to.be.equal(rsaBits || privateKey.getAlgorithmInfo().rsaBits); expect(await subKey.verify(newPrivateKey.primaryKey)).to.be.equal(openpgp.enums.keyStatus.valid); }); + it('should throw when trying to encrypt a subkey separately from key', async function() { + const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; + await privateKey.decrypt('hello world'); + const opt = { rsaBits: rsaBits, passphrase: 'subkey passphrase'}; + await expect(privateKey.addSubkey(opt)).to.be.rejectedWith('Subkey could not be encrypted here, please encrypt whole key'); + }); + it('encrypt and decrypt key with added subkey', async function() { const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; await privateKey.decrypt('hello world'); const total = privateKey.subKeys.length; - let newPrivateKey = await privateKey.addSubkey(); + let newPrivateKey = await privateKey.addSubkey(rsaOpt); newPrivateKey = (await openpgp.key.readArmored(newPrivateKey.armor())).keys[0]; await newPrivateKey.encrypt('12345678'); const armoredKey = newPrivateKey.armor(); @@ -2899,11 +2913,6 @@ describe('addSubkey functionality testing', function(){ const subKey = importedPrivateKey.subKeys[total]; expect(subKey).to.exist; expect(importedPrivateKey.subKeys.length).to.be.equal(total+1); - const subkeyN = subKey.keyPacket.params[0]; - const pkN = privateKey.primaryKey.params[0]; - expect(subkeyN.byteLength()).to.be.equal(pkN.byteLength()); - expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsa_encrypt_sign'); - expect(subKey.getAlgorithmInfo().rsaBits).to.be.equal(1024); expect(await subKey.verify(importedPrivateKey.primaryKey)).to.be.equal(openpgp.enums.keyStatus.valid); }); @@ -2933,7 +2942,6 @@ describe('addSubkey functionality testing', function(){ it('create and add a new ec subkey to a rsa key', async function() { const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; - privateKey.subKeys = []; await privateKey.decrypt('hello world'); const total = privateKey.subKeys.length; const opt2 = {curve: 'curve25519'}; @@ -3000,7 +3008,7 @@ describe('addSubkey functionality testing', function(){ const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; await privateKey.decrypt('hello world'); const total = privateKey.subKeys.length; - const opt2 = {sign: true}; + const opt2 = { sign: true, rsaBits: rsaBits }; let newPrivateKey = await privateKey.addSubkey(opt2); const armoredKey = newPrivateKey.armor(); newPrivateKey = (await openpgp.key.readArmored(armoredKey)).keys[0]; @@ -3020,7 +3028,7 @@ describe('addSubkey functionality testing', function(){ const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; await privateKey.decrypt('hello world'); const total = privateKey.subKeys.length; - let newPrivateKey = await privateKey.addSubkey(); + let newPrivateKey = await privateKey.addSubkey(rsaOpt); const armoredKey = newPrivateKey.armor(); newPrivateKey = (await openpgp.key.readArmored(armoredKey)).keys[0]; const subKey = newPrivateKey.subKeys[total];