Generation of keys for elliptic curves
This commit is contained in:
parent
075d7f8e0e
commit
a5d9e6d09e
|
@ -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.');
|
||||||
}
|
}
|
||||||
|
|
16
src/key.js
16
src/key.js
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user