sha1.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /** @fileOverview Javascript SHA-1 implementation.
  2. *
  3. * Based on the implementation in RFC 3174, method 1, and on the SJCL
  4. * SHA-256 implementation.
  5. *
  6. * @author Quinn Slack
  7. */
  8. /**
  9. * Context for a SHA-1 operation in progress.
  10. * @constructor
  11. * @class Secure Hash Algorithm, 160 bits.
  12. */
  13. sjcl.hash.sha1 = function (hash) {
  14. if (hash) {
  15. this._h = hash._h.slice(0);
  16. this._buffer = hash._buffer.slice(0);
  17. this._length = hash._length;
  18. } else {
  19. this.reset();
  20. }
  21. };
  22. /**
  23. * Hash a string or an array of words.
  24. * @static
  25. * @param {bitArray|String} data the data to hash.
  26. * @return {bitArray} The hash value, an array of 5 big-endian words.
  27. */
  28. sjcl.hash.sha1.hash = function (data) {
  29. return (new sjcl.hash.sha1()).update(data).finalize();
  30. };
  31. sjcl.hash.sha1.prototype = {
  32. /**
  33. * The hash's block size, in bits.
  34. * @constant
  35. */
  36. blockSize: 512,
  37. /**
  38. * Reset the hash state.
  39. * @return this
  40. */
  41. reset:function () {
  42. this._h = this._init.slice(0);
  43. this._buffer = [];
  44. this._length = 0;
  45. return this;
  46. },
  47. /**
  48. * Input several words to the hash.
  49. * @param {bitArray|String} data the data to hash.
  50. * @return this
  51. */
  52. update: function (data) {
  53. if (typeof data === "string") {
  54. data = sjcl.codec.utf8String.toBits(data);
  55. }
  56. var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
  57. ol = this._length,
  58. nl = this._length = ol + sjcl.bitArray.bitLength(data);
  59. for (i = this.blockSize+ol & -this.blockSize; i <= nl;
  60. i+= this.blockSize) {
  61. this._block(b.splice(0,16));
  62. }
  63. return this;
  64. },
  65. /**
  66. * Complete hashing and output the hash value.
  67. * @return {bitArray} The hash value, an array of 5 big-endian words. TODO
  68. */
  69. finalize:function () {
  70. var i, b = this._buffer, h = this._h;
  71. // Round out and push the buffer
  72. b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);
  73. // Round out the buffer to a multiple of 16 words, less the 2 length words.
  74. for (i = b.length + 2; i & 15; i++) {
  75. b.push(0);
  76. }
  77. // append the length
  78. b.push(Math.floor(this._length / 0x100000000));
  79. b.push(this._length | 0);
  80. while (b.length) {
  81. this._block(b.splice(0,16));
  82. }
  83. this.reset();
  84. return h;
  85. },
  86. /**
  87. * The SHA-1 initialization vector.
  88. * @private
  89. */
  90. _init:[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],
  91. /**
  92. * The SHA-1 hash key.
  93. * @private
  94. */
  95. _key:[0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6],
  96. /**
  97. * The SHA-1 logical functions f(0), f(1), ..., f(79).
  98. * @private
  99. */
  100. _f:function(t, b, c, d) {
  101. if (t <= 19) {
  102. return (b & c) | (~b & d);
  103. } else if (t <= 39) {
  104. return b ^ c ^ d;
  105. } else if (t <= 59) {
  106. return (b & c) | (b & d) | (c & d);
  107. } else if (t <= 79) {
  108. return b ^ c ^ d;
  109. }
  110. },
  111. /**
  112. * Circular left-shift operator.
  113. * @private
  114. */
  115. _S:function(n, x) {
  116. return (x << n) | (x >>> 32-n);
  117. },
  118. /**
  119. * Perform one cycle of SHA-1.
  120. * @param {bitArray} words one block of words.
  121. * @private
  122. */
  123. _block:function (words) {
  124. var t, tmp, a, b, c, d, e,
  125. w = words.slice(0),
  126. h = this._h,
  127. k = this._key;
  128. a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4];
  129. for (t=0; t<=79; t++) {
  130. if (t >= 16) {
  131. w[t] = this._S(1, w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]);
  132. }
  133. tmp = (this._S(5, a) + this._f(t, b, c, d) + e + w[t] +
  134. this._key[Math.floor(t/20)]) | 0;
  135. e = d;
  136. d = c;
  137. c = this._S(30, b);
  138. b = a;
  139. a = tmp;
  140. }
  141. h[0] = (h[0]+a) |0;
  142. h[1] = (h[1]+b) |0;
  143. h[2] = (h[2]+c) |0;
  144. h[3] = (h[3]+d) |0;
  145. h[4] = (h[4]+e) |0;
  146. }
  147. };