[Pkg-javascript-commits] [node-sha.js] 01/237: initial

Bastien Roucariès rouca at moszumanska.debian.org
Fri May 5 09:02:50 UTC 2017


This is an automated email from the git hooks/post-receive script.

rouca pushed a commit to branch master
in repository node-sha.js.

commit c1cabff65dc811bd9c7e7530aab90db3b1080f04
Author: Dominic Tarr <dominic.tarr at gmail.com>
Date:   Tue Dec 24 19:52:15 2013 +0700

    initial
---
 .travis.yml     |   4 +
 LICENSE         |  22 +++++
 README.md       |   6 ++
 index.js        | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 package.json    |  19 ++++
 test/reverse.js |  15 +++
 test/test.js    |  22 +++++
 test/write.js   |  18 ++++
 8 files changed, 384 insertions(+)

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..895dbd3
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.8
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b799ec0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013 Dominic Tarr
+
+Permission is hereby granted, free of charge, 
+to any person obtaining a copy of this software and 
+associated documentation files (the "Software"), to 
+deal in the Software without restriction, including 
+without limitation the rights to use, copy, modify, 
+merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom 
+the Software is furnished to do so, 
+subject to the following conditions:
+
+The above copyright notice and this permission notice 
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0b41b54
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+# sha.js
+
+
+## License
+
+MIT
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..2edf9f6
--- /dev/null
+++ b/index.js
@@ -0,0 +1,278 @@
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+module.exports = Sha
+
+function Sha () {
+  
+  //|0 coearses to Int32
+  var h = this._h = new Uint32Array(5)
+  h[0] = 0x67452301|0
+  h[1] = 0xefcdab89|0
+  h[2] = 0x98badcfe|0
+  h[3] = 0x10325476|0
+  h[4] = 0xc3d2e1f0|0
+
+  this._w = new Uint32Array(80)
+  this._x = new Uint32Array(16)
+  this._len = 0
+}
+
+
+//write a string into an array, in either big or little endian mode.
+//you can create a Uint32 view on bytes with typed arrays,
+//new Uint32Array(uint8array.buffer)
+//but unfortunately, it's littleendian.
+//(as far as I can tell, am offline currently,
+// will look up docs when connected)
+
+Sha.write = write
+Sha.reverseByteOrder = reverseByteOrder
+
+
+function write (buffer, string, enc, start, from, to, LE) {
+
+  if(enc !== 'ascii')
+    throw new Error('only ascii is supported, for now')
+
+  var l = to - from
+
+  for( var i = 0; i < l; i++) {
+    //iterate in bigendian order.
+    var byte = (i&0xfffffffc)|(LE ? i%4 : 3 - i%4)
+    buffer[start + byte] = string.charCodeAt(i + from)
+  }
+
+}
+
+
+function reverseByteOrder(n) {
+  return (
+    ((n & 0xff) << 24)
+  | ((n & 0xff00) << 8)
+  | ((n & 0xff0000) >>  8)
+  | ((n & 0xff000000) >>  24)
+  )
+}
+
+Sha.prototype.update = function (data, enc) {
+  //convert to array of ints.
+  //since this is probably a string, copy it into the array,
+  //if it's over 16 words (and so, we have filled _i)
+  //then call _update(). if it's equal less, we have to wait,
+  //because this might be the last block, and so we have to wait for final()
+
+  //for encoding/decoding utf8, see here:
+  //https://github.com/chrisdickinson/bops/blob/master/typedarray/from.js#L36-L57
+  //https://github.com/chrisdickinson/to-utf8
+
+  //for now, assume ascii.
+  var start = this._l || 0
+  this._len += data.length
+  console.log('update', this._len)
+  if(data.length < 512 - start) {
+    this._l = Math.min(512, start + data.length)
+    write(this._x.buffer, data, 'ascii', start, 0, this._l)
+  }
+  return this
+}
+
+Sha.prototype.final = function () {
+  //do the sha stuff to the end of the message array.
+  console.log('final', this._len)
+  var x = this._x, len = this._len*8
+  console.log('x[len >> 5]', x[len >> 5], x[len >> 5] | (0x80 << (24 - len % 32))) | 0
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  console.log('x[len >> 5]', x[len >> 5], x[len >> 5] | (0x80 << (24 - len % 32))) | 0
+  console.log(this._x)
+  x[((len + 64 >> 9) << 4) + 15] = len;
+  console.log(toHex(this._x))
+  this._update()
+  return this
+}
+
+function toHex (buf) {
+  buf = buf.buffer || buf
+  var s = ''
+  for(var i = 0; i < buf.byteLength; i++)
+    s += ((buf[i]>>4).toString(16)) + ((buf[i]&0xf).toString(16))
+  return s
+
+}
+
+Sha.prototype.digest = function () {
+  this.final()
+
+  var h = this._h
+
+  //reverse byte order, so that the individual bytes are in correct order.
+  h[0] = reverseByteOrder(h[0])
+  h[1] = reverseByteOrder(h[1])
+  h[2] = reverseByteOrder(h[2])
+  h[3] = reverseByteOrder(h[3])
+  h[4] = reverseByteOrder(h[4])
+
+  return toHex(this._h.buffer)
+}
+
+// assume that array is a Uint32Array with length=16,
+// and that if it is the last block, it already has the length and the 1 bit appended.
+
+var A = 0
+var B = 1
+var C = 2
+var D = 3
+var E = 4
+
+Sha.prototype._update = function (array) {
+
+  var h = this._h
+  var a = _a = h[A]
+  var b = _b = h[B]
+  var c = _c = h[C]
+  var d = _d = h[D]
+  var e = _e = h[E]
+
+  var i = 0
+  var w = this._w
+  var x = this._x
+console.log('INIT-sha1', toHex(new Int32Array([a, b, c, d, e])))
+
+  for(var j = 0; j < 80; j++)
+  {
+    if(j < 16) w[j] = x[i + j];
+    else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+    var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+                     safe_add(safe_add(e, w[j]), sha1_kt(j)));
+    e = d;
+    d = c;
+    c = rol(b, 30);
+    b = a;
+    a = t;
+  }
+  console.log('ROUND-sha1', toHex(new Int32Array([a, b, c, d, e])))
+
+  h[A] = safe_add(a, _a);
+  h[B] = safe_add(b, _b);
+  h[C] = safe_add(c, _c);
+  h[D] = safe_add(d, _d);
+  h[E] = safe_add(e, _e);
+
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  x[((len + 64 >> 9) << 4) + 15] = len;
+
+  console.log('INIT-core', toHex(x))
+
+  var w = Array(80);
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+  var e = -1009589776;
+
+  console.log('INIT', toHex(new Int32Array([a, b, c, d, e])))
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+    var olde = e;
+
+    for(var j = 0; j < 80; j++)
+    {
+      if(j < 16) w[j] = x[i + j];
+      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
+      e = d;
+      d = c;
+      c = rol(b, 30);
+      b = a;
+      a = t;
+    }
+    console.log('ROUND-core', toHex(new Int32Array([a, b, c, d, e])))
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+    e = safe_add(e, olde);
+  }
+
+//  return [a, b, c, d, e]
+  return new Int32Array([a, b, c, d, e]);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+  if(t < 20) return (b & c) | ((~b) & d);
+  if(t < 40) return b ^ c ^ d;
+  if(t < 60) return (b & c) | (b & d) | (c & d);
+  return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
+         (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+if(!module.parent) {
+  var crypto = require('crypto')
+  var _H = new Sha().update('hello there.', 'ascii').digest('hex')
+  var H2 = crypto.createHash('sha1').update('hello there.', 'ascii').digest('hex')
+  console.error('SHA1', _H)
+  var a = new Uint32Array(16)
+
+  write(a.buffer, 'hello there.', 'ascii', 0, 0, 12)
+  console.error('buff-xxxx', toHex(a.buffer))
+  var H = toHex(core_sha1(a, 12*8))
+  console.error('CORE', H)
+  console.error('OSSL', H2)
+
+  if(H === _H && H === H2)
+    console.log('SUCCESS!')
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0ea299d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "sha.js",
+  "description": "streaming sha1 hash in pure javascript",
+  "version": "0.0.0",
+  "homepage": "https://github.com/dominictarr/sha.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/dominictarr/sha.js.git"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tape": "~2.3.2"
+  },
+  "scripts": {
+    "test": "set -e; for t in test/*.js; do node $t; done"
+  },
+  "author": "Dominic Tarr <dominic.tarr at gmail.com> (dominictarr.com)",
+  "license": "MIT"
+}
\ No newline at end of file
diff --git a/test/reverse.js b/test/reverse.js
new file mode 100644
index 0000000..c1d662f
--- /dev/null
+++ b/test/reverse.js
@@ -0,0 +1,15 @@
+
+
+var rotateByteOrder = require('../').rotateByteOrder
+
+var tape = require('tape')
+
+tape('rotate byte order', function (t) {
+
+  var r = rotateByteOrder(0x12345678)
+  console.log(r.toString(16))
+  t.equal(r, 0x78563412, 'reverse bytes')
+  t.equal(rotateByteOrder(r), 0x12345678, 'reverse again')
+  t.end()
+})
+
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..20e4040
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,22 @@
+
+var crypto = require('crypto')
+var tape   = require('tape')
+var Sha1   = require('../')
+
+var inputs = [
+ ['', 'ascii'],
+// ['abc', 'ascii'],
+// ['123', 'ascii']
+]
+
+tape("hash is the same as node's crypto", function (t) {
+
+  inputs.forEach(function (v) {
+    var a = new Sha1().update(v[0], v[1]).digest('hex')
+    var e = crypto.createHash('sha1').update(v[0], v[1]).digest('hex')
+    t.equal(a, e)
+  })
+
+  t.end()
+
+})
diff --git a/test/write.js b/test/write.js
new file mode 100644
index 0000000..43d41d1
--- /dev/null
+++ b/test/write.js
@@ -0,0 +1,18 @@
+
+var tape = require('tape')
+var write = require('../').write
+
+tape('supports bigendian', function (t) {
+
+  var actual = new Uint8Array(12)
+
+  var expected = new Uint8Array([108, 108, 101, 104, 104, 116, 32, 111, 46, 101, 114, 101])
+
+  write(actual, 'hello there.', 'ascii', 0, 0, 12)
+
+  console.log(actual.buffer)
+  console.log(expected.buffer)
+
+  t.deepEqual(expected, actual)
+  t.end()
+})

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-sha.js.git



More information about the Pkg-javascript-commits mailing list