tests
This commit is contained in:
parent
24119f4fb1
commit
e4bd27ce2f
26
src/key.js
26
src/key.js
|
@ -1101,7 +1101,7 @@ export function readArmored(armoredText) {
|
||||||
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
|
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
|
||||||
* @param {Number} [options.keyExpirationTime=0]
|
* @param {Number} [options.keyExpirationTime=0]
|
||||||
* The number of seconds after the key creation time that the key expires
|
* The number of seconds after the key creation time that the key expires
|
||||||
* @param {String} curve (optional) elliptic curve for ECC keys:
|
* @param {String} curve (optional) elliptic curve for ECC keys
|
||||||
* @param {Date} date Override the creation date of the key and the key signatures
|
* @param {Date} date Override the creation date of the key and the key signatures
|
||||||
* @param {Array<Object>} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
* @param {Array<Object>} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
||||||
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
||||||
|
@ -1110,13 +1110,13 @@ export function readArmored(armoredText) {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export async function generate(options) {
|
export async function generate(options) {
|
||||||
|
options.sign = true; // primary key is always a signing key
|
||||||
options = sanitizeKeyOptions(options);
|
options = sanitizeKeyOptions(options);
|
||||||
options.subkeys = options.subkeys.map(function(subkey, index) { return sanitizeKeyOptions(options.subkeys[index], options); });
|
options.subkeys = options.subkeys.map(function(subkey, index) { return sanitizeKeyOptions(options.subkeys[index], options); });
|
||||||
|
|
||||||
let promises = [generateSecretKey(options)];
|
let promises = [generateSecretKey(options)];
|
||||||
promises = promises.concat(options.subkeys.map(generateSecretSubkey));
|
promises = promises.concat(options.subkeys.map(generateSecretSubkey));
|
||||||
return Promise.all(promises).then(packets => wrapKeyObject(packets, options));
|
return Promise.all(promises).then(packets => wrapKeyObject(packets[0], packets.slice(1), options));
|
||||||
|
|
||||||
function sanitizeKeyOptions(options, subkeyDefaults={}) {
|
function sanitizeKeyOptions(options, subkeyDefaults={}) {
|
||||||
options.curve = options.curve || subkeyDefaults.curve;
|
options.curve = options.curve || subkeyDefaults.curve;
|
||||||
|
@ -1134,17 +1134,18 @@ export async function generate(options) {
|
||||||
throw new Error('Not valid curve.');
|
throw new Error('Not valid curve.');
|
||||||
}
|
}
|
||||||
if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) {
|
if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) {
|
||||||
if (!subkeyDefaults.algorithm || options.sign) {
|
if (options.sign) {
|
||||||
options.algorithm = options.algorithm || enums.publicKey.eddsa;
|
options.algorithm = enums.publicKey.eddsa;
|
||||||
options.curve = enums.curve.ed25519;
|
options.curve = enums.curve.ed25519;
|
||||||
} else {
|
} else {
|
||||||
options.algorithm = options.algorithm || enums.publicKey.ecdh;
|
options.algorithm = enums.publicKey.ecdh;
|
||||||
options.curve = enums.curve.curve25519;
|
options.curve = enums.curve.curve25519;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
options.algorithm = options.algorithm || (!subkeyDefaults.algorithm ? enums.publicKey.ecdsa : enums.publicKey.ecdh);
|
if (options.sign) {
|
||||||
if (options.algorithm !== enums.publicKey.ecdh && options.algorithm !== enums.publicKey.ecdsa) {
|
options.algorithm = enums.publicKey.ecdsa;
|
||||||
throw new Error('Invalid algorithm for curve');
|
} else {
|
||||||
|
options.algorithm = enums.publicKey.ecdh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (options.numBits) {
|
} else if (options.numBits) {
|
||||||
|
@ -1225,7 +1226,7 @@ export async function reformat(options) {
|
||||||
|
|
||||||
options.subkeys = options.subkeys.map(function(subkey, index) { return sanitizeKeyOptions(options.subkeys[index], options); });
|
options.subkeys = options.subkeys.map(function(subkey, index) { return sanitizeKeyOptions(options.subkeys[index], options); });
|
||||||
|
|
||||||
return wrapKeyObject([secretKeyPacket].concat(secretSubkeyPackets), options);
|
return wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options);
|
||||||
|
|
||||||
function sanitizeKeyOptions(options, subkeyDefaults={}) {
|
function sanitizeKeyOptions(options, subkeyDefaults={}) {
|
||||||
options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime;
|
options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime;
|
||||||
|
@ -1236,9 +1237,7 @@ export async function reformat(options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function wrapKeyObject(packets, options) {
|
async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
const secretKeyPacket = packets[0];
|
|
||||||
const secretSubkeyPackets = packets.slice(1);
|
|
||||||
// set passphrase protection
|
// set passphrase protection
|
||||||
if (options.passphrase) {
|
if (options.passphrase) {
|
||||||
await secretKeyPacket.encrypt(options.passphrase);
|
await secretKeyPacket.encrypt(options.passphrase);
|
||||||
|
@ -1293,7 +1292,6 @@ async function wrapKeyObject(packets, options) {
|
||||||
signaturePacket.keyExpirationTime = options.keyExpirationTime;
|
signaturePacket.keyExpirationTime = options.keyExpirationTime;
|
||||||
signaturePacket.keyNeverExpires = false;
|
signaturePacket.keyNeverExpires = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await signaturePacket.sign(secretKeyPacket, dataToSign);
|
await signaturePacket.sign(secretKeyPacket, dataToSign);
|
||||||
|
|
||||||
return { userIdPacket, signaturePacket };
|
return { userIdPacket, signaturePacket };
|
||||||
|
|
|
@ -1081,7 +1081,6 @@ describe('Key', function() {
|
||||||
const opt = {
|
const opt = {
|
||||||
userIds: { name: 'Test User', email: 'text@example.com' },
|
userIds: { name: 'Test User', email: 'text@example.com' },
|
||||||
passphrase: 'secret',
|
passphrase: 'secret',
|
||||||
unlocked: true,
|
|
||||||
date: past
|
date: past
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1108,6 +1107,47 @@ describe('Key', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Generate key - two subkeys with default values', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]};
|
||||||
|
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.lengthOf(2);
|
||||||
|
expect(key.subKeys[0].subKey.algorithm).to.equal('ecdh');
|
||||||
|
expect(key.subKeys[1].subKey.algorithm).to.equal('ecdh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - one signing subkey', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]};
|
||||||
|
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.lengthOf(2);
|
||||||
|
expect(key.subKeys[0].subKey.algorithm).to.equal('ecdh');
|
||||||
|
expect(key.subKeys[1].subKey.algorithm).to.equal('eddsa');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate key - override main key options for subkey', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = {numBits: 2048, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]};
|
||||||
|
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.primaryKey.algorithm).to.equal('rsa_encrypt_sign');
|
||||||
|
expect(key.subKeys[0].subKey.algorithm).to.equal('ecdh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Encrypt key with new passphrase', async function() {
|
it('Encrypt key with new passphrase', async function() {
|
||||||
const userId = 'test <a@b.com>';
|
const userId = 'test <a@b.com>';
|
||||||
const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'};
|
const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'};
|
||||||
|
@ -1261,6 +1301,28 @@ describe('Key', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Reformat key with two subkeys with passphrase', function() {
|
||||||
|
const userId1 = 'test <a@b.com>';
|
||||||
|
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};
|
||||||
|
return openpgp.generateKey(opt1).then(function(newKey) {
|
||||||
|
newKey = newKey.key;
|
||||||
|
expect(newKey.users[0].userId.userid).to.equal(userId1);
|
||||||
|
expect(+newKey.primaryKey.created).to.equal(+now);
|
||||||
|
expect(+newKey.subKeys[0].subKey.created).to.equal(+now);
|
||||||
|
expect(+newKey.subKeys[0].bindingSignatures[0].created).to.equal(+now);
|
||||||
|
const opt2 = {privateKey: newKey, userIds: [userId2], date: before};
|
||||||
|
return openpgp.reformatKey(opt2).then(function(refKey) {
|
||||||
|
refKey = refKey.key;
|
||||||
|
expect(refKey.users.length).to.equal(1);
|
||||||
|
expect(refKey.users[0].userId.userid).to.equal(userId2);
|
||||||
|
expect(+refKey.subKeys[0].bindingSignatures[0].created).to.equal(+before);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Reformat key with no subkey without passphrase', function() {
|
it('Reformat key with no subkey without passphrase', function() {
|
||||||
const userId = 'test1 <a@b.com>';
|
const userId = 'test1 <a@b.com>';
|
||||||
const keys = openpgp.key.readArmored(key_without_subkey).keys;
|
const keys = openpgp.key.readArmored(key_without_subkey).keys;
|
||||||
|
|
|
@ -483,22 +483,22 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have default params set', function() {
|
it('should have default params set', function() {
|
||||||
const now = new Date();
|
const now = openpgp.util.normalizeDate(new Date());
|
||||||
const opt = {
|
const opt = {
|
||||||
userIds: { name: 'Test User', email: 'text@example.com' },
|
userIds: { name: 'Test User', email: 'text@example.com' },
|
||||||
passphrase: 'secret',
|
passphrase: 'secret',
|
||||||
unlocked: true,
|
date: now,
|
||||||
date: now
|
subkeys: []
|
||||||
};
|
};
|
||||||
return openpgp.generateKey(opt).then(function(newKey) {
|
return openpgp.generateKey(opt).then(function(newKey) {
|
||||||
expect(keyGenStub.withArgs({
|
expect(keyGenStub.withArgs({
|
||||||
userIds: ['Test User <text@example.com>'],
|
userIds: ['Test User <text@example.com>'],
|
||||||
passphrase: 'secret',
|
passphrase: 'secret',
|
||||||
numBits: 2048,
|
numBits: 2048,
|
||||||
unlocked: true,
|
|
||||||
keyExpirationTime: 0,
|
keyExpirationTime: 0,
|
||||||
curve: "",
|
curve: "",
|
||||||
date: now
|
date: now,
|
||||||
|
subkeys: [],
|
||||||
}).calledOnce).to.be.true;
|
}).calledOnce).to.be.true;
|
||||||
expect(newKey.key).to.exist;
|
expect(newKey.key).to.exist;
|
||||||
expect(newKey.privateKeyArmored).to.exist;
|
expect(newKey.privateKeyArmored).to.exist;
|
||||||
|
@ -506,23 +506,6 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for no params', function() {
|
|
||||||
const now = new Date();
|
|
||||||
|
|
||||||
return openpgp.generateKey({date: now}).then(function(newKey) {
|
|
||||||
expect(keyGenStub.withArgs({
|
|
||||||
userIds: [],
|
|
||||||
passphrase: undefined,
|
|
||||||
numBits: 2048,
|
|
||||||
unlocked: false,
|
|
||||||
keyExpirationTime: 0,
|
|
||||||
curve: "",
|
|
||||||
date: now
|
|
||||||
}).calledOnce).to.be.true;
|
|
||||||
expect(newKey.key).to.exist;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delegate to async proxy', function() {
|
it('should delegate to async proxy', function() {
|
||||||
const workerStub = {
|
const workerStub = {
|
||||||
postMessage: function() {}
|
postMessage: function() {}
|
||||||
|
@ -533,7 +516,12 @@ describe('OpenPGP.js public api tests', function() {
|
||||||
const proxyGenStub = stub(openpgp.getWorker(), 'delegate');
|
const proxyGenStub = stub(openpgp.getWorker(), 'delegate');
|
||||||
getWebCryptoAllStub.returns();
|
getWebCryptoAllStub.returns();
|
||||||
|
|
||||||
openpgp.generateKey();
|
const opt = {
|
||||||
|
userIds: { name: 'Test User', email: 'text@example.com' },
|
||||||
|
passphrase: 'secret',
|
||||||
|
subkeys: []
|
||||||
|
};
|
||||||
|
openpgp.generateKey(opt);
|
||||||
expect(proxyGenStub.calledOnce).to.be.true;
|
expect(proxyGenStub.calledOnce).to.be.true;
|
||||||
expect(keyGenStub.calledOnce).to.be.false;
|
expect(keyGenStub.calledOnce).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user