From b40408d42fb5f766afe4dcefbd36cf2dcc29fba8 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Thu, 27 Jul 2017 14:38:45 +0200 Subject: [PATCH] standardize packet reading code, make pkcs5 function names same as pkcs1 --- src/crypto/pkcs5.js | 29 ++++-------- src/crypto/public_key/elliptic/ecdh.js | 2 +- src/packet/public_key.js | 8 ++-- .../public_key_encrypted_session_key.js | 13 ++--- src/packet/secret_key.js | 47 +++++++++---------- test/crypto/pkcs5.js | 8 ++-- 6 files changed, 47 insertions(+), 60 deletions(-) diff --git a/src/crypto/pkcs5.js b/src/crypto/pkcs5.js index fc1e694a..a9e364ff 100644 --- a/src/crypto/pkcs5.js +++ b/src/crypto/pkcs5.js @@ -17,27 +17,18 @@ // Functions to add and remove PKCS5 padding -/** - * PKCS5 padding - * @module crypto/pkcs5 - */ - -function getPkcs5Padding(length) { - const c = 8 - (length % 8); - var result = []; - for (var i = 0; i < c; ++i) { - result.push(String.fromCharCode(c)); - } - return result.join(""); -} - /** * Add pkcs5 padding to a text. * @param {String} msg Text to add padding * @return {String} Text with padding added */ -function addPadding(msg) { - return msg + getPkcs5Padding(msg.length); +function encode(msg) { + const c = 8 - (msg.length % 8); + var result = []; + for (var i = 0; i < c; ++i) { + result.push(String.fromCharCode(c)); + } + return msg + result.join(""); } /** @@ -45,7 +36,7 @@ function addPadding(msg) { * @param {String} msg Text to remove padding from * @return {String} Text with padding removed */ -function removePadding(msg) { +function decode(msg) { var len = msg.length; if (len > 0) { var c = msg.charCodeAt(len - 1); @@ -57,6 +48,6 @@ function removePadding(msg) { } module.exports = { - addPadding: addPadding, - removePadding: removePadding + encode: encode, + decode: decode }; diff --git a/src/crypto/public_key/elliptic/ecdh.js b/src/crypto/public_key/elliptic/ecdh.js index 8a19a378..d1cf9f0c 100644 --- a/src/crypto/public_key/elliptic/ecdh.js +++ b/src/crypto/public_key/elliptic/ecdh.js @@ -86,7 +86,7 @@ function encrypt(oid, cipher_algo, hash_algo, m, R, fingerprint) { R = curve.keyFromPublic(R.toByteArray()); const S = v.derive(R); const Z = kdf(hash_algo, S, cipher[cipher_algo].keySize, param); - const C = aes_kw.wrap(Z, m); + const C = aes_kw.wrap(Z, m.toBytes()); return { V: new BigInteger(v.getPublic()), C: C diff --git a/src/packet/public_key.js b/src/packet/public_key.js index c9f6af1e..faf8eec1 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -134,9 +134,9 @@ PublicKey.prototype.write = function () { } arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)])); - var param_count = crypto.getPubKeyParamCount(this.algorithm); + var paramCount = crypto.getPubKeyParamCount(this.algorithm); - for (var i = 0; i < param_count; i++) { + for (var i = 0; i < paramCount; i++) { arr.push(this.params[i].write()); } @@ -189,8 +189,8 @@ PublicKey.prototype.getFingerprint = function () { toHash = this.writeOld(); this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash)); } else if (this.version === 3) { - var param_count = crypto.getPubKeyParamCount(this.algorithm); - for (var i = 0; i < param_count; i++) { + var paramCount = crypto.getPubKeyParamCount(this.algorithm); + for (var i = 0; i < paramCount; i++) { toHash += this.params[i].toBytes(); } this.fingerprint = util.Uint8Array2str(crypto.hash.md5(util.str2Uint8Array(toHash))); diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index a05ff206..925abd3d 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -110,20 +110,17 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) { var checksum = util.calc_checksum(this.sessionKey); data += util.Uint8Array2str(util.writeNumber(checksum, 2)); - var param; + var toEncrypt; if (this.publicKeyAlgorithm === 'ecdh') { - param = util.str2Uint8Array(crypto.pkcs5.addPadding(data)); + toEncrypt = new type_mpi(crypto.pkcs5.encode(data)); } else { - param = new type_mpi(); - param.fromBytes(crypto.pkcs1.eme.encode( - data, - key.params[0].byteLength())); + toEncrypt = new type_mpi(crypto.pkcs1.eme.encode(data, key.params[0].byteLength())); } this.encrypted = crypto.publicKeyEncrypt( this.publicKeyAlgorithm, key.params, - param, + toEncrypt, key.fingerprint); }; @@ -145,7 +142,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) { var checksum; var decoded; if (this.publicKeyAlgorithm === 'ecdh') { - decoded = crypto.pkcs5.removePadding(result); + decoded = crypto.pkcs5.decode(result); checksum = util.readNumber(util.str2Uint8Array(decoded.substr(decoded.length - 2))); } else { decoded = crypto.pkcs1.eme.decode(result); diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 52bfce8f..94a5e703 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -37,7 +37,6 @@ import publicKey from './public_key.js'; import enums from '../enums.js'; import util from '../util.js'; import crypto from '../crypto'; -import type_mpi from '../type/mpi.js'; import type_s2k from '../type/s2k.js'; /** @@ -76,38 +75,38 @@ function get_hash_fn(hash) { // Helper function -function parse_cleartext_mpi(hash_algorithm, cleartext, algorithm) { +function parse_cleartext_params(hash_algorithm, cleartext, algorithm) { var hashlen = get_hash_len(hash_algorithm), hashfn = get_hash_fn(hash_algorithm); var hashtext = util.Uint8Array2str(cleartext.subarray(cleartext.length - hashlen, cleartext.length)); cleartext = cleartext.subarray(0, cleartext.length - hashlen); - var hash = util.Uint8Array2str(hashfn(cleartext)); if (hash !== hashtext) { return new Error("Hash mismatch."); } - var mpis = crypto.getPrivKeyParamCount(algorithm); + var types = crypto.getPrivKeyParamTypes(algorithm); + var params = crypto.constructParams(new Array(types.length), types); + var p = 0; - var j = 0; - var mpi = []; - - for (var i = 0; i < mpis && j < cleartext.length; i++) { - mpi[i] = new type_mpi(); - j += mpi[i].read(cleartext.subarray(j, cleartext.length)); + for (var i = 0; i < types.length && p < cleartext.length; i++) { + p += params[i].read(cleartext.subarray(p, cleartext.length)); + if (p > cleartext.length) { + throw new Error('Error reading MPI @:' + p); + } } - return mpi; + return params; } -function write_cleartext_mpi(hash_algorithm, algorithm, mpi) { +function write_cleartext_params(hash_algorithm, algorithm, params) { var arr = []; - var discard = crypto.getPubKeyParamCount(algorithm); + var numPublicParams = crypto.getPubKeyParamCount(algorithm); - for (var i = discard; i < mpi.length; i++) { - arr.push(mpi[i].write()); + for (var i = numPublicParams; i < params.length; i++) { + arr.push(params[i].write()); } var bytes = util.concatUint8Array(arr); @@ -143,11 +142,11 @@ SecretKey.prototype.read = function (bytes) { // - Plain or encrypted multiprecision integers comprising the secret // key data. These algorithm-specific fields are as described // below. - var parsedMPI = parse_cleartext_mpi('mod', bytes.subarray(1, bytes.length), this.algorithm); - if (parsedMPI instanceof Error) { - throw parsedMPI; + var privParams = parse_cleartext_params('mod', bytes.subarray(1, bytes.length), this.algorithm); + if (privParams instanceof Error) { + throw privParams; } - this.params = this.params.concat(parsedMPI); + this.params = this.params.concat(privParams); this.isDecrypted = true; } @@ -161,7 +160,7 @@ SecretKey.prototype.write = function () { if (!this.encrypted) { arr.push(new Uint8Array([0])); - arr.push(write_cleartext_mpi('mod', this.algorithm, this.params)); + arr.push(write_cleartext_params('mod', this.algorithm, this.params)); } else { arr.push(this.encrypted); } @@ -188,7 +187,7 @@ SecretKey.prototype.encrypt = function (passphrase) { var s2k = new type_s2k(), symmetric = 'aes256', - cleartext = write_cleartext_mpi('sha1', this.algorithm, this.params), + cleartext = write_cleartext_params('sha1', this.algorithm, this.params), key = produceEncryptionKey(s2k, passphrase, symmetric), blockLen = crypto.cipher[symmetric].blockSize, iv = crypto.random.getRandomBytes(blockLen); @@ -263,11 +262,11 @@ SecretKey.prototype.decrypt = function (passphrase) { 'sha1' : 'mod'; - var parsedMPI = parse_cleartext_mpi(hash, cleartext, this.algorithm); - if (parsedMPI instanceof Error) { + var privParams = parse_cleartext_params(hash, cleartext, this.algorithm); + if (privParams instanceof Error) { return false; } - this.params = this.params.concat(parsedMPI); + this.params = this.params.concat(privParams); this.isDecrypted = true; this.encrypted = null; return true; diff --git a/test/crypto/pkcs5.js b/test/crypto/pkcs5.js index 98b6a591..2e078ffa 100644 --- a/test/crypto/pkcs5.js +++ b/test/crypto/pkcs5.js @@ -16,7 +16,7 @@ describe('PKCS5 padding', function() { it('Add padding', function () { var s = ''; while (s.length < 16) { - var r = pkcs5.addPadding(s); + var r = pkcs5.encode(s); // 0..7 -> 8, 8..15 -> 16 var l = Math.ceil((s.length+1)/8)*8; var c = l - s.length; @@ -30,12 +30,12 @@ describe('PKCS5 padding', function() { for (var k=1; k<=8; ++k) { var s = repeat(' ', 8-k); var r = s + repeat(String.fromCharCode(k), k); - var t = pkcs5.removePadding(r); + var t = pkcs5.decode(r); expect(t).to.equal(s); } }); it('Invalid padding', function () { - expect(function () {pkcs5.removePadding(' ');}).to.throw(Error, /Invalid padding/); - expect(function () {pkcs5.removePadding('');}).to.throw(Error, /Invalid padding/); + expect(function () {pkcs5.decode(' ');}).to.throw(Error, /Invalid padding/); + expect(function () {pkcs5.decode('');}).to.throw(Error, /Invalid padding/); }); });