simplify packet parsing using type maps
This commit is contained in:
parent
cdc7004b96
commit
b718cf359d
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
12
src/index.js
12
src/index.js
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user