| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /** @fileOverview Javascript SHA-1 implementation.
- *
- * Based on the implementation in RFC 3174, method 1, and on the SJCL
- * SHA-256 implementation.
- *
- * @author Quinn Slack
- */
- /**
- * Context for a SHA-1 operation in progress.
- * @constructor
- * @class Secure Hash Algorithm, 160 bits.
- */
- sjcl.hash.sha1 = function (hash) {
- if (hash) {
- this._h = hash._h.slice(0);
- this._buffer = hash._buffer.slice(0);
- this._length = hash._length;
- } else {
- this.reset();
- }
- };
- /**
- * Hash a string or an array of words.
- * @static
- * @param {bitArray|String} data the data to hash.
- * @return {bitArray} The hash value, an array of 5 big-endian words.
- */
- sjcl.hash.sha1.hash = function (data) {
- return (new sjcl.hash.sha1()).update(data).finalize();
- };
- sjcl.hash.sha1.prototype = {
- /**
- * The hash's block size, in bits.
- * @constant
- */
- blockSize: 512,
-
- /**
- * Reset the hash state.
- * @return this
- */
- reset:function () {
- this._h = this._init.slice(0);
- this._buffer = [];
- this._length = 0;
- return this;
- },
-
- /**
- * Input several words to the hash.
- * @param {bitArray|String} data the data to hash.
- * @return this
- */
- update: function (data) {
- if (typeof data === "string") {
- data = sjcl.codec.utf8String.toBits(data);
- }
- var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
- ol = this._length,
- nl = this._length = ol + sjcl.bitArray.bitLength(data);
- for (i = this.blockSize+ol & -this.blockSize; i <= nl;
- i+= this.blockSize) {
- this._block(b.splice(0,16));
- }
- return this;
- },
-
- /**
- * Complete hashing and output the hash value.
- * @return {bitArray} The hash value, an array of 5 big-endian words. TODO
- */
- finalize:function () {
- var i, b = this._buffer, h = this._h;
- // Round out and push the buffer
- b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1,1)]);
- // Round out the buffer to a multiple of 16 words, less the 2 length words.
- for (i = b.length + 2; i & 15; i++) {
- b.push(0);
- }
- // append the length
- b.push(Math.floor(this._length / 0x100000000));
- b.push(this._length | 0);
- while (b.length) {
- this._block(b.splice(0,16));
- }
- this.reset();
- return h;
- },
- /**
- * The SHA-1 initialization vector.
- * @private
- */
- _init:[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],
- /**
- * The SHA-1 hash key.
- * @private
- */
- _key:[0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6],
- /**
- * The SHA-1 logical functions f(0), f(1), ..., f(79).
- * @private
- */
- _f:function(t, b, c, d) {
- if (t <= 19) {
- return (b & c) | (~b & d);
- } else if (t <= 39) {
- return b ^ c ^ d;
- } else if (t <= 59) {
- return (b & c) | (b & d) | (c & d);
- } else if (t <= 79) {
- return b ^ c ^ d;
- }
- },
- /**
- * Circular left-shift operator.
- * @private
- */
- _S:function(n, x) {
- return (x << n) | (x >>> 32-n);
- },
-
- /**
- * Perform one cycle of SHA-1.
- * @param {bitArray} words one block of words.
- * @private
- */
- _block:function (words) {
- var t, tmp, a, b, c, d, e,
- w = words.slice(0),
- h = this._h,
- k = this._key;
-
- a = h[0]; b = h[1]; c = h[2]; d = h[3]; e = h[4];
- for (t=0; t<=79; t++) {
- if (t >= 16) {
- w[t] = this._S(1, w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]);
- }
- tmp = (this._S(5, a) + this._f(t, b, c, d) + e + w[t] +
- this._key[Math.floor(t/20)]) | 0;
- e = d;
- d = c;
- c = this._S(30, b);
- b = a;
- a = tmp;
- }
- h[0] = (h[0]+a) |0;
- h[1] = (h[1]+b) |0;
- h[2] = (h[2]+c) |0;
- h[3] = (h[3]+d) |0;
- h[4] = (h[4]+e) |0;
- }
- };
|