Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v5] Generate ECC keys by default #1065

Merged
merged 3 commits into from Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -1825,8 +1825,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 @@ -1867,8 +1866,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 @@ -1887,8 +1885,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 @@ -1902,8 +1899,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 @@ -1916,8 +1912,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 @@ -1930,8 +1925,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 @@ -1944,8 +1938,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 @@ -1959,12 +1952,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 @@ -1977,12 +1968,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 @@ -1995,8 +1984,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 @@ -2009,7 +1997,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 @@ -2021,9 +2009,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 @@ -2039,7 +2043,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 @@ -2056,26 +2060,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 @@ -2095,8 +2098,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 @@ -2195,8 +2197,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 @@ -2230,7 +2231,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 @@ -2273,8 +2274,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 @@ -2294,8 +2294,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 @@ -2313,8 +2312,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 @@ -2325,8 +2323,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 @@ -2338,8 +2335,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 @@ -3067,7 +3063,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 @@ -1246,9 +1242,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 @@ -1280,7 +1274,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