simplify packet parsing using type maps

This commit is contained in:
Sanjana Rajan 2017-07-27 00:59:21 +02:00
parent cdc7004b96
commit b718cf359d
9 changed files with 58 additions and 74 deletions

View File

@ -53,8 +53,8 @@ function createType(data, type) {
} }
} }
function mapResult(result, types) { function constructParams(result, types) {
for (var i=0; i < result.length; i++) { for (var i=0; i < types.length; i++) {
result[i] = createType(result[i], types[i]); result[i] = createType(result[i], types[i]);
} }
return result; return result;
@ -81,7 +81,7 @@ export default {
var n = publicParams[0].toBigInteger(); var n = publicParams[0].toBigInteger();
var e = publicParams[1].toBigInteger(); var e = publicParams[1].toBigInteger();
m = data.toBigInteger(); m = data.toBigInteger();
return mapResult([rsa.encrypt(m, e, n)], types); return constructParams([rsa.encrypt(m, e, n)], types);
case 'elgamal': case 'elgamal':
var elgamal = new publicKey.elgamal(); var elgamal = new publicKey.elgamal();
@ -89,7 +89,7 @@ export default {
var g = publicParams[1].toBigInteger(); var g = publicParams[1].toBigInteger();
var y = publicParams[2].toBigInteger(); var y = publicParams[2].toBigInteger();
m = data.toBigInteger(); m = data.toBigInteger();
return mapResult(elgamal.encrypt(m, g, p, y), types); return constructParams(elgamal.encrypt(m, g, p, y), types);
case 'ecdh': case 'ecdh':
var ecdh = publicKey.elliptic.ecdh; var ecdh = publicKey.elliptic.ecdh;
@ -97,7 +97,7 @@ export default {
var kdf_params = publicParams[2]; var kdf_params = publicParams[2];
var R = publicParams[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 mapResult([res.V, res.C], types); return constructParams([res.V, res.C], types);
default: default:
return []; return [];
@ -258,7 +258,7 @@ export default {
// Algorithm-Specific Fields for ECDH encrypted session keys: // Algorithm-Specific Fields for ECDH encrypted session keys:
// - MPI containing the ephemeral key used to establish the shared secret // - MPI containing the ephemeral key used to establish the shared secret
// - EcdhSymmetricKey // - ECDHSymmetricKey
case 'ecdh': case 'ecdh':
return ['mpi', 'ecdh_symkey']; return ['mpi', 'ecdh_symkey'];
@ -280,17 +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) {
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': case 'ecdsa':
return publicKey.elliptic.generate(curve).then(function (keyObject) { 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': case 'ecdh':
return publicKey.elliptic.generate(curve).then(function (keyObject) { 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: default:
@ -316,5 +316,7 @@ export default {
*/ */
generateSessionKey: function(algo) { generateSessionKey: function(algo) {
return random.getRandomBytes(cipher[algo].keySize); return random.getRandomBytes(cipher[algo].keySize);
} },
constructParams: constructParams
}; };

View File

@ -69,7 +69,7 @@ function kdf(hash_algo, X, length, param) {
/** /**
* Encrypt and wrap a session key * 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} cipher_algo Symmetric cipher to use
* @param {Enums} hash_algo Hash to use * @param {Enums} hash_algo Hash to use
* @param {Uint8Array} m Value derived from session key (RFC 6637) * @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 * 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} cipher_algo Symmetric cipher to use
* @param {Enums} hash_algo Hash algorithm to use * @param {Enums} hash_algo Hash algorithm to use
* @param {BigInteger} V Public part of ephemeral key * @param {BigInteger} V Public part of ephemeral key

View File

@ -79,21 +79,21 @@ export { default as Keyid } from './type/keyid';
/** /**
* @see module:type/ecdh_symkey * @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 * @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 * @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 * @see module:encoding/armor

View File

@ -93,24 +93,15 @@ 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 param_count = crypto.getPubKeyParamCount(this.algorithm); var types = crypto.getPubKeyParamTypes(this.algorithm);
this.params = []; 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; var p = 0;
for (var i = 0; i < param_count && p < bmpi.length; i++) { for (var i = 0; i < types.length && p < b.length; i++) {
if ((this.algorithm === 'ecdsa' || this.algorithm === 'ecdh') && i === 0) { p += this.params[i].read(b.subarray(p, b.length));
this.params[i] = new type_oid(); if (p > b.length) {
} 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) {
throw new Error('Error reading MPI @:' + p); throw new Error('Error reading MPI @:' + p);
} }
} }

View File

@ -78,20 +78,11 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
var i = 10; var i = 10;
var integerCount = crypto.getEncSessionKeyParamCount(this.publicKeyAlgorithm); var types = crypto.getEncSessionKeyParamTypes(this.publicKeyAlgorithm);
this.encrypted = crypto.constructParams(new Array(types.length), types);
for (var j = 0; j < types.length; j++) {
this.encrypted = []; i += this.encrypted[j].read(bytes.subarray(i, bytes.length));
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);
} }
}; };

View File

@ -26,12 +26,12 @@
import util from '../util.js'; import util from '../util.js';
module.exports = EcdhSymmetricKey; module.exports = ECDHSymmetricKey;
/** /**
* @constructor * @constructor
*/ */
function EcdhSymmetricKey(data) { function ECDHSymmetricKey(data) {
if (typeof data === 'undefined') { if (typeof data === 'undefined') {
data = new Uint8Array([]); data = new Uint8Array([]);
} else if (typeof data === 'string') { } 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 * @param {Uint8Array} input Where to read the encoded symmetric key from
* @return {Number} Number of read bytes * @return {Number} Number of read bytes
*/ */
EcdhSymmetricKey.prototype.read = function (input) { ECDHSymmetricKey.prototype.read = function (input) {
if (input.length >= 1) if (input.length >= 1)
{ {
var length = input[0]; 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 * @return {Uint8Array} An array containing the value
*/ */
EcdhSymmetricKey.prototype.write = function () { ECDHSymmetricKey.prototype.write = function () {
return util.concatUint8Array([ return util.concatUint8Array([
new Uint8Array([this.data.length]), new Uint8Array([this.data.length]),
this.data]); this.data]);

View File

@ -26,26 +26,26 @@
import enums from '../enums.js'; import enums from '../enums.js';
module.exports = KdfParams; module.exports = KDFParams;
/** /**
* @constructor * @constructor
* @param {enums.hash} hash Hash algorithm * @param {enums.hash} hash Hash algorithm
* @param {enums.symmetric} cipher Symmetric algorithm * @param {enums.symmetric} cipher Symmetric algorithm
*/ */
function KdfParams(hash, cipher) { function KDFParams(hash, cipher) {
this.hash = hash || enums.hash.sha1; this.hash = hash || enums.hash.sha1;
this.cipher = cipher || enums.symmetric.aes128; this.cipher = cipher || enums.symmetric.aes128;
} }
/** /**
* Read KdfParams from an Uint8Array * Read KDFParams from an Uint8Array
* @param {Uint8Array} input Where to read the KdfParams from * @param {Uint8Array} input Where to read the KDFParams from
* @return {Number} Number of read bytes * @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) { 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.hash = input[2];
this.cipher = input[3]; this.cipher = input[3];
@ -53,9 +53,9 @@ KdfParams.prototype.read = function (input) {
}; };
/** /**
* Write KdfParams to an Uint8Array * Write KDFParams to an Uint8Array
* @return {Uint8Array} Array with the KdfParams value * @return {Uint8Array} Array with the KDFParams value
*/ */
KdfParams.prototype.write = function () { KDFParams.prototype.write = function () {
return new Uint8Array([3, 1, this.hash, this.cipher]); return new Uint8Array([3, 1, this.hash, this.cipher]);
}; };

View File

@ -16,7 +16,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/** /**
* Wrapper to an Oid value<br/> * Wrapper to an OID value<br/>
* <br/> * <br/>
* An object identifier type from {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}. * An object identifier type from {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}.
* @requires util * @requires util
@ -27,12 +27,12 @@
import util from '../util.js'; import util from '../util.js';
module.exports = Oid; module.exports = OID;
/** /**
* @constructor * @constructor
*/ */
function Oid(oid) { function OID(oid) {
if (typeof oid === 'undefined') { if (typeof oid === 'undefined') {
oid = ''; oid = '';
} else if (util.isArray(oid)) { } else if (util.isArray(oid)) {
@ -44,11 +44,11 @@ function Oid(oid) {
} }
/** /**
* Method to read an Oid object * Method to read an OID object
* @param {Uint8Array} input Where to read the Oid from * @param {Uint8Array} input Where to read the OID from
* @return {Number} Number of read bytes * @return {Number} Number of read bytes
*/ */
Oid.prototype.read = function (input) { OID.prototype.read = function (input) {
if (input.length >= 1) { if (input.length >= 1) {
var length = input[0]; var length = input[0];
if (input.length >= 1+length) { if (input.length >= 1+length) {
@ -60,10 +60,10 @@ Oid.prototype.read = function (input) {
}; };
/** /**
* Serialize an Oid object * Serialize an OID object
* @return {Uint8Array} Array with the serialized value the Oid * @return {Uint8Array} Array with the serialized value the OID
*/ */
Oid.prototype.write = function () { OID.prototype.write = function () {
return util.str2Uint8Array( return util.str2Uint8Array(
String.fromCharCode(this.oid.length)+this.oid); String.fromCharCode(this.oid.length)+this.oid);
}; };

View File

@ -5,14 +5,14 @@ var openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp :
var expect = require('chai').expect; var expect = require('chai').expect;
describe('Oid tests', function() { 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 p256_oid = new Uint8Array([0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]);
var p384_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x22]); var p384_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x22]);
var p521_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x23]); var p521_oid = new Uint8Array([0x2B, 0x81, 0x04, 0x00, 0x23]);
it('Constructing', function() { it('Constructing', function() {
var oids = [p256_oid, p384_oid, p521_oid]; var oids = [p256_oid, p384_oid, p521_oid];
oids.forEach(function (data) { oids.forEach(function (data) {
var oid = new Oid(data); var oid = new OID(data);
expect(oid).to.exist; expect(oid).to.exist;
expect(oid.oid).to.exist; expect(oid.oid).to.exist;
expect(oid.oid).to.have.length(data.length); expect(oid.oid).to.have.length(data.length);
@ -22,8 +22,8 @@ describe('Oid tests', function() {
it('Reading and writing', function() { it('Reading and writing', function() {
var oids = [p256_oid, p384_oid, p521_oid]; var oids = [p256_oid, p384_oid, p521_oid];
oids.forEach(function (data) { oids.forEach(function (data) {
data = openpgp.util.concatUint8Array([new Uint8Array([data.length]), data]); data = openpgp.util.concatUint8Array([new Uint8Array([data.length]), data]);
var oid = new Oid(); var oid = new OID();
expect(oid.read(data)).to.equal(data.length); expect(oid.read(data)).to.equal(data.length);
expect(oid.oid).to.exist; expect(oid.oid).to.exist;
expect(oid.oid).to.have.length(data.length-1); expect(oid.oid).to.have.length(data.length-1);