summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Turek <brian.turek@gmail.com>2016-07-16 09:38:01 -0400
committerBrian Turek <brian.turek@gmail.com>2016-07-16 12:55:25 -0400
commitf0a8d65320b4e4b9169950dabe0fed45229c3537 (patch)
tree2d070c28b40656dddd0c7f1ddfc150d4c8ce84d7
parent99f0125a348cdf3ce1ccc9690ce001d31b311f40 (diff)
downloadjsSHA-f0a8d65320b4e4b9169950dabe0fed45229c3537.zip
jsSHA-f0a8d65320b4e4b9169950dabe0fed45229c3537.tar.gz
jsSHA-f0a8d65320b4e4b9169950dabe0fed45229c3537.tar.bz2
Add little endian logic in conversion functions so SHA-3 doesn't need big<->little endian conversions in the round functions
-rw-r--r--src/sha_dev.js355
1 files changed, 229 insertions, 126 deletions
diff --git a/src/sha_dev.js b/src/sha_dev.js
index b84062c..f45ef1f 100644
--- a/src/sha_dev.js
+++ b/src/sha_dev.js
@@ -29,7 +29,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
"use strict";
/* Globals */
- var TWO_PWR_32 = (1 << 16) * (1 << 16);
+ var TWO_PWR_32 = 4294967296;
/**
* Int_64 is a object for 2 32-bit numbers emulating a 64-bit number
@@ -51,48 +51,51 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
*
* There is a known bug with an odd number of existing bytes and using a
* UTF-16 encoding. However, this function is used such that the existing
- * bytes are always a result of a previous UTF-16 str2binb call and
+ * bytes are always a result of a previous UTF-16 str2packed call and
* therefore there should never be an odd number of existing bytes
*
* @private
* @param {string} str String to be converted to binary representation
* @param {string} utfType The Unicode type, UTF8 or UTF16BE, UTF16LE, to
* use to encode the source string
- * @param {Array<number>} existingBin A packed int array of bytes to
+ * @param {Array<number>} existingPacked A packed int array of bytes to
* append the results to
- * @param {number} existingBinLen The number of bits in the existingBin
+ * @param {number} existingPackedLen The number of bits in the existingPacked
* array
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {{value : Array<number>, binLen : number}} Hash list where
* "value" contains the output number array and "binLen" is the binary
* length of "value"
*/
- function str2binb(str, utfType, existingBin, existingBinLen)
+ function str2packed(str, utfType, existingPacked, existingPackedLen, bigEndianMod)
{
- var bin = [], codePnt, binArr = [], byteCnt = 0, i, j, existingByteLen,
- intOffset, byteOffset;
+ var packed, codePnt, codePntArr, byteCnt = 0, i, j, existingByteLen,
+ intOffset, byteOffset, shiftModifier;
- bin = existingBin || [0];
- existingBinLen = existingBinLen || 0;
- existingByteLen = existingBinLen >>> 3;
+ packed = existingPacked || [0];
+ existingPackedLen = existingPackedLen || 0;
+ existingByteLen = existingPackedLen >>> 3;
if ("UTF8" === utfType)
{
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < str.length; i += 1)
{
codePnt = str.charCodeAt(i);
- binArr = [];
+ codePntArr = [];
if (0x80 > codePnt)
{
- binArr.push(codePnt);
+ codePntArr.push(codePnt);
}
else if (0x800 > codePnt)
{
- binArr.push(0xC0 | (codePnt >>> 6));
- binArr.push(0x80 | (codePnt & 0x3F));
+ codePntArr.push(0xC0 | (codePnt >>> 6));
+ codePntArr.push(0x80 | (codePnt & 0x3F));
}
else if ((0xd800 > codePnt) || (0xe000 <= codePnt)) {
- binArr.push(
+ codePntArr.push(
0xe0 | (codePnt >>> 12),
0x80 | ((codePnt >>> 6) & 0x3f),
0x80 | (codePnt & 0x3f)
@@ -102,7 +105,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
{
i += 1;
codePnt = 0x10000 + (((codePnt & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
- binArr.push(
+ codePntArr.push(
0xf0 | (codePnt >>> 18),
0x80 | ((codePnt >>> 12) & 0x3f),
0x80 | ((codePnt >>> 6) & 0x3f),
@@ -110,22 +113,23 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
);
}
- for (j = 0; j < binArr.length; j += 1)
+ for (j = 0; j < codePntArr.length; j += 1)
{
byteOffset = byteCnt + existingByteLen;
intOffset = byteOffset >>> 2;
- while (bin.length <= intOffset)
+ while (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
/* Known bug kicks in here */
- bin[intOffset] |= binArr[j] << (8 * (3 - (byteOffset % 4)));
+ packed[intOffset] |= codePntArr[j] << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
byteCnt += 1;
}
}
}
else if (("UTF16BE" === utfType) || "UTF16LE" === utfType)
{
+ shiftModifier = (bigEndianMod === -1) ? 2 : 0;
for (i = 0; i < str.length; i += 1)
{
codePnt = str.charCodeAt(i);
@@ -138,15 +142,15 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
byteOffset = byteCnt + existingByteLen;
intOffset = byteOffset >>> 2;
- while (bin.length <= intOffset)
+ while (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
- bin[intOffset] |= codePnt << (8 * (2 - (byteOffset % 4)));
+ packed[intOffset] |= codePnt << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
byteCnt += 2;
}
}
- return {"value" : bin, "binLen" : byteCnt * 8 + existingBinLen};
+ return {"value" : packed, "binLen" : byteCnt * 8 + existingPackedLen};
}
/**
@@ -154,28 +158,31 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
*
* @private
* @param {string} str String to be converted to binary representation
- * @param {Array<number>} existingBin A packed int array of bytes to
+ * @param {Array<number>} existingPacked A packed int array of bytes to
* append the results to
- * @param {number} existingBinLen The number of bits in the existingBin
+ * @param {number} existingPackedLen The number of bits in the existingPacked
* array
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {{value : Array<number>, binLen : number}} Hash list where
* "value" contains the output number array and "binLen" is the binary
* length of "value"
*/
- function hex2binb(str, existingBin, existingBinLen)
+ function hex2packed(str, existingPacked, existingPackedLen, bigEndianMod)
{
- var bin, length = str.length, i, num, intOffset, byteOffset,
- existingByteLen;
-
- bin = existingBin || [0];
- existingBinLen = existingBinLen || 0;
- existingByteLen = existingBinLen >>> 3;
+ var packed, length = str.length, i, num, intOffset, byteOffset,
+ existingByteLen, shiftModifier;
if (0 !== (length % 2))
{
throw new Error("String of HEX type must be in byte increments");
}
+ packed = existingPacked || [0];
+ existingPackedLen = existingPackedLen || 0;
+ existingByteLen = existingPackedLen >>> 3;
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
+
for (i = 0; i < length; i += 2)
{
num = parseInt(str.substr(i, 2), 16);
@@ -183,11 +190,11 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
{
byteOffset = (i >>> 1) + existingByteLen;
intOffset = byteOffset >>> 2;
- while (bin.length <= intOffset)
+ while (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
- bin[intOffset] |= num << 8 * (3 - (byteOffset % 4));
+ packed[intOffset] |= num << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
}
else
{
@@ -195,7 +202,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
}
}
- return {"value" : bin, "binLen" : length * 4 + existingBinLen};
+ return {"value" : packed, "binLen" : length * 4 + existingPackedLen};
}
/**
@@ -203,22 +210,25 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
*
* @private
* @param {string} str String of raw bytes to be converted to binary representation
- * @param {Array<number>} existingBin A packed int array of bytes to
+ * @param {Array<number>} existingPacked A packed int array of bytes to
* append the results to
- * @param {number} existingBinLen The number of bits in the existingBin
+ * @param {number} existingPackedLen The number of bits in the existingPacked
* array
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {{value : Array<number>, binLen : number}} Hash list where
* "value" contains the output number array and "binLen" is the binary
* length of "value"
*/
- function bytes2binb(str, existingBin, existingBinLen)
+ function bytes2packed(str, existingPacked, existingPackedLen, bigEndianMod)
{
- var bin = [], codePnt, i, existingByteLen, intOffset,
- byteOffset;
+ var packed, codePnt, i, existingByteLen, intOffset,
+ byteOffset, shiftModifier;
- bin = existingBin || [0];
- existingBinLen = existingBinLen || 0;
- existingByteLen = existingBinLen >>> 3;
+ packed = existingPacked || [0];
+ existingPackedLen = existingPackedLen || 0;
+ existingByteLen = existingPackedLen >>> 3;
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < str.length; i += 1)
{
@@ -226,14 +236,14 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
byteOffset = i + existingByteLen;
intOffset = byteOffset >>> 2;
- if (bin.length <= intOffset)
+ if (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
- bin[intOffset] |= codePnt << 8 * (3 - (byteOffset % 4));
+ packed[intOffset] |= codePnt << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
}
- return {"value" : bin, "binLen" : str.length * 8 + existingBinLen};
+ return {"value" : packed, "binLen" : str.length * 8 + existingPackedLen};
}
/**
@@ -241,28 +251,27 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
*
* @private
* @param {string} str String to be converted to binary representation
- * @param {Array<number>} existingBin A packed int array of bytes to
+ * @param {Array<number>} existingPacked A packed int array of bytes to
* append the results to
- * @param {number} existingBinLen The number of bits in the existingBin
+ * @param {number} existingPackedLen The number of bits in the existingPacked
* array
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {{value : Array<number>, binLen : number}} Hash list where
* "value" contains the output number array and "binLen" is the binary
* length of "value"
*/
- function b642binb(str, existingBin, existingBinLen)
+ function b642packed(str, existingPacked, existingPackedLen, bigEndianMod)
{
- var bin = [], byteCnt = 0, index, i, j, tmpInt, strPart, firstEqual,
+ var packed, byteCnt = 0, index, i, j, tmpInt, strPart, firstEqual,
b64Tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
- existingByteLen, intOffset, byteOffset;
-
- bin = existingBin || [0];
- existingBinLen = existingBinLen || 0;
- existingByteLen = existingBinLen >>> 3;
+ existingByteLen, intOffset, byteOffset, shiftModifier;
if (-1 === str.search(/^[a-zA-Z0-9=+\/]+$/))
{
throw new Error("Invalid character in base-64 string");
}
+
firstEqual = str.indexOf("=");
str = str.replace(/\=/g, "");
if ((-1 !== firstEqual) && (firstEqual < str.length))
@@ -270,6 +279,11 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
throw new Error("Invalid '=' found in base-64 string");
}
+ packed = existingPacked || [0];
+ existingPackedLen = existingPackedLen || 0;
+ existingByteLen = existingPackedLen >>> 3;
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
+
for (i = 0; i < str.length; i += 4)
{
strPart = str.substr(i, 4);
@@ -285,17 +299,17 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
{
byteOffset = byteCnt + existingByteLen;
intOffset = byteOffset >>> 2;
- while (bin.length <= intOffset)
+ while (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
- bin[intOffset] |= ((tmpInt >>> (16 - (j * 8))) & 0xFF) <<
- 8 * (3 - (byteOffset % 4));
+ packed[intOffset] |= ((tmpInt >>> (16 - (j * 8))) & 0xFF) <<
+ (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
byteCnt += 1;
}
}
- return {"value" : bin, "binLen" : byteCnt * 8 + existingBinLen};
+ return {"value" : packed, "binLen" : byteCnt * 8 + existingPackedLen};
}
/**
@@ -304,57 +318,64 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* @private
* @param {ArrayBuffer} arr ArrayBuffer to be converted to binary
* representation
- * @param {Array<number>} existingBin A packed int array of bytes to
+ * @param {Array<number>} existingPacked A packed int array of bytes to
* append the results to
- * @param {number} existingBinLen The number of bits in the existingBin
+ * @param {number} existingPackedLen The number of bits in the existingPacked
* array
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {{value : Array<number>, binLen : number}} Hash list where
* "value" contains the output number array and "binLen" is the binary
* length of "value"
*/
- function arraybuffer2binb(arr, existingBin, existingBinLen)
+ function arraybuffer2packed(arr, existingPacked, existingPackedLen, bigEndianMod)
{
- var bin = [], i, existingByteLen, intOffset, byteOffset;
+ var packed, i, existingByteLen, intOffset, byteOffset, shiftModifier;
- bin = existingBin || [0];
- existingBinLen = existingBinLen || 0;
- existingByteLen = existingBinLen >>> 3;
+ packed = existingPacked || [0];
+ existingPackedLen = existingPackedLen || 0;
+ existingByteLen = existingPackedLen >>> 3;
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < arr.byteLength; i += 1)
{
byteOffset = i + existingByteLen;
intOffset = byteOffset >>> 2;
- if (bin.length <= intOffset)
+ if (packed.length <= intOffset)
{
- bin.push(0);
+ packed.push(0);
}
- bin[intOffset] |= arr[i] << 8 * (3 - (byteOffset % 4));
+ packed[intOffset] |= arr[i] << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4)));
}
- return {"value" : bin, "binLen" : arr.byteLength * 8 + existingBinLen};
+ return {"value" : packed, "binLen" : arr.byteLength * 8 + existingPackedLen};
}
/**
* Convert an array of big-endian words to a hex string.
*
* @private
- * @param {Array<number>} binarray Array of integers to be converted to
+ * @param {Array<number>} packed Array of integers to be converted to
* hexidecimal representation
* @param {number} outputLength Length of output in bits
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @param {{outputUpper : boolean, b64Pad : string}} formatOpts Hash list
* containing validated output formatting options
* @return {string} Hexidecimal representation of the parameter in string
* form
*/
- function binb2hex(binarray, outputLength, formatOpts)
+ function packed2hex(packed, outputLength, bigEndianMod, formatOpts)
{
var hex_tab = "0123456789abcdef", str = "",
- length = outputLength / 8, i, srcByte;
+ length = outputLength / 8, i, srcByte, shiftModifier;
+
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < length; i += 1)
{
/* The below is more than a byte but it gets taken care of later */
- srcByte = binarray[i >>> 2] >>> ((3 - (i % 4)) * 8);
+ srcByte = packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)));
str += hex_tab.charAt((srcByte >>> 4) & 0xF) +
hex_tab.charAt(srcByte & 0xF);
}
@@ -366,26 +387,30 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* Convert an array of big-endian words to a base-64 string
*
* @private
- * @param {Array<number>} binarray Array of integers to be converted to
+ * @param {Array<number>} packed Array of integers to be converted to
* base-64 representation
* @param {number} outputLength Length of output in bits
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @param {{outputUpper : boolean, b64Pad : string}} formatOpts Hash list
* containing validated output formatting options
* @return {string} Base-64 encoded representation of the parameter in
* string form
*/
- function binb2b64(binarray, outputLength, formatOpts)
+ function packed2b64(packed, outputLength, bigEndianMod, formatOpts)
{
- var str = "", length = outputLength / 8, i, j, triplet, int1, int2,
+ var str = "", length = outputLength / 8, i, j, triplet, int1, int2, shiftModifier,
b64Tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
+
for (i = 0; i < length; i += 3)
{
- int1 = ((i + 1) < length) ? binarray[(i + 1) >>> 2] : 0;
- int2 = ((i + 2) < length) ? binarray[(i + 2) >>> 2] : 0;
- triplet = (((binarray[i >>> 2] >>> 8 * (3 - i % 4)) & 0xFF) << 16) |
- (((int1 >>> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) |
- ((int2 >>> 8 * (3 - (i + 2) % 4)) & 0xFF);
+ int1 = ((i + 1) < length) ? packed[(i + 1) >>> 2] : 0;
+ int2 = ((i + 2) < length) ? packed[(i + 2) >>> 2] : 0;
+ triplet = (((packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF) << 16) |
+ (((int1 >>> (8 * (shiftModifier + bigEndianMod * ((i + 1) % 4)))) & 0xFF) << 8) |
+ ((int2 >>> (8 * (shiftModifier + bigEndianMod * ((i + 2) % 4)))) & 0xFF);
for (j = 0; j < 4; j += 1)
{
if (i * 8 + j * 6 <= outputLength)
@@ -405,19 +430,23 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* Convert an array of big-endian words to raw bytes string
*
* @private
- * @param {Array<number>} binarray Array of integers to be converted to
+ * @param {Array<number>} packed Array of integers to be converted to
* a raw bytes string representation
* @param {number} outputLength Length of output in bits
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {string} Raw bytes representation of the parameter in string
* form
*/
- function binb2bytes(binarray, outputLength)
+ function packed2bytes(packed, outputLength, bigEndianMod)
{
- var str = "", length = outputLength / 8, i, srcByte;
+ var str = "", length = outputLength / 8, i, srcByte, shiftModifier;
+
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < length; i += 1)
{
- srcByte = (binarray[i >>> 2] >>> ((3 - (i % 4)) * 8)) & 0xFF;
+ srcByte = (packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF;
str += String.fromCharCode(srcByte);
}
@@ -428,19 +457,23 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* Convert an array of big-endian words to an ArrayBuffer
*
* @private
- * @param {Array<number>} binarray Array of integers to be converted to
+ * @param {Array<number>} packed Array of integers to be converted to
* an ArrayBuffer
* @param {number} outputLength Length of output in bits
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {ArrayBuffer} Raw bytes representation of the parameter in an
* ArrayBuffer
*/
- function binb2arraybuffer(binarray, outputLength)
+ function packed2arraybuffer(packed, outputLength, bigEndianMod)
{
- var length = outputLength / 8, i, retVal = new ArrayBuffer(length);
+ var length = outputLength / 8, i, retVal = new ArrayBuffer(length), shiftModifier;
+
+ shiftModifier = (bigEndianMod === -1) ? 3 : 0;
for (i = 0; i < length; i += 1)
{
- retVal[i] = (binarray[i >>> 2] >>> ((3 - (i % 4)) * 8)) & 0xFF;
+ retVal[i] = (packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF;
}
return retVal;
@@ -499,11 +532,13 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* @param {string} format The format of the string to be converted
* @param {string} utfType The string encoding to use (UTF8, UTF16BE,
* UTF16LE)
+ * @param {number} bigEndianMod Modifier for whether hash function is
+ * big or small endian
* @return {function(string, Array<number>=, number=): {value :
* Array<number>, binLen : number}} Function that will convert an input
* string to a packed int array
*/
- function getStrConverter(format, utfType)
+ function getStrConverter(format, utfType, bigEndianMod)
{
var retVal;
@@ -525,19 +560,68 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
switch (format)
{
case "HEX":
- retVal = hex2binb;
+ /**
+ * @param {string} str String of raw bytes to be converted to binary representation
+ * @param {Array<number>} existingBin A packed int array of bytes to
+ * append the results to
+ * @param {number} existingBinLen The number of bits in the existingBin
+ * array
+ * @return {{value : Array<number>, binLen : number}} Hash list where
+ * "value" contains the output number array and "binLen" is the binary
+ * length of "value"
+ */
+ retVal = function(str, existingBin, existingBinLen)
+ {
+ return hex2packed(str, existingBin, existingBinLen, bigEndianMod);
+ };
break;
case "TEXT":
+ /**
+ * @param {string} str String of raw bytes to be converted to binary representation
+ * @param {Array<number>} existingBin A packed int array of bytes to
+ * append the results to
+ * @param {number} existingBinLen The number of bits in the existingBin
+ * array
+ * @return {{value : Array<number>, binLen : number}} Hash list where
+ * "value" contains the output number array and "binLen" is the binary
+ * length of "value"
+ */
retVal = function(str, existingBin, existingBinLen)
{
- return str2binb(str, utfType, existingBin, existingBinLen);
+ return str2packed(str, utfType, existingBin, existingBinLen, bigEndianMod);
};
break;
case "B64":
- retVal = b642binb;
+ /**
+ * @param {string} str String of raw bytes to be converted to binary representation
+ * @param {Array<number>} existingBin A packed int array of bytes to
+ * append the results to
+ * @param {number} existingBinLen The number of bits in the existingBin
+ * array
+ * @return {{value : Array<number>, binLen : number}} Hash list where
+ * "value" contains the output number array and "binLen" is the binary
+ * length of "value"
+ */
+ retVal = function(str, existingBin, existingBinLen)
+ {
+ return b642packed(str, existingBin, existingBinLen, bigEndianMod);
+ };
break;
case "BYTES":
- retVal = bytes2binb;
+ /**
+ * @param {string} str String of raw bytes to be converted to binary representation
+ * @param {Array<number>} existingBin A packed int array of bytes to
+ * append the results to
+ * @param {number} existingBinLen The number of bits in the existingBin
+ * array
+ * @return {{value : Array<number>, binLen : number}} Hash list where
+ * "value" contains the output number array and "binLen" is the binary
+ * length of "value"
+ */
+ retVal = function(str, existingBin, existingBinLen)
+ {
+ return bytes2packed(str, existingBin, existingBinLen, bigEndianMod);
+ };
break;
case "ARRAYBUFFER":
try {
@@ -545,7 +629,21 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
} catch(ignore) {
throw new Error("ARRAYBUFFER not supported by this environment");
}
- retVal = arraybuffer2binb;
+ /**
+ * @param {ArrayBuffer} arr ArrayBuffer to be converted to binary
+ * representation
+ * @param {Array<number>} existingBin A packed int array of bytes to
+ * append the results to
+ * @param {number} existingBinLen The number of bits in the existingBin
+ * array
+ * @return {{value : Array<number>, binLen : number}} Hash list where
+ * "value" contains the output number array and "binLen" is the binary
+ * length of "value"
+ */
+ retVal = function(arr, existingBin, existingBinLen)
+ {
+ return arraybuffer2packed(arr, existingBin, existingBinLen, bigEndianMod);
+ };
break;
default:
throw new Error("format must be HEX, TEXT, B64, BYTES, or ARRAYBUFFER");
@@ -567,6 +665,14 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
return (x << n) | (x >>> (32 - n));
}
+ /**
+ * The 64-bit implementation of circular rotate left
+ *
+ * @private
+ * @param {Int_64} x The 64-bit integer argument
+ * @param {number} n The number of bits to shift
+ * @return {Int_64} The x shifted circularly by n bits
+ */
function rotl_64(x, n)
{
if (n > 32)
@@ -1590,13 +1696,9 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
{
for (x = 0; x < block.length; x+=2)
{
- /* Transform pair of big-endian integers to little-endian Int_64 */
state[(x >>> 1) % 5][((x >>> 1) / 5) | 0] = xor_64(
state[(x >>> 1) % 5][((x >>> 1) / 5) | 0],
- new Int_64(
- (block[x + 1] & 0xFF) << 24 | (block[x + 1] & 0xFF00) << 8 | (block[x + 1] & 0xFF0000) >>> 8 | block[x + 1] >>> 24,
- (block[x] & 0xFF) << 24 | (block[x] & 0xFF00) << 8 | (block[x] & 0xFF0000) >>> 8 | block[x] >>> 24
- )
+ new Int_64(block[x + 1], block[x])
);
}
}
@@ -1672,11 +1774,11 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
* @param {Array<Array<Int_64>>} state The state from a previous round
* @param {number} blockSize The block size/rate of the variant in bits
* @param {number} delimiter The delimiter value for the variant
- * @param {number} ouputLen The output length for the variant in bits
+ * @param {number} outputLen The output length for the variant in bits
* @return {Array<number>} The array of integers representing the SHA-3
* hash of message
*/
- function finalizeSHA3(remainder, remainderBinLen, processedBinLen, state, blockSize, delimiter, ouputLen)
+ function finalizeSHA3(remainder, remainderBinLen, processedBinLen, state, blockSize, delimiter, outputLen)
{
var i, retVal = [], binaryStringInc = blockSize >>> 5, state_offset = 0,
remainderIntLen = remainderBinLen >>> 5, temp;
@@ -1702,20 +1804,20 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
/* Find the next "empty" byte for the 0x80 and append it via an xor */
i = remainderBinLen >>> 3;
- remainder[i >> 2] ^= delimiter << (24 - (8 * (i % 4)));
+ remainder[i >> 2] ^= delimiter << (8 * (i % 4));
- remainder[binaryStringInc - 1] ^= 0x80;
+ remainder[binaryStringInc - 1] ^= 0x80000000;
state = roundSHA3(remainder, state);
- while (retVal.length * 32 < ouputLen)
+ while (retVal.length * 32 < outputLen)
{
temp = state[state_offset % 5][(state_offset / 5) | 0];
- retVal.push((temp.lowOrder & 0xFF) << 24 | (temp.lowOrder & 0xFF00) << 8 | (temp.lowOrder & 0xFF0000) >> 8 | temp.lowOrder >>> 24);
- if (retVal.length * 32 >= ouputLen)
+ retVal.push(temp.lowOrder);
+ if (retVal.length * 32 >= outputLen)
{
break;
}
- retVal.push((temp.highOrder & 0xFF) << 24 | (temp.highOrder & 0xFF00) << 8 | (temp.highOrder & 0xFF0000) >> 8 | temp.highOrder >>> 24);
+ retVal.push(temp.highOrder);
state_offset += 1;
if (0 === ((state_offset * 64) % blockSize))
@@ -1746,14 +1848,12 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
intermediateState, converterFunc, shaVariant = variant, outputBinLen,
variantBlockSize, roundFunc, finalizeFunc, stateCloneFunc,
hmacKeySet = false, keyWithIPad = [], keyWithOPad = [], numRounds,
- updatedCalled = false, inputOptions, isSHAKE = false;
+ updatedCalled = false, inputOptions, isSHAKE = false, bigEndianMod = -1;
inputOptions = options || {};
utfType = inputOptions["encoding"] || "UTF8";
numRounds = inputOptions["numRounds"] || 1;
- converterFunc = getStrConverter(inputFormat, utfType);
-
if ((numRounds !== parseInt(numRounds, 10)) || (1 > numRounds))
{
throw new Error("numRounds must a integer >= 1");
@@ -1810,6 +1910,8 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
roundFunc = roundSHA3;
stateCloneFunc = function(state) { return cloneSHA3State(state);};
+ bigEndianMod = 1;
+
if ("SHA3-224" === shaVariant)
{
variantBlockSize = 1152;
@@ -1858,6 +1960,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
{
throw new Error("Chosen SHA variant is not supported");
}
+ converterFunc = getStrConverter(inputFormat, utfType, bigEndianMod);
intermediateState = getNewState(shaVariant);
/**
@@ -1894,7 +1997,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
keyOptions = options || {};
utfType = keyOptions["encoding"] || "UTF8";
- keyConverterFunc = getStrConverter(inputFormat, utfType);
+ keyConverterFunc = getStrConverter(inputFormat, utfType, bigEndianMod);
convertRet = keyConverterFunc(key);
keyBinLen = convertRet["binLen"];
@@ -2016,13 +2119,13 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
switch (format)
{
case "HEX":
- formatFunc = function(binarray) {return binb2hex(binarray, outputBinLen, outputOptions);};
+ formatFunc = function(binarray) {return packed2hex(binarray, outputBinLen, bigEndianMod, outputOptions);};
break;
case "B64":
- formatFunc = function(binarray) {return binb2b64(binarray, outputBinLen, outputOptions);};
+ formatFunc = function(binarray) {return packed2b64(binarray, outputBinLen, bigEndianMod, outputOptions);};
break;
case "BYTES":
- formatFunc = function(binarray) {return binb2bytes(binarray, outputBinLen);};
+ formatFunc = function(binarray) {return packed2bytes(binarray, outputBinLen, bigEndianMod);};
break;
case "ARRAYBUFFER":
try {
@@ -2030,7 +2133,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
} catch (ignore) {
throw new Error("ARRAYBUFFER not supported by this environment");
}
- formatFunc = function(binarray) {return binb2arraybuffer(binarray, outputBinLen);};
+ formatFunc = function(binarray) {return packed2arraybuffer(binarray, outputBinLen, bigEndianMod);};
break;
default:
throw new Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");
@@ -2047,7 +2150,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
*/
if (((8 & SUPPORTED_ALGS) !== 0) && (isSHAKE === true) && (outputBinLen % 32 !== 0))
{
- finalizedState[finalizedState.length - 1] &= 0xFFFFFF00 << 24 - (outputBinLen % 32);
+ finalizedState[finalizedState.length - 1] &= 0x00FFFFFF >>> 24 - (outputBinLen % 32);
}
finalizedState = finalizeFunc(finalizedState, outputBinLen, 0, getNewState(shaVariant), outputBinLen);
}
@@ -2083,13 +2186,13 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
switch (format)
{
case "HEX":
- formatFunc = function(binarray) {return binb2hex(binarray, outputBinLen, outputOptions);};
+ formatFunc = function(binarray) {return packed2hex(binarray, outputBinLen, bigEndianMod, outputOptions);};
break;
case "B64":
- formatFunc = function(binarray) {return binb2b64(binarray, outputBinLen, outputOptions);};
+ formatFunc = function(binarray) {return packed2b64(binarray, outputBinLen, bigEndianMod, outputOptions);};
break;
case "BYTES":
- formatFunc = function(binarray) {return binb2bytes(binarray, outputBinLen);};
+ formatFunc = function(binarray) {return packed2bytes(binarray, outputBinLen, bigEndianMod);};
break;
case "ARRAYBUFFER":
try {
@@ -2097,7 +2200,7 @@ var SUPPORTED_ALGS = 8 | 4 | 2 | 1;
} catch(ignore) {
throw new Error("ARRAYBUFFER not supported by this environment");
}
- formatFunc = function(binarray) {return binb2arraybuffer(binarray, outputBinLen);};
+ formatFunc = function(binarray) {return packed2arraybuffer(binarray, outputBinLen, bigEndianMod);};
break;
default:
throw new Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER");