bitArray.js 4.9 KB

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