refactor mpi, generalize mpi to params to account for non-mpi algorithm-specific data

This commit is contained in:
Sanjana Rajan 2017-07-26 23:11:50 +02:00
parent 840c0229f8
commit cdc7004b96
9 changed files with 150 additions and 137 deletions

View File

@ -38,14 +38,26 @@ 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'; import type_oid from '../type/oid.js';
function BigInteger2mpi(bn) { function createType(data, type) {
var mpi = new type_mpi(); switch(type) {
mpi.fromBigInteger(bn); case 'mpi':
return mpi; return new type_mpi(data);
case 'oid':
return new type_oid(data);
case 'kdf':
return new type_kdf_params(data);
case 'ecdh_symkey':
return new type_ecdh_symkey(data);
default:
return null;
}
} }
function mapResult(result) { function mapResult(result, types) {
return result.map(BigInteger2mpi); for (var i=0; i < result.length; i++) {
result[i] = createType(result[i], types[i]);
}
return result;
} }
export default { export default {
@ -53,38 +65,39 @@ export default {
* Encrypts data using the specified public key multiprecision integers * Encrypts data using the specified public key multiprecision integers
* and the specified algorithm. * and the specified algorithm.
* @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
* @param {Array<module:type/mpi>} publicMPIs Algorithm dependent multiprecision integers * @param {Array<module:type/mpi>} publicParams Algorithm dependent multiprecision integers
* @param {module:type/mpi} data Data to be encrypted as MPI * @param {module:type/mpi} data Data to be encrypted as MPI
* @return {Array<module:type/mpi>} if RSA an module:type/mpi; * @return {Array<module:type/mpi>} if RSA an module:type/mpi;
* if elgamal encryption an array of two module:type/mpi is returned; otherwise null * if elgamal encryption an array of two module:type/mpi is returned; otherwise null
*/ */
publicKeyEncrypt: function(algo, publicMPIs, data, fingerprint) { publicKeyEncrypt: function(algo, publicParams, data, fingerprint) {
var types = this.getEncSessionKeyParamTypes(algo);
var result = (function() { var result = (function() {
var m; var m;
switch (algo) { switch (algo) {
case 'rsa_encrypt': case 'rsa_encrypt':
case 'rsa_encrypt_sign': case 'rsa_encrypt_sign':
var rsa = new publicKey.rsa(); var rsa = new publicKey.rsa();
var n = publicMPIs[0].toBigInteger(); var n = publicParams[0].toBigInteger();
var e = publicMPIs[1].toBigInteger(); var e = publicParams[1].toBigInteger();
m = data.toBigInteger(); m = data.toBigInteger();
return mapResult([rsa.encrypt(m, e, n)]); return mapResult([rsa.encrypt(m, e, n)], types);
case 'elgamal': case 'elgamal':
var elgamal = new publicKey.elgamal(); var elgamal = new publicKey.elgamal();
var p = publicMPIs[0].toBigInteger(); var p = publicParams[0].toBigInteger();
var g = publicMPIs[1].toBigInteger(); var g = publicParams[1].toBigInteger();
var y = publicMPIs[2].toBigInteger(); var y = publicParams[2].toBigInteger();
m = data.toBigInteger(); m = data.toBigInteger();
return mapResult(elgamal.encrypt(m, g, p, y)); return mapResult(elgamal.encrypt(m, g, p, y), types);
case 'ecdh': case 'ecdh':
var ecdh = publicKey.elliptic.ecdh; var ecdh = publicKey.elliptic.ecdh;
var curve = publicMPIs[0]; var curve = publicParams[0];
var kdf_params = publicMPIs[2]; var kdf_params = publicParams[2];
var R = publicMPIs[1].toBigInteger(); var R = publicParams[1].toBigInteger();
var res = ecdh.encrypt(curve.oid, kdf_params.cipher, kdf_params.hash, data, R, fingerprint); var res = ecdh.encrypt(curve.oid, kdf_params.cipher, kdf_params.hash, data, R, fingerprint);
return [BigInteger2mpi(res.V), new type_ecdh_symkey(res.C)]; return mapResult([res.V, res.C], types);
default: default:
return []; return [];
@ -98,7 +111,7 @@ export default {
* Decrypts data using the specified public key multiprecision integers of the private key, * Decrypts data using the specified public key multiprecision integers of the private key,
* the specified secretMPIs of the private key and the specified algorithm. * the specified secretMPIs of the private key and the specified algorithm.
* @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
* @param {Array<module:type/mpi>} publicMPIs Algorithm dependent multiprecision integers * @param {Array<module:type/mpi>} publicParams Algorithm dependent multiprecision integers
* of the public key part of the private key * of the public key part of the private key
* @param {Array<module:type/mpi>} secretMPIs Algorithm dependent multiprecision integers * @param {Array<module:type/mpi>} secretMPIs Algorithm dependent multiprecision integers
* of the private key used * of the private key used
@ -146,8 +159,7 @@ export default {
} }
})(); })();
var result = new type_mpi(); var result = new type_mpi(bn);
result.fromBigInteger(bn);
return result; return result;
}, },
@ -155,7 +167,7 @@ export default {
* @param {String} algo The public key algorithm * @param {String} algo The public key algorithm
* @return {Integer} The number of integers. * @return {Integer} The number of integers.
*/ */
getPrivateMpiCount: function(algo) { getPrivKeyParamTypes: function(algo) {
switch (algo) { switch (algo) {
case 'rsa_encrypt': case 'rsa_encrypt':
case 'rsa_encrypt_sign': case 'rsa_encrypt_sign':
@ -165,27 +177,30 @@ export default {
// - MPI of RSA secret prime value p. // - MPI of RSA secret prime value p.
// - MPI of RSA secret prime value q (p < q). // - MPI of RSA secret prime value q (p < q).
// - MPI of u, the multiplicative inverse of p, mod q. // - MPI of u, the multiplicative inverse of p, mod q.
return 4; return ['mpi', 'mpi', 'mpi', 'mpi'];
case 'elgamal': case 'elgamal':
// Algorithm-Specific Fields for Elgamal secret keys: // Algorithm-Specific Fields for Elgamal secret keys:
// - MPI of Elgamal secret exponent x. // - MPI of Elgamal secret exponent x.
return 1; return ['mpi'];
case 'dsa': case 'dsa':
// Algorithm-Specific Fields for DSA secret keys: // Algorithm-Specific Fields for DSA secret keys:
// - MPI of DSA secret exponent x. // - MPI of DSA secret exponent x.
return 1; return ['mpi'];
case 'ecdh': case 'ecdh':
case 'ecdsa': case 'ecdsa':
// Algorithm-Specific Fields for ECDSA or ECDH secret keys: // Algorithm-Specific Fields for ECDSA or ECDH secret keys:
// - MPI of an integer representing the secret key. // - MPI of an integer representing the secret key.
return 1; return ['mpi'];
default: default:
throw new Error('Unknown algorithm'); throw new Error('Unknown algorithm');
} }
}, },
getPublicMpiCount: function(algo) { getPrivKeyParamCount: function(algo) {
// - A series of multiprecision integers comprising the key material: return this.getPrivKeyParamTypes(algo).length;
},
getPubKeyParamTypes: function(algo) {
// Algorithm-Specific Fields for RSA public keys: // Algorithm-Specific Fields for RSA public keys:
// - a multiprecision integer (MPI) of RSA public modulus n; // - a multiprecision integer (MPI) of RSA public modulus n;
// - an MPI of RSA public encryption exponent e. // - an MPI of RSA public encryption exponent e.
@ -193,42 +208,71 @@ export default {
case 'rsa_encrypt': case 'rsa_encrypt':
case 'rsa_encrypt_sign': case 'rsa_encrypt_sign':
case 'rsa_sign': case 'rsa_sign':
return 2; return ['mpi', 'mpi'];
// Algorithm-Specific Fields for Elgamal public keys: // Algorithm-Specific Fields for Elgamal public keys:
// - MPI of Elgamal prime p; // - MPI of Elgamal prime p;
// - MPI of Elgamal group generator g; // - MPI of Elgamal group generator g;
// - MPI of Elgamal public key value y (= g**x mod p where x is secret). // - MPI of Elgamal public key value y (= g**x mod p where x is secret).
case 'elgamal': case 'elgamal':
return 3; return ['mpi', 'mpi', 'mpi'];
// Algorithm-Specific Fields for DSA public keys: // Algorithm-Specific Fields for DSA public keys:
// - MPI of DSA prime p; // - MPI of DSA prime p;
// - MPI of DSA group order q (q is a prime divisor of p-1); // - MPI of DSA group order q (q is a prime divisor of p-1);
// - MPI of DSA group generator g; // - MPI of DSA group generator g;
// - MPI of DSA public-key value y (= g**x mod p where x is secret). // - MPI of DSA public-key value y (= g**x mod p where x is secret).
case 'dsa': case 'dsa':
return 4; return ['mpi', 'mpi', 'mpi', 'mpi'];
// Algorithm-Specific Fields for ECDSA public keys: // Algorithm-Specific Fields for ECDSA public keys:
// - OID of curve; // - OID of curve;
// - MPI of EC point representing public key. // - MPI of EC point representing public key.
case 'ecdsa': case 'ecdsa':
return 2; return ['oid', 'mpi'];
// Algorithm-Specific Fields for ECDH public keys: // Algorithm-Specific Fields for ECDH public keys:
// - OID of curve; // - OID of curve;
// - MPI of EC point representing public key. // - MPI of EC point representing public key.
// - variable-length field containing KDF parameters. // - variable-length field containing KDF parameters.
case 'ecdh': case 'ecdh':
return 3; return ['oid', 'mpi', 'kdf'];
default:
throw new Error('Unknown algorithm.');
}
},
getPubKeyParamCount: function(algo) {
return this.getPubKeyParamTypes(algo).length;
},
getEncSessionKeyParamTypes: function(algo) {
switch (algo) {
// Algorithm-Specific Fields for RSA encrypted session keys:
// - MPI of RSA encrypted value m**e mod n.
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
return ['mpi'];
// Algorithm-Specific Fields for Elgamal encrypted session keys:
// - MPI of Elgamal value g**k mod p
// - MPI of Elgamal value m * y**k mod p
case 'elgamal':
return ['mpi', 'mpi'];
// Algorithm-Specific Fields for ECDH encrypted session keys:
// - MPI containing the ephemeral key used to establish the shared secret
// - EcdhSymmetricKey
case 'ecdh':
return ['mpi', 'ecdh_symkey'];
default: default:
throw new Error('Unknown algorithm.'); throw new Error('Unknown algorithm.');
} }
}, },
generateMpi: function(algo, bits, curve) { getEncSessionKeyParamCount: function(algo) {
return this.getEncSessionKeyParamTypes(algo).length;
},
generateParams: function(algo, bits, curve) {
var types = this.getPubKeyParamTypes(algo).concat(this.getPrivKeyParamTypes(algo));
switch (algo) { switch (algo) {
case 'rsa_encrypt': case 'rsa_encrypt':
case 'rsa_encrypt_sign': case 'rsa_encrypt_sign':
@ -236,33 +280,17 @@ export default {
//remember "publicKey" refers to the crypto/public_key dir //remember "publicKey" refers to the crypto/public_key dir
var rsa = new publicKey.rsa(); var rsa = new publicKey.rsa();
return rsa.generate(bits, "10001").then(function(keyObject) { return rsa.generate(bits, "10001").then(function(keyObject) {
var output = []; return mapResult([keyObject.n, keyObject.ee, keyObject.d, keyObject.p, keyObject.q, keyObject.u], types);
output.push(keyObject.n);
output.push(keyObject.ee);
output.push(keyObject.d);
output.push(keyObject.p);
output.push(keyObject.q);
output.push(keyObject.u);
return mapResult(output);
}); });
case 'ecdsa': case 'ecdsa':
return publicKey.elliptic.generate(curve).then(function (keyObject) { return publicKey.elliptic.generate(curve).then(function (keyObject) {
return [ return mapResult([keyObject.oid, keyObject.R, keyObject.r], types);
new type_oid(keyObject.oid),
BigInteger2mpi(keyObject.R),
BigInteger2mpi(keyObject.r)
];
}); });
case 'ecdh': case 'ecdh':
return publicKey.elliptic.generate(curve).then(function (keyObject) { return publicKey.elliptic.generate(curve).then(function (keyObject) {
return [ return mapResult([keyObject.oid, keyObject.R, [keyObject.hash, keyObject.cipher], keyObject.r], types);
new type_oid(keyObject.oid),
BigInteger2mpi(keyObject.R),
new type_kdf_params(keyObject.hash, keyObject.cipher),
BigInteger2mpi(keyObject.r)
];
}); });
default: default:

View File

@ -113,8 +113,7 @@ export default {
randomBits.charCodeAt(0)) + randomBits.charCodeAt(0)) +
randomBits.substring(1); randomBits.substring(1);
} }
var mpi = new type_mpi(); var mpi = new type_mpi(randomBits);
mpi.fromBytes(randomBits);
return mpi.toBigInteger(); return mpi.toBigInteger();
}, },

View File

@ -380,7 +380,7 @@ Key.prototype.encrypt = function(passphrase) {
var keys = this.getAllKeyPackets(); var keys = this.getAllKeyPackets();
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
keys[i].encrypt(passphrase); keys[i].encrypt(passphrase);
keys[i].clearPrivateMPIs(); keys[i].clearPrivateParams();
} }
}; };
@ -1279,8 +1279,8 @@ function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
packetlist.push(subkeySignaturePacket); packetlist.push(subkeySignaturePacket);
if (!options.unlocked) { if (!options.unlocked) {
secretKeyPacket.clearPrivateMPIs(); secretKeyPacket.clearPrivateParams();
secretSubkeyPacket.clearPrivateMPIs(); secretSubkeyPacket.clearPrivateParams();
} }
return new Key(packetlist); return new Key(packetlist);

View File

@ -51,12 +51,8 @@ export default function PublicKey() {
/** Key creation date. /** Key creation date.
* @type {Date} */ * @type {Date} */
this.created = new Date(); this.created = new Date();
/** A list of multiprecision integers /* Algorithm specific params */
* @type {module:type/mpi} */ this.params = [];
this.mpi = [];
/** Public key algorithm
* @type {module:enums.publicKey} */
this.algorithm = 'rsa_sign';
// time in days (V3 only) // time in days (V3 only)
this.expirationTimeV3 = 0; this.expirationTimeV3 = 0;
/** /**
@ -97,22 +93,22 @@ PublicKey.prototype.read = function (bytes) {
// - A one-octet number denoting the public-key algorithm of this key. // - A one-octet number denoting the public-key algorithm of this key.
this.algorithm = enums.read(enums.publicKey, bytes[pos++]); this.algorithm = enums.read(enums.publicKey, bytes[pos++]);
var mpicount = crypto.getPublicMpiCount(this.algorithm); var param_count = crypto.getPubKeyParamCount(this.algorithm);
this.mpi = []; this.params = [];
var bmpi = bytes.subarray(pos, bytes.length); var bmpi = bytes.subarray(pos, bytes.length);
var p = 0; var p = 0;
for (var i = 0; i < mpicount && p < bmpi.length; i++) { for (var i = 0; i < param_count && p < bmpi.length; i++) {
if ((this.algorithm === 'ecdsa' || this.algorithm === 'ecdh') && i === 0) { if ((this.algorithm === 'ecdsa' || this.algorithm === 'ecdh') && i === 0) {
this.mpi[i] = new type_oid(); this.params[i] = new type_oid();
} else if (this.algorithm === 'ecdh' && i === 2) { } else if (this.algorithm === 'ecdh' && i === 2) {
this.mpi[i] = new type_kdf_params(); this.params[i] = new type_kdf_params();
} else { } else {
this.mpi[i] = new type_mpi(); this.params[i] = new type_mpi();
} }
p += this.mpi[i].read(bmpi.subarray(p, bmpi.length)); p += this.params[i].read(bmpi.subarray(p, bmpi.length));
if (p > bmpi.length) { if (p > bmpi.length) {
throw new Error('Error reading MPI @:' + p); throw new Error('Error reading MPI @:' + p);
@ -147,10 +143,10 @@ PublicKey.prototype.write = function () {
} }
arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)])); arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)]));
var mpicount = crypto.getPublicMpiCount(this.algorithm); var param_count = crypto.getPubKeyParamCount(this.algorithm);
for (var i = 0; i < mpicount; i++) { for (var i = 0; i < param_count; i++) {
arr.push(this.mpi[i].write()); arr.push(this.params[i].write());
} }
return util.concatUint8Array(arr); return util.concatUint8Array(arr);
@ -183,7 +179,7 @@ PublicKey.prototype.getKeyId = function () {
if (this.version === 4) { if (this.version === 4) {
this.keyid.read(util.str2Uint8Array(util.hex2bin(this.getFingerprint()).substr(12, 8))); this.keyid.read(util.str2Uint8Array(util.hex2bin(this.getFingerprint()).substr(12, 8)));
} else if (this.version === 3) { } else if (this.version === 3) {
var arr = this.mpi[0].write(); var arr = this.params[0].write();
this.keyid.read(arr.subarray(arr.length - 8, arr.length)); this.keyid.read(arr.subarray(arr.length - 8, arr.length));
} }
return this.keyid; return this.keyid;
@ -202,9 +198,9 @@ PublicKey.prototype.getFingerprint = function () {
toHash = this.writeOld(); toHash = this.writeOld();
this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash)); this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash));
} else if (this.version === 3) { } else if (this.version === 3) {
var mpicount = crypto.getPublicMpiCount(this.algorithm); var param_count = crypto.getPubKeyParamCount(this.algorithm);
for (var i = 0; i < mpicount; i++) { for (var i = 0; i < param_count; i++) {
toHash += this.mpi[i].toBytes(); toHash += this.params[i].toBytes();
} }
this.fingerprint = util.Uint8Array2str(crypto.hash.md5(util.str2Uint8Array(toHash))); this.fingerprint = util.Uint8Array2str(crypto.hash.md5(util.str2Uint8Array(toHash)));
} }
@ -217,15 +213,15 @@ PublicKey.prototype.getFingerprint = function () {
* @return {int} Number of bits * @return {int} Number of bits
*/ */
PublicKey.prototype.getBitSize = function () { PublicKey.prototype.getBitSize = function () {
return this.mpi[0].byteLength() * 8; return this.params[0].byteLength() * 8;
}; };
/** /**
* Fix custom types after cloning * Fix custom types after cloning
*/ */
PublicKey.prototype.postCloneTypeFix = function() { PublicKey.prototype.postCloneTypeFix = function() {
for (var i = 0; i < this.mpi.length; i++) { for (var i = 0; i < this.params.length; i++) {
this.mpi[i] = type_mpi.fromClone(this.mpi[i]); this.params[i] = type_mpi.fromClone(this.params[i]);
} }
if (this.keyid) { if (this.keyid) {
this.keyid = type_keyid.fromClone(this.keyid); this.keyid = type_keyid.fromClone(this.keyid);

View File

@ -55,10 +55,7 @@ export default function PublicKeyEncryptedSessionKey() {
this.version = 3; this.version = 3;
this.publicKeyId = new type_keyid(); this.publicKeyId = new type_keyid();
this.publicKeyAlgorithm = 'rsa_encrypt';
this.sessionKey = null; this.sessionKey = null;
this.sessionKeyAlgorithm = 'aes256';
/** @type {Array<module:type/mpi>} */ /** @type {Array<module:type/mpi>} */
this.encrypted = []; this.encrypted = [];
@ -81,34 +78,20 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
var i = 10; var i = 10;
var integerCount = (function(algo) { var integerCount = crypto.getEncSessionKeyParamCount(this.publicKeyAlgorithm);
switch (algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
return 1;
case 'elgamal':
return 2;
case 'ecdh':
return 2;
default:
throw new Error("Invalid algorithm.");
}
})(this.publicKeyAlgorithm);
this.encrypted = []; this.encrypted = [];
for (var j = 0; j < integerCount; j++) { for (var j = 0; j < integerCount; j++) {
var mpi; var param;
if (this.publicKeyAlgorithm === 'ecdh' && j === 1) { if (this.publicKeyAlgorithm === 'ecdh' && j === 1) {
mpi = new type_ecdh_symkey(); param = new type_ecdh_symkey();
} else { } else {
mpi = new type_mpi(); param = new type_mpi();
} }
i += mpi.read(bytes.subarray(i, bytes.length)); i += param.read(bytes.subarray(i, bytes.length));
this.encrypted.push(mpi); this.encrypted.push(param);
} }
}; };
@ -136,20 +119,20 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) {
var checksum = util.calc_checksum(this.sessionKey); var checksum = util.calc_checksum(this.sessionKey);
data += util.Uint8Array2str(util.writeNumber(checksum, 2)); data += util.Uint8Array2str(util.writeNumber(checksum, 2));
var mpi; var param;
if (this.publicKeyAlgorithm === 'ecdh') { if (this.publicKeyAlgorithm === 'ecdh') {
mpi = util.str2Uint8Array(crypto.pkcs5.addPadding(data)); param = util.str2Uint8Array(crypto.pkcs5.addPadding(data));
} else { } else {
mpi = new type_mpi(); param = new type_mpi();
mpi.fromBytes(crypto.pkcs1.eme.encode( param.fromBytes(crypto.pkcs1.eme.encode(
data, data,
key.mpi[0].byteLength())); key.params[0].byteLength()));
} }
this.encrypted = crypto.publicKeyEncrypt( this.encrypted = crypto.publicKeyEncrypt(
this.publicKeyAlgorithm, this.publicKeyAlgorithm,
key.mpi, key.params,
mpi, param,
key.fingerprint); key.fingerprint);
}; };
@ -164,7 +147,7 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) {
PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) { PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) {
var result = crypto.publicKeyDecrypt( var result = crypto.publicKeyDecrypt(
this.publicKeyAlgorithm, this.publicKeyAlgorithm,
key.mpi, key.params,
this.encrypted, this.encrypted,
key.fingerprint).toBytes(); key.fingerprint).toBytes();

View File

@ -89,7 +89,7 @@ function parse_cleartext_mpi(hash_algorithm, cleartext, algorithm) {
return new Error("Hash mismatch."); return new Error("Hash mismatch.");
} }
var mpis = crypto.getPrivateMpiCount(algorithm); var mpis = crypto.getPrivKeyParamCount(algorithm);
var j = 0; var j = 0;
var mpi = []; var mpi = [];
@ -104,7 +104,7 @@ function parse_cleartext_mpi(hash_algorithm, cleartext, algorithm) {
function write_cleartext_mpi(hash_algorithm, algorithm, mpi) { function write_cleartext_mpi(hash_algorithm, algorithm, mpi) {
var arr = []; var arr = [];
var discard = crypto.getPublicMpiCount(algorithm); var discard = crypto.getPubKeyParamCount(algorithm);
for (var i = discard; i < mpi.length; i++) { for (var i = discard; i < mpi.length; i++) {
arr.push(mpi[i].write()); arr.push(mpi[i].write());
@ -147,7 +147,7 @@ SecretKey.prototype.read = function (bytes) {
if (parsedMPI instanceof Error) { if (parsedMPI instanceof Error) {
throw parsedMPI; throw parsedMPI;
} }
this.mpi = this.mpi.concat(parsedMPI); this.params = this.params.concat(parsedMPI);
this.isDecrypted = true; this.isDecrypted = true;
} }
@ -161,7 +161,7 @@ SecretKey.prototype.write = function () {
if (!this.encrypted) { if (!this.encrypted) {
arr.push(new Uint8Array([0])); arr.push(new Uint8Array([0]));
arr.push(write_cleartext_mpi('mod', this.algorithm, this.mpi)); arr.push(write_cleartext_mpi('mod', this.algorithm, this.params));
} else { } else {
arr.push(this.encrypted); arr.push(this.encrypted);
} }
@ -188,7 +188,7 @@ SecretKey.prototype.encrypt = function (passphrase) {
var s2k = new type_s2k(), var s2k = new type_s2k(),
symmetric = 'aes256', symmetric = 'aes256',
cleartext = write_cleartext_mpi('sha1', this.algorithm, this.mpi), cleartext = write_cleartext_mpi('sha1', this.algorithm, this.params),
key = produceEncryptionKey(s2k, passphrase, symmetric), key = produceEncryptionKey(s2k, passphrase, symmetric),
blockLen = crypto.cipher[symmetric].blockSize, blockLen = crypto.cipher[symmetric].blockSize,
iv = crypto.random.getRandomBytes(blockLen); iv = crypto.random.getRandomBytes(blockLen);
@ -267,7 +267,7 @@ SecretKey.prototype.decrypt = function (passphrase) {
if (parsedMPI instanceof Error) { if (parsedMPI instanceof Error) {
return false; return false;
} }
this.mpi = this.mpi.concat(parsedMPI); this.params = this.params.concat(parsedMPI);
this.isDecrypted = true; this.isDecrypted = true;
this.encrypted = null; this.encrypted = null;
return true; return true;
@ -276,8 +276,8 @@ SecretKey.prototype.decrypt = function (passphrase) {
SecretKey.prototype.generate = function (bits, curve) { SecretKey.prototype.generate = function (bits, curve) {
var self = this; var self = this;
return crypto.generateMpi(self.algorithm, bits, curve).then(function(mpi) { return crypto.generateParams(self.algorithm, bits, curve).then(function(params) {
self.mpi = mpi; self.params = params;
self.isDecrypted = true; self.isDecrypted = true;
}); });
}; };
@ -285,10 +285,10 @@ SecretKey.prototype.generate = function (bits, curve) {
/** /**
* Clear private MPIs, return to initial state * Clear private MPIs, return to initial state
*/ */
SecretKey.prototype.clearPrivateMPIs = function () { SecretKey.prototype.clearPrivateParams = function () {
if (!this.encrypted) { if (!this.encrypted) {
throw new Error('If secret key is not encrypted, clearing private MPIs is irreversible.'); throw new Error('If secret key is not encrypted, clearing private MPIs is irreversible.');
} }
this.mpi = this.mpi.slice(0, crypto.getPublicMpiCount(this.algorithm)); this.params = this.params.slice(0, crypto.getPubKeyParamCount(this.algorithm));
this.isDecrypted = false; this.isDecrypted = false;
}; };

View File

@ -243,7 +243,7 @@ Signature.prototype.sign = function (key, data) {
this.signedHashValue = hash.subarray(0, 2); this.signedHashValue = hash.subarray(0, 2);
this.signature = crypto.signature.sign(hashAlgorithm, this.signature = crypto.signature.sign(hashAlgorithm,
publicKeyAlgorithm, key.mpi, toHash); publicKeyAlgorithm, key.params, toHash);
}; };
/** /**
@ -644,7 +644,7 @@ Signature.prototype.verify = function (key, data) {
} }
this.verified = crypto.signature.verify(publicKeyAlgorithm, this.verified = crypto.signature.verify(publicKeyAlgorithm,
hashAlgorithm, mpi, key.mpi, hashAlgorithm, mpi, key.params,
util.concatUint8Array([bytes, this.signatureData, trailer])); util.concatUint8Array([bytes, this.signatureData, trailer]));
return this.verified; return this.verified;

View File

@ -42,9 +42,15 @@ import util from '../util.js';
/** /**
* @constructor * @constructor
*/ */
export default function MPI() { export default function MPI(data) {
/** An implementation dependent integer */ /** An implementation dependent integer */
this.data = null; if (data instanceof BigInteger) {
this.fromBigInteger(data);
} else if (typeof data === 'string') {
this.fromBytes(data);
} else {
this.data = null;
}
} }
/** /**

View File

@ -191,13 +191,13 @@ describe("Packet", function() {
enc.publicKeyAlgorithm = 'rsa_encrypt'; enc.publicKeyAlgorithm = 'rsa_encrypt';
enc.sessionKeyAlgorithm = 'aes256'; enc.sessionKeyAlgorithm = 'aes256';
enc.publicKeyId.bytes = '12345678'; enc.publicKeyId.bytes = '12345678';
enc.encrypt({ mpi: mpi }); enc.encrypt({ params: mpi });
msg.push(enc); msg.push(enc);
msg2.read(msg.write()); msg2.read(msg.write());
msg2[0].decrypt({ mpi: mpi }); msg2[0].decrypt({ params: mpi });
expect(stringify(msg2[0].sessionKey)).to.equal(stringify(enc.sessionKey)); expect(stringify(msg2[0].sessionKey)).to.equal(stringify(enc.sessionKey));
expect(msg2[0].sessionKeyAlgorithm).to.equal(enc.sessionKeyAlgorithm); expect(msg2[0].sessionKeyAlgorithm).to.equal(enc.sessionKeyAlgorithm);
@ -445,8 +445,8 @@ describe("Packet", function() {
return mpi; return mpi;
}); });
key[0].mpi = mpi; key[0].params = mpi;
key[0].algorithm = "rsa_sign";
key[0].encrypt('hello'); key[0].encrypt('hello');
var raw = key.write(); var raw = key.write();
@ -455,7 +455,7 @@ describe("Packet", function() {
key2.read(raw); key2.read(raw);
key2[0].decrypt('hello'); key2[0].decrypt('hello');
expect(key[0].mpi.toString()).to.equal(key2[0].mpi.toString()); expect(key[0].params.toString()).to.equal(key2[0].params.toString());
}); });
}); });
@ -473,7 +473,8 @@ describe("Packet", function() {
return mpi; return mpi;
}); });
key.mpi = mpi; key.params = mpi;
key.algorithm = "rsa_sign";
var signed = new openpgp.packet.List(), var signed = new openpgp.packet.List(),
literal = new openpgp.packet.Literal(), literal = new openpgp.packet.Literal(),