Skip to content

Commit

Permalink
Generate ECC keys by default (#1065)
Browse files Browse the repository at this point in the history
Also, remove the deprecated numBits options of generateKey in favor of rsaBits.
  • Loading branch information
larabr authored and twiss committed Dec 12, 2020
1 parent 5830fc2 commit 3f087df
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/key/factory.js
Expand Up @@ -41,7 +41,7 @@ import armor from '../encoding/armor';
* @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 https://tools.ietf.org/html/rfc4880#section-9.1}
* @param {Integer} options.numBits number of bits for the key creation.
* @param {Integer} options.rsaBits number of bits for the key creation.
* @param {String|Array<String>} options.userIds
* Assumes already in form of "User Name <username@email.com>"
* If array is used, the first userId is set as primary user Id
Expand Down
5 changes: 3 additions & 2 deletions src/openpgp.js
Expand Up @@ -129,10 +129,11 @@ export async function destroyWorker() {
* @async
* @static
*/
export function generateKey({ userIds = [], passphrase = "", numBits = 2048, rsaBits = numBits, keyExpirationTime = 0, curve = "", date = new Date(), subkeys = [{}] }) {
export function generateKey({ userIds = [], passphrase = "", rsaBits = null, keyExpirationTime = 0, curve = "curve25519", date = new Date(), subkeys = [{}] }) {
userIds = toArray(userIds);
curve = rsaBits ? "" : curve;
const options = { userIds, passphrase, rsaBits, keyExpirationTime, curve, date, subkeys };
if (util.getWebCryptoAll() && rsaBits < 2048) {
if (util.getWebCryptoAll() && rsaBits && rsaBits < 2048) {
throw new Error('rsaBits should be 2048 or 4096, found: ' + rsaBits);
}

Expand Down
86 changes: 41 additions & 45 deletions test/general/key.js
Expand Up @@ -1986,8 +1986,7 @@ function versionSpecificTests() {
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip, compr.uncompressed]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.v5_keys ? [7] : [1]);
};
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test <a@b.com>', passphrase: 'hello'};
return openpgp.generateKey(opt).then(async function(key) {
testPref(key.key);
testPref(await openpgp.key.readArmored(key.publicKeyArmored));
Expand Down Expand Up @@ -2028,8 +2027,7 @@ function versionSpecificTests() {
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip, compr.uncompressed]);
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.v5_keys ? [7] : [1]);
};
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test <a@b.com>', passphrase: 'hello'};
try {
const key = await openpgp.generateKey(opt);
testPref(key.key);
Expand All @@ -2048,8 +2046,7 @@ function versionSpecificTests() {
});

it('Generated key is not unlocked by default', function() {
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test <a@b.com>', passphrase: '123'};
let key;
return openpgp.generateKey(opt).then(function(newKey) {
key = newKey.key;
Expand All @@ -2063,8 +2060,7 @@ function versionSpecificTests() {

it('Generate key - single userid', function() {
const userId = { name: 'test', email: 'a@b.com', comment: 'test comment' };
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: '123'};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand All @@ -2077,8 +2073,7 @@ function versionSpecificTests() {

it('Generate key - single userid (all missing)', function() {
const userId = { name: '', email: '', comment: '' };
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: '123'};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand All @@ -2091,8 +2086,7 @@ function versionSpecificTests() {

it('Generate key - single userid (missing email)', function() {
const userId = { name: 'test', email: '', comment: 'test comment' };
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: '123'};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand All @@ -2105,8 +2099,7 @@ function versionSpecificTests() {

it('Generate key - single userid (missing comment)', function() {
const userId = { name: 'test', email: 'a@b.com', comment: '' };
const opt = {numBits: 512, userIds: userId, passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: '123'};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand All @@ -2120,12 +2113,10 @@ function versionSpecificTests() {
it('Generate key - setting date to the past', function() {
const past = new Date(0);
const opt = {
numBits: 512,
userIds: { name: 'Test User', email: 'text@example.com' },
passphrase: 'secret',
date: past
};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

return openpgp.generateKey(opt).then(function(newKey) {
expect(newKey.key).to.exist;
Expand All @@ -2138,12 +2129,10 @@ function versionSpecificTests() {
it('Generate key - setting date to the future', function() {
const future = new Date(Math.ceil(Date.now() / 1000) * 1000 + 1000);
const opt = {
numBits: 512,
userIds: { name: 'Test User', email: 'text@example.com' },
passphrase: 'secret',
date: future
};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

return openpgp.generateKey(opt).then(function(newKey) {
expect(newKey.key).to.exist;
Expand All @@ -2156,8 +2145,7 @@ function versionSpecificTests() {
it('Generate key - multi userid', function() {
const userId1 = 'test <a@b.com>';
const userId2 = 'test <b@c.com>';
const opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: [userId1, userId2], passphrase: '123'};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(2);
Expand All @@ -2170,7 +2158,7 @@ function versionSpecificTests() {

it('Generate key - two subkeys with default values', function() {
const userId = 'test <a@b.com>';
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]};
const opt = {userIds: [userId], passphrase: '123', subkeys:[{},{}]};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand All @@ -2182,9 +2170,25 @@ function versionSpecificTests() {
});
});

it('Generate RSA key - two subkeys with default values', function() {
const userId = 'test <a@b.com>';
const opt = {rsaBits: 512, userIds: [userId], passphrase: '123', subkeys:[{},{}]};
if (openpgp.util.getWebCryptoAll()) { opt.rsaBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
expect(key.users[0].userId.userid).to.equal(userId);
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
expect(key.subKeys).to.have.length(2);
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign');
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign');
});
});

it('Generate key - one signing subkey', function() {
const userId = 'test <a@b.com>';
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
const opt = {userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
return openpgp.generateKey(opt).then(async function({ privateKeyArmored }) {
const key = await openpgp.key.readArmored(privateKeyArmored);
expect(key.users.length).to.equal(1);
Expand All @@ -2200,7 +2204,7 @@ function versionSpecificTests() {

it('Reformat key - one signing subkey', function() {
const userId = 'test <a@b.com>';
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
const opt = {userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
return openpgp.generateKey(opt).then(async function({ key }) {
await key.decrypt('123');
return openpgp.reformatKey({ privateKey: key, userIds: [userId] });
Expand All @@ -2217,26 +2221,25 @@ function versionSpecificTests() {
});
});

it('Generate key - override main key options for subkey', function() {
it('Generate key - override main RSA key options for subkey', function() {
const userId = 'test <a@b.com>';
const opt = {numBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {rsaBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]};
if (openpgp.util.getWebCryptoAll()) { opt.rsaBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
expect(key.users[0].userId.userid).to.equal(userId);
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().bits).to.equal(opt.rsaBits);
expect(key.getAlgorithmInfo().rsaBits).to.equal(key.getAlgorithmInfo().bits);
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
});
});

it('Encrypt key with new passphrase', async function() {
const userId = 'test <a@b.com>';
const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: 'passphrase'};
const key = (await openpgp.generateKey(opt)).key;
const armor1 = key.armor();
const armor2 = key.armor();
Expand All @@ -2256,8 +2259,7 @@ function versionSpecificTests() {
it('Generate key - ensure keyExpirationTime works', function() {
const expect_delta = 365 * 24 * 60 * 60;
const userId = 'test <a@b.com>';
const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId, passphrase: '123', keyExpirationTime: expect_delta};
return openpgp.generateKey(opt).then(async function(key) {
key = key.key;

Expand Down Expand Up @@ -2356,8 +2358,7 @@ function versionSpecificTests() {
it('Reformat key without passphrase', function() {
const userId1 = 'test1 <a@b.com>';
const userId2 = 'test2 <b@a.com>';
const opt = {numBits: 512, userIds: userId1};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId1};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
expect(key.users.length).to.equal(1);
Expand Down Expand Up @@ -2391,7 +2392,7 @@ function versionSpecificTests() {
const userId2 = 'test <b@c.com>';
const now = openpgp.util.normalizeDate(new Date());
const before = openpgp.util.normalizeDate(new Date(0));
const opt1 = {curve: 'curve25519', userIds: [userId1], date: now};
const opt1 = {userIds: [userId1], date: now};
return openpgp.generateKey(opt1).then(function(newKey) {
newKey = newKey.key;
expect(newKey.users[0].userId.userid).to.equal(userId1);
Expand Down Expand Up @@ -2434,8 +2435,7 @@ function versionSpecificTests() {
const userId1 = 'test1 <a@b.com>';
const userId2 = 'test2 <b@c.com>';
const userId3 = 'test3 <c@d.com>';
const opt = {numBits: 512, userIds: userId1};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId1};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
opt.privateKey = key;
Expand All @@ -2455,8 +2455,7 @@ function versionSpecificTests() {
it('Sign and encrypt with reformatted key', function() {
const userId1 = 'test1 <a@b.com>';
const userId2 = 'test2 <b@a.com>';
const opt = {numBits: 512, userIds: userId1};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: userId1};
return openpgp.generateKey(opt).then(function(key) {
key = key.key;
opt.privateKey = key;
Expand All @@ -2474,8 +2473,7 @@ function versionSpecificTests() {
});

it('Reject with user-friendly error when reformatting encrypted key', function() {
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test1 <a@b.com>', passphrase: '1234'};
return openpgp.generateKey(opt).then(function(original) {
return openpgp.reformatKey({privateKey: original.key, userIds: 'test2 <b@a.com>', passphrase: '1234'}).then(function() {
throw new Error('reformatKey should result in error when key not decrypted');
Expand All @@ -2486,8 +2484,7 @@ function versionSpecificTests() {
});

it('Revoke generated key with revocation certificate', function() {
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test1 <a@b.com>', passphrase: '1234'};
return openpgp.generateKey(opt).then(function(original) {
return openpgp.revokeKey({key: original.key.toPublic(), revocationCertificate: original.revocationCertificate}).then(async function(revKey) {
revKey = revKey.publicKey;
Expand All @@ -2499,8 +2496,7 @@ function versionSpecificTests() {
});

it('Revoke generated key with private key', function() {
const opt = {numBits: 512, userIds: 'test1 <a@b.com>', passphrase: '1234'};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
const opt = {userIds: 'test1 <a@b.com>', passphrase: '1234'};
return openpgp.generateKey(opt).then(async function(original) {
await original.key.decrypt('1234');
return openpgp.revokeKey({key: original.key, reasonForRevocation: {string: 'Testing key revocation'}}).then(async function(revKey) {
Expand Down Expand Up @@ -3308,7 +3304,7 @@ VYGdb3eNlV8CfoEC

it("Should throw when trying to encrypt a key that's already encrypted", async function() {
await expect((async function() {
let { privateKeyArmored } = await openpgp.generateKey({ userIds: [{ email: 'hello@user.com' }], passphrase: 'pass', numBits: openpgp.util.getWebCryptoAll() ? 2048 : 512 });
let { privateKeyArmored } = await openpgp.generateKey({ userIds: [{ email: 'hello@user.com' }], passphrase: 'pass' });
let k = await openpgp.key.readArmored(privateKeyArmored);
await k.decrypt('pass');
await k.encrypt('pass');
Expand Down
11 changes: 2 additions & 9 deletions test/general/openpgp.js
Expand Up @@ -587,9 +587,9 @@ describe('OpenPGP.js public api tests', function() {
expect(keyGenStub.withArgs({
userIds: [{ name: 'Test User', email: 'text@example.com' }],
passphrase: 'secret',
rsaBits: 2048,
rsaBits: null,
keyExpirationTime: 0,
curve: "",
curve: "curve25519",
date: now,
subkeys: []
}).calledOnce).to.be.true;
Expand Down Expand Up @@ -641,7 +641,6 @@ describe('OpenPGP.js public api tests', function() {
openpgp.destroyWorker();
const opt = {
userIds: [{ name: 'Test User', email: 'text@example.com' }],
numBits: 512
};

return openpgp.generateKey(opt).then(function(newKey) {
Expand All @@ -660,7 +659,6 @@ describe('OpenPGP.js public api tests', function() {
}
const opt = {
userIds: [{ name: 'Test User', email: 'text@example.com' }],
numBits: 512
};

return openpgp.generateKey(opt).then(function(newKey) {
Expand All @@ -674,9 +672,7 @@ describe('OpenPGP.js public api tests', function() {
openpgp.config.use_native = true;
const opt = {
userIds: [{ name: 'Test User', email: 'text@example.com' }],
numBits: 512
};
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

return openpgp.generateKey(opt).then(function(newKey) {
expect(newKey.key.getUserIds()[0]).to.equal('Test User <text@example.com>');
Expand Down Expand Up @@ -1262,9 +1258,7 @@ describe('OpenPGP.js public api tests', function() {
it('should encrypt/sign and decrypt/verify with generated key', function () {
const genOpt = {
userIds: [{ name: 'Test User', email: 'text@example.com' }],
numBits: 512
};
if (openpgp.util.getWebCryptoAll()) { genOpt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys

return openpgp.generateKey(genOpt).then(async function(newKey) {
const newPublicKey = await openpgp.key.readArmored(newKey.publicKeyArmored);
Expand Down Expand Up @@ -1296,7 +1290,6 @@ describe('OpenPGP.js public api tests', function() {
it('should encrypt/sign and decrypt/verify with generated key and detached signatures', async function () {
const newKey = await openpgp.generateKey({
userIds: [{ name: 'Test User', email: 'text@example.com' }],
numBits: openpgp.util.getWebCryptoAll() ? 2048 : 512 // webkit webcrypto accepts minimum 2048 bit keys
});
const newPublicKey = await openpgp.key.readArmored(newKey.publicKeyArmored);
const newPrivateKey = await openpgp.key.readArmored(newKey.privateKeyArmored);
Expand Down

0 comments on commit 3f087df

Please sign in to comment.