mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-23 21:55:48 +00:00
Merge commit '8e54231a6c664154302dd72c4ce935233ae8d8de' as 'src/js/sjcl'
This commit is contained in:
187
src/js/sjcl/core/bitArray.js
Normal file
187
src/js/sjcl/core/bitArray.js
Normal file
@@ -0,0 +1,187 @@
|
||||
/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
|
||||
*
|
||||
* @author Emily Stark
|
||||
* @author Mike Hamburg
|
||||
* @author Dan Boneh
|
||||
*/
|
||||
|
||||
/** @namespace Arrays of bits, encoded as arrays of Numbers.
|
||||
*
|
||||
* @description
|
||||
* <p>
|
||||
* These objects are the currency accepted by SJCL's crypto functions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Most of our crypto primitives operate on arrays of 4-byte words internally,
|
||||
* but many of them can take arguments that are not a multiple of 4 bytes.
|
||||
* This library encodes arrays of bits (whose size need not be a multiple of 8
|
||||
* bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
|
||||
* array of words, 32 bits at a time. Since the words are double-precision
|
||||
* floating point numbers, they fit some extra data. We use this (in a private,
|
||||
* possibly-changing manner) to encode the number of bits actually present
|
||||
* in the last word of the array.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Because bitwise ops clear this out-of-band data, these arrays can be passed
|
||||
* to ciphers like AES which want arrays of words.
|
||||
* </p>
|
||||
*/
|
||||
sjcl.bitArray = {
|
||||
/**
|
||||
* Array slices in units of bits.
|
||||
* @param {bitArray} a The array to slice.
|
||||
* @param {Number} bstart The offset to the start of the slice, in bits.
|
||||
* @param {Number} bend The offset to the end of the slice, in bits. If this is undefined,
|
||||
* slice until the end of the array.
|
||||
* @return {bitArray} The requested slice.
|
||||
*/
|
||||
bitSlice: function (a, bstart, bend) {
|
||||
a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);
|
||||
return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract a number packed into a bit array.
|
||||
* @param {bitArray} a The array to slice.
|
||||
* @param {Number} bstart The offset to the start of the slice, in bits.
|
||||
* @param {Number} length The length of the number to extract.
|
||||
* @return {Number} The requested slice.
|
||||
*/
|
||||
extract: function(a, bstart, blength) {
|
||||
// FIXME: this Math.floor is not necessary at all, but for some reason
|
||||
// seems to suppress a bug in the Chromium JIT.
|
||||
var x, sh = Math.floor((-bstart-blength) & 31);
|
||||
if ((bstart + blength - 1 ^ bstart) & -32) {
|
||||
// it crosses a boundary
|
||||
x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);
|
||||
} else {
|
||||
// within a single word
|
||||
x = a[bstart/32|0] >>> sh;
|
||||
}
|
||||
return x & ((1<<blength) - 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Concatenate two bit arrays.
|
||||
* @param {bitArray} a1 The first array.
|
||||
* @param {bitArray} a2 The second array.
|
||||
* @return {bitArray} The concatenation of a1 and a2.
|
||||
*/
|
||||
concat: function (a1, a2) {
|
||||
if (a1.length === 0 || a2.length === 0) {
|
||||
return a1.concat(a2);
|
||||
}
|
||||
|
||||
var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);
|
||||
if (shift === 32) {
|
||||
return a1.concat(a2);
|
||||
} else {
|
||||
return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the length of an array of bits.
|
||||
* @param {bitArray} a The array.
|
||||
* @return {Number} The length of a, in bits.
|
||||
*/
|
||||
bitLength: function (a) {
|
||||
var l = a.length, x;
|
||||
if (l === 0) { return 0; }
|
||||
x = a[l - 1];
|
||||
return (l-1) * 32 + sjcl.bitArray.getPartial(x);
|
||||
},
|
||||
|
||||
/**
|
||||
* Truncate an array.
|
||||
* @param {bitArray} a The array.
|
||||
* @param {Number} len The length to truncate to, in bits.
|
||||
* @return {bitArray} A new array, truncated to len bits.
|
||||
*/
|
||||
clamp: function (a, len) {
|
||||
if (a.length * 32 < len) { return a; }
|
||||
a = a.slice(0, Math.ceil(len / 32));
|
||||
var l = a.length;
|
||||
len = len & 31;
|
||||
if (l > 0 && len) {
|
||||
a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
|
||||
}
|
||||
return a;
|
||||
},
|
||||
|
||||
/**
|
||||
* Make a partial word for a bit array.
|
||||
* @param {Number} len The number of bits in the word.
|
||||
* @param {Number} x The bits.
|
||||
* @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
|
||||
* @return {Number} The partial word.
|
||||
*/
|
||||
partial: function (len, x, _end) {
|
||||
if (len === 32) { return x; }
|
||||
return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of bits used by a partial word.
|
||||
* @param {Number} x The partial word.
|
||||
* @return {Number} The number of bits used by the partial word.
|
||||
*/
|
||||
getPartial: function (x) {
|
||||
return Math.round(x/0x10000000000) || 32;
|
||||
},
|
||||
|
||||
/**
|
||||
* Compare two arrays for equality in a predictable amount of time.
|
||||
* @param {bitArray} a The first array.
|
||||
* @param {bitArray} b The second array.
|
||||
* @return {boolean} true if a == b; false otherwise.
|
||||
*/
|
||||
equal: function (a, b) {
|
||||
if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
|
||||
return false;
|
||||
}
|
||||
var x = 0, i;
|
||||
for (i=0; i<a.length; i++) {
|
||||
x |= a[i]^b[i];
|
||||
}
|
||||
return (x === 0);
|
||||
},
|
||||
|
||||
/** Shift an array right.
|
||||
* @param {bitArray} a The array to shift.
|
||||
* @param {Number} shift The number of bits to shift.
|
||||
* @param {Number} [carry=0] A byte to carry in
|
||||
* @param {bitArray} [out=[]] An array to prepend to the output.
|
||||
* @private
|
||||
*/
|
||||
_shiftRight: function (a, shift, carry, out) {
|
||||
var i, last2=0, shift2;
|
||||
if (out === undefined) { out = []; }
|
||||
|
||||
for (; shift >= 32; shift -= 32) {
|
||||
out.push(carry);
|
||||
carry = 0;
|
||||
}
|
||||
if (shift === 0) {
|
||||
return out.concat(a);
|
||||
}
|
||||
|
||||
for (i=0; i<a.length; i++) {
|
||||
out.push(carry | a[i]>>>shift);
|
||||
carry = a[i] << (32-shift);
|
||||
}
|
||||
last2 = a.length ? a[a.length-1] : 0;
|
||||
shift2 = sjcl.bitArray.getPartial(last2);
|
||||
out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
|
||||
return out;
|
||||
},
|
||||
|
||||
/** xor a block of 4 words together.
|
||||
* @private
|
||||
*/
|
||||
_xor4: function(x,y) {
|
||||
return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user