bitArray.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /** @fileOverview Arrays of bits, encoded as arrays of Numbers.
  2. *
  3. * @author Emily Stark
  4. * @author Mike Hamburg
  5. * @author Dan Boneh
  6. */
  7. /** @namespace Arrays of bits, encoded as arrays of Numbers.
  8. *
  9. * @description
  10. * <p>
  11. * These objects are the currency accepted by SJCL's crypto functions.
  12. * </p>
  13. *
  14. * <p>
  15. * Most of our crypto primitives operate on arrays of 4-byte words internally,
  16. * but many of them can take arguments that are not a multiple of 4 bytes.
  17. * This library encodes arrays of bits (whose size need not be a multiple of 8
  18. * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
  19. * array of words, 32 bits at a time. Since the words are double-precision
  20. * floating point numbers, they fit some extra data. We use this (in a private,
  21. * possibly-changing manner) to encode the number of bits actually present
  22. * in the last word of the array.
  23. * </p>
  24. *
  25. * <p>
  26. * Because bitwise ops clear this out-of-band data, these arrays can be passed
  27. * to ciphers like AES which want arrays of words.
  28. * </p>
  29. */
  30. sjcl.bitArray = {
  31. /**
  32. * Array slices in units of bits.
  33. * @param {bitArray} a The array to slice.
  34. * @param {Number} bstart The offset to the start of the slice, in bits.
  35. * @param {Number} bend The offset to the end of the slice, in bits. If this is undefined,
  36. * slice until the end of the array.
  37. * @return {bitArray} The requested slice.
  38. */
  39. bitSlice: function (a, bstart, bend) {
  40. a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);
  41. return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);
  42. },
  43. /**
  44. * Extract a number packed into a bit array.
  45. * @param {bitArray} a The array to slice.
  46. * @param {Number} bstart The offset to the start of the slice, in bits.
  47. * @param {Number} length The length of the number to extract.
  48. * @return {Number} The requested slice.
  49. */
  50. extract: function(a, bstart, blength) {
  51. // FIXME: this Math.floor is not necessary at all, but for some reason
  52. // seems to suppress a bug in the Chromium JIT.
  53. var x, sh = Math.floor((-bstart-blength) & 31);
  54. if ((bstart + blength - 1 ^ bstart) & -32) {
  55. // it crosses a boundary
  56. x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);
  57. } else {
  58. // within a single word
  59. x = a[bstart/32|0] >>> sh;
  60. }
  61. return x & ((1<<blength) - 1);
  62. },
  63. /**
  64. * Concatenate two bit arrays.
  65. * @param {bitArray} a1 The first array.
  66. * @param {bitArray} a2 The second array.
  67. * @return {bitArray} The concatenation of a1 and a2.
  68. */
  69. concat: function (a1, a2) {
  70. if (a1.length === 0 || a2.length === 0) {
  71. return a1.concat(a2);
  72. }
  73. var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);
  74. if (shift === 32) {
  75. return a1.concat(a2);
  76. } else {
  77. return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));
  78. }
  79. },
  80. /**
  81. * Find the length of an array of bits.
  82. * @param {bitArray} a The array.
  83. * @return {Number} The length of a, in bits.
  84. */
  85. bitLength: function (a) {
  86. var l = a.length, x;
  87. if (l === 0) { return 0; }
  88. x = a[l - 1];
  89. return (l-1) * 32 + sjcl.bitArray.getPartial(x);
  90. },
  91. /**
  92. * Truncate an array.
  93. * @param {bitArray} a The array.
  94. * @param {Number} len The length to truncate to, in bits.
  95. * @return {bitArray} A new array, truncated to len bits.
  96. */
  97. clamp: function (a, len) {
  98. if (a.length * 32 < len) { return a; }
  99. a = a.slice(0, Math.ceil(len / 32));
  100. var l = a.length;
  101. len = len & 31;
  102. if (l > 0 && len) {
  103. a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
  104. }
  105. return a;
  106. },
  107. /**
  108. * Make a partial word for a bit array.
  109. * @param {Number} len The number of bits in the word.
  110. * @param {Number} x The bits.
  111. * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
  112. * @return {Number} The partial word.
  113. */
  114. partial: function (len, x, _end) {
  115. if (len === 32) { return x; }
  116. return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
  117. },
  118. /**
  119. * Get the number of bits used by a partial word.
  120. * @param {Number} x The partial word.
  121. * @return {Number} The number of bits used by the partial word.
  122. */
  123. getPartial: function (x) {
  124. return Math.round(x/0x10000000000) || 32;
  125. },
  126. /**
  127. * Compare two arrays for equality in a predictable amount of time.
  128. * @param {bitArray} a The first array.
  129. * @param {bitArray} b The second array.
  130. * @return {boolean} true if a == b; false otherwise.
  131. */
  132. equal: function (a, b) {
  133. if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
  134. return false;
  135. }
  136. var x = 0, i;
  137. for (i=0; i<a.length; i++) {
  138. x |= a[i]^b[i];
  139. }
  140. return (x === 0);
  141. },
  142. /** Shift an array right.
  143. * @param {bitArray} a The array to shift.
  144. * @param {Number} shift The number of bits to shift.
  145. * @param {Number} [carry=0] A byte to carry in
  146. * @param {bitArray} [out=[]] An array to prepend to the output.
  147. * @private
  148. */
  149. _shiftRight: function (a, shift, carry, out) {
  150. var i, last2=0, shift2;
  151. if (out === undefined) { out = []; }
  152. for (; shift >= 32; shift -= 32) {
  153. out.push(carry);
  154. carry = 0;
  155. }
  156. if (shift === 0) {
  157. return out.concat(a);
  158. }
  159. for (i=0; i<a.length; i++) {
  160. out.push(carry | a[i]>>>shift);
  161. carry = a[i] << (32-shift);
  162. }
  163. last2 = a.length ? a[a.length-1] : 0;
  164. shift2 = sjcl.bitArray.getPartial(last2);
  165. out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
  166. return out;
  167. },
  168. /** xor a block of 4 words together.
  169. * @private
  170. */
  171. _xor4: function(x,y) {
  172. return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
  173. }
  174. };