Generation of keys for elliptic curves

This commit is contained in:
Ismael Bejarano 2016-08-12 00:25:47 -03:00 committed by Sanjana Rajan
parent 075d7f8e0e
commit a5d9e6d09e
5 changed files with 60 additions and 9 deletions

View File

@ -22,7 +22,9 @@
* @requires crypto/public_key * @requires crypto/public_key
* @requires crypto/random * @requires crypto/random
* @requires type/ecdh_symkey * @requires type/ecdh_symkey
* @requires type/kdf_params
* @requires type/mpi * @requires type/mpi
* @requires type/oid
* @module crypto/crypto * @module crypto/crypto
*/ */
@ -32,7 +34,9 @@ import random from './random.js';
import cipher from './cipher'; import cipher from './cipher';
import publicKey from './public_key'; import publicKey from './public_key';
import type_ecdh_symkey from '../type/ecdh_symkey.js'; import type_ecdh_symkey from '../type/ecdh_symkey.js';
import type_kdf_params from '../type/kdf_params.js';
import type_mpi from '../type/mpi.js'; import type_mpi from '../type/mpi.js';
import type_oid from '../type/oid.js';
function BigInteger2mpi(bn) { function BigInteger2mpi(bn) {
var mpi = new type_mpi(); var mpi = new type_mpi();
@ -224,7 +228,7 @@ export default {
} }
}, },
generateMpi: function(algo, bits) { generateMpi: function(algo, bits, curve) {
switch (algo) { switch (algo) {
case 'rsa_encrypt': case 'rsa_encrypt':
case 'rsa_encrypt_sign': case 'rsa_encrypt_sign':
@ -241,6 +245,26 @@ export default {
output.push(keyObject.u); output.push(keyObject.u);
return mapResult(output); return mapResult(output);
}); });
case 'ecdsa':
return publicKey.elliptic.generate(curve).then(function (key) {
return [
new type_oid(key.oid),
BigInteger2mpi(key.R),
BigInteger2mpi(key.r)
];
});
case 'ecdh':
return publicKey.elliptic.generate(curve).then(function (key) {
return [
new type_oid(key.oid),
BigInteger2mpi(key.R),
new type_kdf_params(key.hash, key.cipher),
BigInteger2mpi(key.r)
];
});
default: default:
throw new Error('Unsupported algorithm for key generation.'); throw new Error('Unsupported algorithm for key generation.');
} }

View File

@ -1115,8 +1115,12 @@ export function readArmored(armoredText) {
export function generate(options) { export function generate(options) {
var secretKeyPacket, secretSubkeyPacket; var secretKeyPacket, secretSubkeyPacket;
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
if (options.curve) {
options.keyType = enums.publicKey.ecdsa;
}
options.keyType = options.keyType || enums.publicKey.rsa_encrypt_sign; options.keyType = options.keyType || enums.publicKey.rsa_encrypt_sign;
if (options.keyType !== enums.publicKey.rsa_encrypt_sign) { // RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated if (options.keyType !== enums.publicKey.rsa_encrypt_sign &&
options.keyType !== enums.publicKey.ecdsa) { // RSA Encrypt-Only and RSA Sign-Only are deprecated and SHOULD NOT be generated
throw new Error('Only RSA Encrypt or Sign supported'); throw new Error('Only RSA Encrypt or Sign supported');
} }
@ -1135,13 +1139,17 @@ export function generate(options) {
function generateSecretKey() { function generateSecretKey() {
secretKeyPacket = new packet.SecretKey(); secretKeyPacket = new packet.SecretKey();
secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType); secretKeyPacket.algorithm = enums.read(enums.publicKey, options.keyType);
return secretKeyPacket.generate(options.numBits); return secretKeyPacket.generate(options.numBits, options.curve);
} }
function generateSecretSubkey() { function generateSecretSubkey() {
secretSubkeyPacket = new packet.SecretSubkey(); secretSubkeyPacket = new packet.SecretSubkey();
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, options.keyType); var subkeyType = options.keyType;
return secretSubkeyPacket.generate(options.numBits); if (subkeyType === enums.publicKey.ecdsa) {
subkeyType = enums.publicKey.ecdh;
}
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, subkeyType);
return secretSubkeyPacket.generate(options.numBits, options.curve);
} }
} }

View File

@ -97,8 +97,9 @@ export function destroyWorker() {
* { key:Key, privateKeyArmored:String, publicKeyArmored:String } * { key:Key, privateKeyArmored:String, publicKeyArmored:String }
* @static * @static
*/ */
export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=false, keyExpirationTime=0 } = {}) {
const options = formatUserIds({ userIds, passphrase, numBits, unlocked, keyExpirationTime }); export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=false, curve=null } = {}) {
const options = formatUserIds({ userIds, passphrase, numBits, unlocked, curve });
if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported
return asyncProxy.delegate('generateKey', options); return asyncProxy.delegate('generateKey', options);
@ -455,6 +456,9 @@ function checkCleartextOrMessage(message) {
* Format user ids for internal use. * Format user ids for internal use.
*/ */
function formatUserIds(options) { function formatUserIds(options) {
if (!options.curve) {
delete options.curve;
}
if (!options.userIds) { if (!options.userIds) {
return options; return options;
} }

View File

@ -273,10 +273,10 @@ SecretKey.prototype.decrypt = function (passphrase) {
return true; return true;
}; };
SecretKey.prototype.generate = function (bits) { SecretKey.prototype.generate = function (bits, curve) {
var self = this; var self = this;
return crypto.generateMpi(self.algorithm, bits).then(function(mpi) { return crypto.generateMpi(self.algorithm, bits, curve).then(function(mpi) {
self.mpi = mpi; self.mpi = mpi;
self.isDecrypted = true; self.isDecrypted = true;
}); });

View File

@ -211,4 +211,19 @@ describe('Elliptic Curve Cryptography', function () {
}); });
}); });
}); });
it('Generate key', function (done) {
var options = {
userIds: {name: "Hamlet (secp256k1)", email: "hamlet@example.net"},
curve: "secp256k1",
passphrase: "ophelia"
};
openpgp.generateKey(options).then(function (key) {
expect(key).to.exist;
expect(key.key).to.exist;
expect(key.key.primaryKey).to.exist;
expect(key.privateKeyArmored).to.exist;
expect(key.publicKeyArmored).to.exist;
done();
});
});
}); });