diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 73568598..784ae0f6 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -228,7 +228,7 @@ export default { } }, - generateMpi: function(algo, bits, curve) { + generateMpi: function(algo, bits, curve, material) { switch (algo) { case 'rsa_encrypt': case 'rsa_encrypt_sign': @@ -247,7 +247,7 @@ export default { }); case 'ecdsa': - return publicKey.elliptic.generate(curve).then(function (key) { + return publicKey.elliptic.generate(curve, material).then(function (key) { return [ new type_oid(key.oid), BigInteger2mpi(key.R), @@ -256,7 +256,7 @@ export default { }); case 'ecdh': - return publicKey.elliptic.generate(curve).then(function (key) { + return publicKey.elliptic.generate(curve, material).then(function (key) { return [ new type_oid(key.oid), BigInteger2mpi(key.R), diff --git a/src/crypto/public_key/elliptic/curves.js b/src/crypto/public_key/elliptic/curves.js index c6b33477..faabd656 100644 --- a/src/crypto/public_key/elliptic/curves.js +++ b/src/crypto/public_key/elliptic/curves.js @@ -97,10 +97,15 @@ function get(oid_or_name) { throw new Error('Not valid curve'); } -function generate(curve) { +function generate(curve, material) { return new Promise(function (resolve) { curve = get(curve); - var keyPair = curve.genKeyPair(); + var keyPair; + if (typeof(material) !== "undefined") { + keyPair = curve.keyFromPrivate(material); + } else { + keyPair = curve.genKeyPair(); + } resolve({ oid: curve.oid, R: new BigInteger(keyPair.getPublic()), diff --git a/src/key.js b/src/key.js index 1a6ae9b9..241326de 100644 --- a/src/key.js +++ b/src/key.js @@ -1139,7 +1139,11 @@ export function generate(options) { function generateSecretKey() { secretKeyPacket = new packet.SecretKey(); secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType); - return secretKeyPacket.generate(options.numBits, options.curve); + var material; + if (typeof(options.material) !== "undefined") { + material = options.material.key; + } + return secretKeyPacket.generate(options.numBits, options.curve, material); } function generateSecretSubkey() { @@ -1148,8 +1152,12 @@ export function generate(options) { if (subkeyType === enums.publicKey.ecdsa) { subkeyType = enums.publicKey.ecdh; } + var material; + if (typeof(options.material) !== "undefined") { + material = options.material.subkey; + } secretSubkeyPacket.algorithm = enums.read(enums.publicKey, subkeyType); - return secretSubkeyPacket.generate(options.numBits, options.curve); + return secretSubkeyPacket.generate(options.numBits, options.curve, material); } } diff --git a/src/openpgp.js b/src/openpgp.js index 88074dfd..acb8e737 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -98,8 +98,8 @@ export function destroyWorker() { * @static */ -export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=false, curve=null } = {}) { - const options = formatUserIds({ userIds, passphrase, numBits, unlocked, curve }); +export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=false, curve=null, material=null } = {}) { + const options = formatUserIds({ userIds, passphrase, numBits, unlocked, curve, material }); if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported return asyncProxy.delegate('generateKey', options); @@ -459,6 +459,9 @@ function formatUserIds(options) { if (!options.curve) { delete options.curve; } + if (!options.material) { + delete options.material; + } if (!options.userIds) { return options; } diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 8e525e41..ea1bd246 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -273,10 +273,10 @@ SecretKey.prototype.decrypt = function (passphrase) { return true; }; -SecretKey.prototype.generate = function (bits, curve) { +SecretKey.prototype.generate = function (bits, curve, material) { var self = this; - return crypto.generateMpi(self.algorithm, bits, curve).then(function(mpi) { + return crypto.generateMpi(self.algorithm, bits, curve, material).then(function(mpi) { self.mpi = mpi; self.isDecrypted = true; });