Generate key by default without unlocking secret part. Use options parameter for generate method.
This commit is contained in:
parent
fd25743082
commit
bb0ac83cb7
40
src/key.js
40
src/key.js
|
@ -928,36 +928,41 @@ function readArmored(armoredText) {
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key. Currently only supports RSA keys.
|
* Generates a new OpenPGP key. Currently only supports RSA keys.
|
||||||
* Primary and subkey will be of same type.
|
* Primary and subkey will be of same type.
|
||||||
* @param {module:enums.publicKey} keyType to indicate what type of key to make.
|
* @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}
|
* RSA is 1. See {@link http://tools.ietf.org/html/rfc4880#section-9.1}
|
||||||
* @param {Integer} numBits number of bits for the key creation.
|
* @param {Integer} options.numBits number of bits for the key creation.
|
||||||
* @param {String} userId assumes already in form of "User Name <username@email.com>"
|
* @param {String} options.userId assumes already in form of "User Name <username@email.com>"
|
||||||
* @param {String} passphrase The passphrase used to encrypt the resulting private key
|
* @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}
|
* @return {module:key~Key}
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function generate(keyType, numBits, userId, passphrase) {
|
function generate(options) {
|
||||||
|
options.keyType = options.keyType || enums.publicKey.rsa_encrypt_sign;
|
||||||
// RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated
|
// RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated
|
||||||
if (keyType !== enums.publicKey.rsa_encrypt_sign) {
|
if (options.keyType !== enums.publicKey.rsa_encrypt_sign) {
|
||||||
throw new Error('Only RSA Encrypt or Sign supported');
|
throw new Error('Only RSA Encrypt or Sign supported');
|
||||||
}
|
}
|
||||||
|
if (!options.passphrase) {
|
||||||
|
throw new Error('Parameter options.passphrase required');
|
||||||
|
}
|
||||||
|
|
||||||
var packetlist = new packet.List();
|
var packetlist = new packet.List();
|
||||||
|
|
||||||
var secretKeyPacket = new packet.SecretKey();
|
var secretKeyPacket = new packet.SecretKey();
|
||||||
secretKeyPacket.algorithm = enums.read(enums.publicKey, keyType);
|
secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
|
||||||
secretKeyPacket.generate(numBits);
|
secretKeyPacket.generate(options.numBits);
|
||||||
secretKeyPacket.encrypt(passphrase);
|
secretKeyPacket.encrypt(options.passphrase);
|
||||||
|
|
||||||
var userIdPacket = new packet.Userid();
|
var userIdPacket = new packet.Userid();
|
||||||
userIdPacket.read(userId);
|
userIdPacket.read(options.userId);
|
||||||
|
|
||||||
var dataToSign = {};
|
var dataToSign = {};
|
||||||
dataToSign.userid = userIdPacket;
|
dataToSign.userid = userIdPacket;
|
||||||
dataToSign.key = secretKeyPacket;
|
dataToSign.key = secretKeyPacket;
|
||||||
var signaturePacket = new packet.Signature();
|
var signaturePacket = new packet.Signature();
|
||||||
signaturePacket.signatureType = enums.signature.cert_generic;
|
signaturePacket.signatureType = enums.signature.cert_generic;
|
||||||
signaturePacket.publicKeyAlgorithm = keyType;
|
signaturePacket.publicKeyAlgorithm = options.keyType;
|
||||||
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
||||||
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
|
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
|
||||||
signaturePacket.preferredSymmetricAlgorithms = [];
|
signaturePacket.preferredSymmetricAlgorithms = [];
|
||||||
|
@ -980,16 +985,16 @@ function generate(keyType, numBits, userId, passphrase) {
|
||||||
signaturePacket.sign(secretKeyPacket, dataToSign);
|
signaturePacket.sign(secretKeyPacket, dataToSign);
|
||||||
|
|
||||||
var secretSubkeyPacket = new packet.SecretSubkey();
|
var secretSubkeyPacket = new packet.SecretSubkey();
|
||||||
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, keyType);
|
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
|
||||||
secretSubkeyPacket.generate(numBits);
|
secretSubkeyPacket.generate(options.numBits);
|
||||||
secretSubkeyPacket.encrypt(passphrase);
|
secretSubkeyPacket.encrypt(options.passphrase);
|
||||||
|
|
||||||
dataToSign = {};
|
dataToSign = {};
|
||||||
dataToSign.key = secretKeyPacket;
|
dataToSign.key = secretKeyPacket;
|
||||||
dataToSign.bind = secretSubkeyPacket;
|
dataToSign.bind = secretSubkeyPacket;
|
||||||
var subkeySignaturePacket = new packet.Signature();
|
var subkeySignaturePacket = new packet.Signature();
|
||||||
subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
|
subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
|
||||||
subkeySignaturePacket.publicKeyAlgorithm = keyType;
|
subkeySignaturePacket.publicKeyAlgorithm = options.keyType;
|
||||||
subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
subkeySignaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
||||||
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
|
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
|
||||||
subkeySignaturePacket.sign(secretKeyPacket, dataToSign);
|
subkeySignaturePacket.sign(secretKeyPacket, dataToSign);
|
||||||
|
@ -1000,6 +1005,11 @@ function generate(keyType, numBits, userId, passphrase) {
|
||||||
packetlist.push(secretSubkeyPacket);
|
packetlist.push(secretSubkeyPacket);
|
||||||
packetlist.push(subkeySignaturePacket);
|
packetlist.push(subkeySignaturePacket);
|
||||||
|
|
||||||
|
if (!options.unlocked) {
|
||||||
|
secretKeyPacket.clearPrivateMPIs();
|
||||||
|
secretSubkeyPacket.clearPrivateMPIs();
|
||||||
|
}
|
||||||
|
|
||||||
return new Key(packetlist);
|
return new Key(packetlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,24 +198,25 @@ function verifyClearSignedMessage(publicKeys, msg, callback) {
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key pair. Currently only supports RSA keys.
|
* Generates a new OpenPGP key pair. Currently only supports RSA keys.
|
||||||
* Primary and subkey will be of same type.
|
* Primary and subkey will be of same type.
|
||||||
* @param {module:enums.publicKey} keyType to indicate what type of key to make.
|
* @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}
|
* RSA is 1. See {@link http://tools.ietf.org/html/rfc4880#section-9.1}
|
||||||
* @param {Integer} numBits number of bits for the key creation. (should be 1024+, generally)
|
* @param {Integer} options.numBits number of bits for the key creation. (should be 1024+, generally)
|
||||||
* @param {String} userId assumes already in form of "User Name <username@email.com>"
|
* @param {String} options.userId assumes already in form of "User Name <username@email.com>"
|
||||||
* @param {String} passphrase The passphrase used to encrypt the resulting private key
|
* @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
|
||||||
* @param {function} callback (optional) callback(error, result) for async style
|
* @param {function} callback (optional) callback(error, result) for async style
|
||||||
* @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String}
|
* @return {Object} {key: module:key~Key, privateKeyArmored: String, publicKeyArmored: String}
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
function generateKeyPair(keyType, numBits, userId, passphrase, callback) {
|
function generateKeyPair(options, callback) {
|
||||||
if (useWorker(callback)) {
|
if (useWorker(callback)) {
|
||||||
asyncProxy.generateKeyPair(keyType, numBits, userId, passphrase, callback);
|
asyncProxy.generateKeyPair(options, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return execute(function() {
|
return execute(function() {
|
||||||
var result = {};
|
var result = {};
|
||||||
var newKey = key.generate(keyType, numBits, userId, passphrase);
|
var newKey = key.generate(options);
|
||||||
result.key = newKey;
|
result.key = newKey;
|
||||||
result.privateKeyArmored = newKey.armor();
|
result.privateKeyArmored = newKey.armor();
|
||||||
result.publicKeyArmored = newKey.toPublic().armor();
|
result.publicKeyArmored = newKey.toPublic().armor();
|
||||||
|
|
|
@ -182,7 +182,6 @@ SecretKey.prototype.encrypt = function (passphrase) {
|
||||||
blockLen = crypto.cipher[symmetric].blockSize,
|
blockLen = crypto.cipher[symmetric].blockSize,
|
||||||
iv = crypto.random.getRandomBytes(blockLen);
|
iv = crypto.random.getRandomBytes(blockLen);
|
||||||
|
|
||||||
|
|
||||||
this.encrypted = '';
|
this.encrypted = '';
|
||||||
this.encrypted += String.fromCharCode(254);
|
this.encrypted += String.fromCharCode(254);
|
||||||
this.encrypted += String.fromCharCode(enums.write(enums.symmetric, symmetric));
|
this.encrypted += String.fromCharCode(enums.write(enums.symmetric, symmetric));
|
||||||
|
@ -255,8 +254,9 @@ SecretKey.prototype.decrypt = function (passphrase) {
|
||||||
'mod';
|
'mod';
|
||||||
|
|
||||||
var parsedMPI = parse_cleartext_mpi(hash, cleartext, this.algorithm);
|
var parsedMPI = parse_cleartext_mpi(hash, cleartext, this.algorithm);
|
||||||
if (parsedMPI instanceof Error)
|
if (parsedMPI instanceof Error) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
this.mpi = this.mpi.concat(parsedMPI);
|
this.mpi = this.mpi.concat(parsedMPI);
|
||||||
this.isDecrypted = true;
|
this.isDecrypted = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -266,3 +266,11 @@ SecretKey.prototype.generate = function (bits) {
|
||||||
this.mpi = crypto.generateMpi(this.algorithm, bits);
|
this.mpi = crypto.generateMpi(this.algorithm, bits);
|
||||||
this.isDecrypted = true;
|
this.isDecrypted = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear private MPIs, return to initial state
|
||||||
|
*/
|
||||||
|
SecretKey.prototype.clearPrivateMPIs = function () {
|
||||||
|
this.mpi = this.mpi.slice(0, crypto.getPublicMpiCount(this.algorithm));
|
||||||
|
this.isDecrypted = false;
|
||||||
|
};
|
||||||
|
|
|
@ -234,13 +234,10 @@ AsyncProxy.prototype.verifyClearSignedMessage = function(publicKeys, message, ca
|
||||||
* @param {String} passphrase The passphrase used to encrypt the resulting private key
|
* @param {String} passphrase The passphrase used to encrypt the resulting private key
|
||||||
* @param {Function} callback receives object with key and public and private armored texts
|
* @param {Function} callback receives object with key and public and private armored texts
|
||||||
*/
|
*/
|
||||||
AsyncProxy.prototype.generateKeyPair = function(keyType, numBits, userId, passphrase, callback) {
|
AsyncProxy.prototype.generateKeyPair = function(options, callback) {
|
||||||
this.worker.postMessage({
|
this.worker.postMessage({
|
||||||
event: 'generate-key-pair',
|
event: 'generate-key-pair',
|
||||||
keyType: keyType,
|
options: options
|
||||||
numBits: numBits,
|
|
||||||
userId: userId,
|
|
||||||
passphrase: passphrase
|
|
||||||
});
|
});
|
||||||
this.tasks.push(function(err, data) {
|
this.tasks.push(function(err, data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
|
@ -98,7 +98,7 @@ onmessage = function (event) {
|
||||||
break;
|
break;
|
||||||
case 'generate-key-pair':
|
case 'generate-key-pair':
|
||||||
try {
|
try {
|
||||||
data = window.openpgp.generateKeyPair(msg.keyType, msg.numBits, msg.userId, msg.passphrase);
|
data = window.openpgp.generateKeyPair(msg.options);
|
||||||
data.key = data.key.toPacketlist();
|
data.key = data.key.toPacketlist();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = e.message;
|
err = e.message;
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe('Basic', function() {
|
||||||
|
|
||||||
describe("Key generation/encryption/decryption", function() {
|
describe("Key generation/encryption/decryption", function() {
|
||||||
var testHelper = function(passphrase, userid, message) {
|
var testHelper = function(passphrase, userid, message) {
|
||||||
var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 512, userid, passphrase);
|
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase});
|
||||||
expect(key).to.exist;
|
expect(key).to.exist;
|
||||||
expect(key.key).to.exist;
|
expect(key.key).to.exist;
|
||||||
expect(key.privateKeyArmored).to.exist;
|
expect(key.privateKeyArmored).to.exist;
|
||||||
|
@ -72,7 +72,7 @@ describe('Basic', function() {
|
||||||
var userid = 'Test McTestington <test@example.com>';
|
var userid = 'Test McTestington <test@example.com>';
|
||||||
var passphrase = 'password';
|
var passphrase = 'password';
|
||||||
|
|
||||||
var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 512, userid, passphrase);
|
var key = openpgp.generateKeyPair({numBits: 512, userId: userid, passphrase: passphrase});
|
||||||
|
|
||||||
var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message;
|
var info = '\npassphrase: ' + passphrase + '\n' + 'userid: ' + userid + '\n' + 'message: ' + message;
|
||||||
|
|
||||||
|
|
|
@ -634,7 +634,7 @@ var pgp_desktop_priv =
|
||||||
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
|
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
|
||||||
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.integrity_protect ? [1] : null); // modification detection
|
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.integrity_protect ? [1] : null); // modification detection
|
||||||
}
|
}
|
||||||
var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 512, 'test', 'hello');
|
var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: 'hello'});
|
||||||
testPref(key.key);
|
testPref(key.key);
|
||||||
testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]);
|
testPref(openpgp.key.readArmored(key.publicKeyArmored).keys[0]);
|
||||||
});
|
});
|
||||||
|
@ -653,5 +653,12 @@ var pgp_desktop_priv =
|
||||||
expect(primUser.selfCertificate).to.be.an.instanceof(openpgp.packet.Signature);
|
expect(primUser.selfCertificate).to.be.an.instanceof(openpgp.packet.Signature);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Generated key is not unlocked by default', function() {
|
||||||
|
var key = openpgp.generateKeyPair({numBits: 512, userId: 'test', passphrase: '123'});
|
||||||
|
var msg = openpgp.message.fromText('hello').encrypt([key.key]);
|
||||||
|
msg = msg.decrypt.bind(msg, key.key);
|
||||||
|
expect(msg).to.throw('Private key is not decrypted.');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -398,7 +398,7 @@ describe('High level API', function() {
|
||||||
describe('Key generation', function() {
|
describe('Key generation', function() {
|
||||||
|
|
||||||
it('Generate 1024-bit RSA/RSA key async', function (done) {
|
it('Generate 1024-bit RSA/RSA key async', function (done) {
|
||||||
openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington <test@example.com>', 'hello world', function(err, data) {
|
openpgp.generateKeyPair({numBits: 1024, userId: 'Test McTestington <test@example.com>', passphrase: 'hello world'}, function(err, data) {
|
||||||
expect(err).to.not.exist;
|
expect(err).to.not.exist;
|
||||||
expect(data).to.exist;
|
expect(data).to.exist;
|
||||||
expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
expect(data.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
||||||
|
@ -409,7 +409,7 @@ describe('High level API', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Generate 1024-bit RSA/RSA key sync', function () {
|
it('Generate 1024-bit RSA/RSA key sync', function () {
|
||||||
var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 1024, 'Test McTestington <test@example.com>', 'hello world');
|
var key = openpgp.generateKeyPair({numBits: 1024, userId: 'Test McTestington <test@example.com>', passphrase: 'hello world'});
|
||||||
expect(key).to.exist;
|
expect(key).to.exist;
|
||||||
expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
expect(key.publicKeyArmored).to.match(/^-----BEGIN PGP PUBLIC/);
|
||||||
expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);
|
expect(key.privateKeyArmored).to.match(/^-----BEGIN PGP PRIVATE/);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user