From b718cf359d5c2551dd5e9678d4adb194936f2a2d Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Thu, 27 Jul 2017 00:59:21 +0200 Subject: [PATCH] simplify packet parsing using type maps --- src/crypto/crypto.js | 22 ++++++++++--------- src/crypto/public_key/elliptic/ecdh.js | 4 ++-- src/index.js | 12 +++++----- src/packet/public_key.js | 21 +++++------------- .../public_key_encrypted_session_key.js | 17 ++++---------- src/type/ecdh_symkey.js | 12 +++++----- src/type/kdf_params.js | 18 +++++++-------- src/type/oid.js | 18 +++++++-------- test/general/oid.js | 8 +++---- 9 files changed, 58 insertions(+), 74 deletions(-) diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 03deaac3..912633ab 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -53,8 +53,8 @@ function createType(data, type) { } } -function mapResult(result, types) { - for (var i=0; i < result.length; i++) { +function constructParams(result, types) { + for (var i=0; i < types.length; i++) { result[i] = createType(result[i], types[i]); } return result; @@ -81,7 +81,7 @@ export default { var n = publicParams[0].toBigInteger(); var e = publicParams[1].toBigInteger(); m = data.toBigInteger(); - return mapResult([rsa.encrypt(m, e, n)], types); + return constructParams([rsa.encrypt(m, e, n)], types); case 'elgamal': var elgamal = new publicKey.elgamal(); @@ -89,7 +89,7 @@ export default { var g = publicParams[1].toBigInteger(); var y = publicParams[2].toBigInteger(); m = data.toBigInteger(); - return mapResult(elgamal.encrypt(m, g, p, y), types); + return constructParams(elgamal.encrypt(m, g, p, y), types); case 'ecdh': var ecdh = publicKey.elliptic.ecdh; @@ -97,7 +97,7 @@ export default { var kdf_params = publicParams[2]; var R = publicParams[1].toBigInteger(); var res = ecdh.encrypt(curve.oid, kdf_params.cipher, kdf_params.hash, data, R, fingerprint); - return mapResult([res.V, res.C], types); + return constructParams([res.V, res.C], types); default: return []; @@ -258,7 +258,7 @@ export default { // Algorithm-Specific Fields for ECDH encrypted session keys: // - MPI containing the ephemeral key used to establish the shared secret - // - EcdhSymmetricKey + // - ECDHSymmetricKey case 'ecdh': return ['mpi', 'ecdh_symkey']; @@ -280,17 +280,17 @@ export default { //remember "publicKey" refers to the crypto/public_key dir var rsa = new publicKey.rsa(); return rsa.generate(bits, "10001").then(function(keyObject) { - return mapResult([keyObject.n, keyObject.ee, keyObject.d, keyObject.p, keyObject.q, keyObject.u], types); + return constructParams([keyObject.n, keyObject.ee, keyObject.d, keyObject.p, keyObject.q, keyObject.u], types); }); case 'ecdsa': return publicKey.elliptic.generate(curve).then(function (keyObject) { - return mapResult([keyObject.oid, keyObject.R, keyObject.r], types); + return constructParams([keyObject.oid, keyObject.R, keyObject.r], types); }); case 'ecdh': return publicKey.elliptic.generate(curve).then(function (keyObject) { - return mapResult([keyObject.oid, keyObject.R, [keyObject.hash, keyObject.cipher], keyObject.r], types); + return constructParams([keyObject.oid, keyObject.R, [keyObject.hash, keyObject.cipher], keyObject.r], types); }); default: @@ -316,5 +316,7 @@ export default { */ generateSessionKey: function(algo) { return random.getRandomBytes(cipher[algo].keySize); - } + }, + + constructParams: constructParams }; diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index af8ab3ff..8a19a378 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -69,7 +69,7 @@ function kdf(hash_algo, X, length, param) { /** * Encrypt and wrap a session key * - * @param {String} oid Oid of the curve to use + * @param {String} oid OID of the curve to use * @param {Enums} cipher_algo Symmetric cipher to use * @param {Enums} hash_algo Hash to use * @param {Uint8Array} m Value derived from session key (RFC 6637) @@ -96,7 +96,7 @@ function encrypt(oid, cipher_algo, hash_algo, m, R, fingerprint) { /** * Decrypt and unwrap the value derived from session key * - * @param {String} oid Curve oid + * @param {String} oid Curve OID * @param {Enums} cipher_algo Symmetric cipher to use * @param {Enums} hash_algo Hash algorithm to use * @param {BigInteger} V Public part of ephemeral key diff --git a/src/index.js b/src/index.js index fd0e9de5..46bec340 100644 --- a/src/index.js +++ b/src/index.js @@ -79,21 +79,21 @@ export { default as Keyid } from './type/keyid'; /** * @see module:type/ecdh_symkey - * @name module:openpgp.EcdhSymmetricKey + * @name module:openpgp.ECDHSymmetricKey */ -export { default as EcdhSymmetricKey } from './type/ecdh_symkey'; +export { default as ECDHSymmetricKey } from './type/ecdh_symkey'; /** * @see module:type/kdf_params - * @name module:openpgp.KdfParams + * @name module:openpgp.KDFParams */ -export { default as KdfParams } from './type/kdf_params'; +export { default as KDFParams } from './type/kdf_params'; /** * @see module:type/oid - * @name module:openpgp.Oid + * @name module:openpgp.OID */ -export { default as Oid } from './type/oid'; +export { default as OID } from './type/oid'; /** * @see module:encoding/armor diff --git a/src/packet/public_key.js b/src/packet/public_key.js index 57b4ca98..c9f6af1e 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -93,24 +93,15 @@ PublicKey.prototype.read = function (bytes) { // - A one-octet number denoting the public-key algorithm of this key. this.algorithm = enums.read(enums.publicKey, bytes[pos++]); - var param_count = crypto.getPubKeyParamCount(this.algorithm); - this.params = []; + var types = crypto.getPubKeyParamTypes(this.algorithm); + this.params = crypto.constructParams(new Array(types.length), types); - var bmpi = bytes.subarray(pos, bytes.length); + var b = bytes.subarray(pos, bytes.length); var p = 0; - for (var i = 0; i < param_count && p < bmpi.length; i++) { - if ((this.algorithm === 'ecdsa' || this.algorithm === 'ecdh') && i === 0) { - this.params[i] = new type_oid(); - } else if (this.algorithm === 'ecdh' && i === 2) { - this.params[i] = new type_kdf_params(); - } else { - this.params[i] = new type_mpi(); - } - - p += this.params[i].read(bmpi.subarray(p, bmpi.length)); - - if (p > bmpi.length) { + for (var i = 0; i < types.length && p < b.length; i++) { + p += this.params[i].read(b.subarray(p, b.length)); + if (p > b.length) { throw new Error('Error reading MPI @:' + p); } } diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index 9678f479..a05ff206 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -78,20 +78,11 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { var i = 10; - var integerCount = crypto.getEncSessionKeyParamCount(this.publicKeyAlgorithm); + var types = crypto.getEncSessionKeyParamTypes(this.publicKeyAlgorithm); + this.encrypted = crypto.constructParams(new Array(types.length), types); - - this.encrypted = []; - - for (var j = 0; j < integerCount; j++) { - var param; - if (this.publicKeyAlgorithm === 'ecdh' && j === 1) { - param = new type_ecdh_symkey(); - } else { - param = new type_mpi(); - } - i += param.read(bytes.subarray(i, bytes.length)); - this.encrypted.push(param); + for (var j = 0; j < types.length; j++) { + i += this.encrypted[j].read(bytes.subarray(i, bytes.length)); } }; diff --git a/src/type/ecdh_symkey.js b/src/type/ecdh_symkey.js index ef32b68a..84b3be2d 100644 --- a/src/type/ecdh_symkey.js +++ b/src/type/ecdh_symkey.js @@ -26,12 +26,12 @@ import util from '../util.js'; -module.exports = EcdhSymmetricKey; +module.exports = ECDHSymmetricKey; /** * @constructor */ -function EcdhSymmetricKey(data) { +function ECDHSymmetricKey(data) { if (typeof data === 'undefined') { data = new Uint8Array([]); } else if (typeof data === 'string') { @@ -43,11 +43,11 @@ function EcdhSymmetricKey(data) { } /** - * Read an EcdhSymmetricKey from an Uint8Array + * Read an ECDHSymmetricKey from an Uint8Array * @param {Uint8Array} input Where to read the encoded symmetric key from * @return {Number} Number of read bytes */ -EcdhSymmetricKey.prototype.read = function (input) { +ECDHSymmetricKey.prototype.read = function (input) { if (input.length >= 1) { var length = input[0]; @@ -61,10 +61,10 @@ EcdhSymmetricKey.prototype.read = function (input) { }; /** - * Write an EcdhSymmetricKey as an Uint8Array + * Write an ECDHSymmetricKey as an Uint8Array * @return {Uint8Array} An array containing the value */ -EcdhSymmetricKey.prototype.write = function () { +ECDHSymmetricKey.prototype.write = function () { return util.concatUint8Array([ new Uint8Array([this.data.length]), this.data]); diff --git a/src/type/kdf_params.js b/src/type/kdf_params.js index 1a6d1371..4720c280 100644 --- a/src/type/kdf_params.js +++ b/src/type/kdf_params.js @@ -26,26 +26,26 @@ import enums from '../enums.js'; -module.exports = KdfParams; +module.exports = KDFParams; /** * @constructor * @param {enums.hash} hash Hash algorithm * @param {enums.symmetric} cipher Symmetric algorithm */ -function KdfParams(hash, cipher) { +function KDFParams(hash, cipher) { this.hash = hash || enums.hash.sha1; this.cipher = cipher || enums.symmetric.aes128; } /** - * Read KdfParams from an Uint8Array - * @param {Uint8Array} input Where to read the KdfParams from + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input Where to read the KDFParams from * @return {Number} Number of read bytes */ -KdfParams.prototype.read = function (input) { +KDFParams.prototype.read = function (input) { if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KdfParams'); + throw new Error('Cannot read KDFParams'); } this.hash = input[2]; this.cipher = input[3]; @@ -53,9 +53,9 @@ KdfParams.prototype.read = function (input) { }; /** - * Write KdfParams to an Uint8Array - * @return {Uint8Array} Array with the KdfParams value + * Write KDFParams to an Uint8Array + * @return {Uint8Array} Array with the KDFParams value */ -KdfParams.prototype.write = function () { +KDFParams.prototype.write = function () { return new Uint8Array([3, 1, this.hash, this.cipher]); }; diff --git a/src/type/oid.js b/src/type/oid.js index a8fd1899..c4253889 100644 --- a/src/type/oid.js +++ b/src/type/oid.js @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /** - * Wrapper to an Oid value
+ * Wrapper to an OID value
*
* An object identifier type from {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}. * @requires util @@ -27,12 +27,12 @@ import util from '../util.js'; -module.exports = Oid; +module.exports = OID; /** * @constructor */ -function Oid(oid) { +function OID(oid) { if (typeof oid === 'undefined') { oid = ''; } else if (util.isArray(oid)) { @@ -44,11 +44,11 @@ function Oid(oid) { } /** - * Method to read an Oid object - * @param {Uint8Array} input Where to read the Oid from + * Method to read an OID object + * @param {Uint8Array} input Where to read the OID from * @return {Number} Number of read bytes */ -Oid.prototype.read = function (input) { +OID.prototype.read = function (input) { if (input.length >= 1) { var length = input[0]; if (input.length >= 1+length) { @@ -60,10 +60,10 @@ Oid.prototype.read = function (input) { }; /** - * Serialize an Oid object - * @return {Uint8Array} Array with the serialized value the Oid + * Serialize an OID object + * @return {Uint8Array} Array with the serialized value the OID */ -Oid.prototype.write = function () { +OID.prototype.write = function () { return util.str2Uint8Array( String.fromCharCode(this.oid.length)+this.oid); }; diff --git a/test/general/oid.js b/test/general/oid.js index e093f407..b4f4e68a 100644 --- a/test/general/oid.js +++ b/test/general/oid.js @@ -5,14 +5,14 @@ var openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : var expect = require('chai').expect; describe('Oid tests', function() { - var Oid = openpgp.Oid; + var OID = openpgp.OID; var p256_oid = new Uint8Array([0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]); var p384_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x22]); var p521_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x23]); it('Constructing', function() { var oids = [p256_oid, p384_oid, p521_oid]; oids.forEach(function (data) { - var oid = new Oid(data); + var oid = new OID(data); expect(oid).to.exist; expect(oid.oid).to.exist; expect(oid.oid).to.have.length(data.length); @@ -22,8 +22,8 @@ describe('Oid tests', function() { it('Reading and writing', function() { var oids = [p256_oid, p384_oid, p521_oid]; oids.forEach(function (data) { - data = openpgp.util.concatUint8Array([new Uint8Array([data.length]), data]); - var oid = new Oid(); + data = openpgp.util.concatUint8Array([new Uint8Array([data.length]), data]); + var oid = new OID(); expect(oid.read(data)).to.equal(data.length); expect(oid.oid).to.exist; expect(oid.oid).to.have.length(data.length-1);