bitArray.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. var x, sh = (-bstart-blength) & 31;
  52. if ((bstart + blength - 1 ^ bstart) & -32) {
  53. // it crosses a boundary
  54. x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh);
  55. } else {
  56. x = a[bstart/32|0] >>> sh;
  57. }
  58. return x & ((1<<blength) - 1);
  59. },
  60. /**
  61. * Concatenate two bit arrays.
  62. * @param {bitArray} a1 The first array.
  63. * @param {bitArray} a2 The second array.
  64. * @return {bitArray} The concatenation of a1 and a2.
  65. */
  66. concat: function (a1, a2) {
  67. if (a1.length === 0 || a2.length === 0) {
  68. return a1.concat(a2);
  69. }
  70. var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);
  71. if (shift === 32) {
  72. return a1.concat(a2);
  73. } else {
  74. return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));
  75. }
  76. },
  77. /**
  78. * Find the length of an array of bits.
  79. * @param {bitArray} a The array.
  80. * @return {Number} The length of a, in bits.
  81. */
  82. bitLength: function (a) {
  83. var l = a.length, x;
  84. if (l === 0) { return 0; }
  85. x = a[l - 1];
  86. return (l-1) * 32 + sjcl.bitArray.getPartial(x);
  87. },
  88. /**
  89. * Truncate an array.
  90. * @param {bitArray} a The array.
  91. * @param {Number} len The length to truncate to, in bits.
  92. * @return {bitArray} A new array, truncated to len bits.
  93. */
  94. clamp: function (a, len) {
  95. if (a.length * 32 < len) { return a; }
  96. a = a.slice(0, Math.ceil(len / 32));
  97. var l = a.length;
  98. len = len & 31;
  99. if (l > 0 && len) {
  100. a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
  101. }
  102. return a;
  103. },
  104. /**
  105. * Make a partial word for a bit array.
  106. * @param {Number} len The number of bits in the word.
  107. * @param {Number} x The bits.
  108. * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
  109. * @return {Number} The partial word.
  110. */
  111. partial: function (len, x, _end) {
  112. if (len === 32) { return x; }
  113. return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
  114. },
  115. /**
  116. * Get the number of bits used by a partial word.
  117. * @param {Number} x The partial word.
  118. * @return {Number} The number of bits used by the partial word.
  119. */
  120. getPartial: function (x) {
  121. return Math.round(x/0x10000000000) || 32;
  122. },
  123. /**
  124. * Compare two arrays for equality in a predictable amount of time.
  125. * @param {bitArray} a The first array.
  126. * @param {bitArray} b The second array.
  127. * @return {boolean} true if a == b; false otherwise.
  128. */
  129. equal: function (a, b) {
  130. if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
  131. return false;
  132. }
  133. var x = 0, i;
  134. for (i=0; i<a.length; i++) {
  135. x |= a[i]^b[i];
  136. }
  137. return (x === 0);
  138. },
  139. /** Shift an array right.
  140. * @param {bitArray} a The array to shift.
  141. * @param {Number} shift The number of bits to shift.
  142. * @param {Number} [carry=0] A byte to carry in
  143. * @param {bitArray} [out=[]] An array to prepend to the output.
  144. * @private
  145. */
  146. _shiftRight: function (a, shift, carry, out) {
  147. var i, last2=0, shift2;
  148. if (out === undefined) { out = []; }
  149. for (; shift >= 32; shift -= 32) {
  150. out.push(carry);
  151. carry = 0;
  152. }
  153. if (shift === 0) {
  154. return out.concat(a);
  155. }
  156. for (i=0; i<a.length; i++) {
  157. out.push(carry | a[i]>>>shift);
  158. carry = a[i] << (32-shift);
  159. }
  160. last2 = a.length ? a[a.length-1] : 0;
  161. shift2 = sjcl.bitArray.getPartial(last2);
  162. out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
  163. return out;
  164. },
  165. /** xor a block of 4 words together.
  166. * @private
  167. */
  168. _xor4: function(x,y) {
  169. return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
  170. }
  171. };