[Pkg-javascript-commits] [node-hash.js] 01/29: initial
Bastien Roucariès
rouca at moszumanska.debian.org
Thu Apr 20 19:30:36 UTC 2017
This is an automated email from the git hooks/post-receive script.
rouca pushed a commit to branch master
in repository node-hash.js.
commit 8596aa44e6c573a8631499c58ca6837e3a21c985
Author: Fedor Indutny <fedor at indutny.com>
Date: Sat Apr 26 01:12:00 2014 +0400
initial
---
.gitignore | 2 +
.travis.yml | 8 ++
README.md | 28 +++++++
lib/hash.js | 10 +++
lib/hash/hash.js | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/hash/hmac.js | 47 ++++++++++++
lib/hash/utils.js | 106 ++++++++++++++++++++++++++
package.json | 28 +++++++
test/hash-test.js | 64 ++++++++++++++++
test/hmac-test.js | 59 +++++++++++++++
10 files changed, 574 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1ca9571
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..8fe40db
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+ - "0.8"
+ - "0.10"
+ - "0.11"
+branches:
+ only:
+ - master
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..63107cb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# hash.js [![Build Status](https://secure.travis-ci.org/indutny/hash.js.png)](http://travis-ci.org/indutny/hash.js)
+
+Just a bike-shed.
+
+#### LICENSE
+
+This software is licensed under the MIT License.
+
+Copyright Fedor Indutny, 2014.
+
+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/lib/hash.js b/lib/hash.js
new file mode 100644
index 0000000..b2479f8
--- /dev/null
+++ b/lib/hash.js
@@ -0,0 +1,10 @@
+var hash = exports;
+
+hash.utils = require('./hash/utils');
+hash.hash = require('./hash/hash');
+hash.hmac = require('./hash/hmac');
+
+// Proxy hash functions to the main object
+Object.keys(hash.hash).forEach(function(name) {
+ hash[name] = hash.hash[name];
+});
diff --git a/lib/hash/hash.js b/lib/hash/hash.js
new file mode 100644
index 0000000..e616f88
--- /dev/null
+++ b/lib/hash/hash.js
@@ -0,0 +1,222 @@
+var assert = require('assert');
+var util = require('util');
+var hash = require('../hash');
+var utils = hash.utils;
+
+var sha256_K = [
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+];
+
+function SHA256() {
+ if (!(this instanceof SHA256))
+ return new SHA256();
+
+ this.h = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
+ this.k = sha256_K;
+ this.pending = null;
+ this.pendingTotal = 0;
+
+ this.blockSize = this.constructor.blockSize;
+ this.outSize = this.constructor.outSize;
+ this.hmacStrength = this.constructor.hmacStrength;
+}
+exports.sha256 = SHA256;
+
+SHA256.blockSize = 512;
+SHA256.outSize = 256;
+SHA256.hmacStrength = 192;
+
+SHA256.prototype.update = function update(msg, enc) {
+ // Convert message to array, pad it, and join into 32bit blocks
+ msg = utils.toArray(msg, enc);
+ if (!this.pending)
+ this.pending = msg;
+ else
+ this.pending = this.pending.concat(msg);
+ this.pendingTotal += msg.length;
+
+ // Try updating
+ this._update();
+
+ return this;
+};
+
+SHA256.prototype._update = function _update() {
+ var msg = this.pending;
+ if (msg.length < this.blockSize / 8)
+ return;
+
+ // Process pending data in blocks
+ var r = msg.length % (this.blockSize / 8);
+ this.pending = msg.slice(msg.length - r, msg.length);
+ if (this.pending.length === 0)
+ this.pending = null;
+
+ msg = utils.join32(msg.slice(0, msg.length - r));
+ assert.equal(msg.length % 16, 0);
+
+ var W = new Array(64);
+ for (var off = 0; off < msg.length; off += 16) {
+ for (var i = 0; i < 16; i++)
+ W[i] = msg[i + off];
+ for (; i < W.length; i++)
+ W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);
+
+ var a = this.h[0];
+ var b = this.h[1];
+ var c = this.h[2];
+ var d = this.h[3];
+ var e = this.h[4];
+ var f = this.h[5];
+ var g = this.h[6];
+ var h = this.h[7];
+
+ assert.equal(this.k.length, W.length);
+ for (var i = 0; i < W.length; i++) {
+ var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
+ var T2 = sum32(s0_256(a), maj32(a, b, c));
+ h = g;
+ g = f;
+ f = e;
+ e = sum32(d, T1);
+ d = c;
+ c = b;
+ b = a;
+ a = sum32(T1, T2);
+ }
+
+ this.h[0] = sum32(this.h[0], a);
+ this.h[1] = sum32(this.h[1], b);
+ this.h[2] = sum32(this.h[2], c);
+ this.h[3] = sum32(this.h[3], d);
+ this.h[4] = sum32(this.h[4], e);
+ this.h[5] = sum32(this.h[5], f);
+ this.h[6] = sum32(this.h[6], g);
+ this.h[7] = sum32(this.h[7], h);
+ }
+};
+
+SHA256.prototype.digest = function digest(enc) {
+ if (this.pending !== null)
+ this.update(pad(this.pendingTotal, this.blockSize / 8));
+ assert(this.pending === null);
+
+ return this._digest(enc);
+};
+
+SHA256.prototype._digest = function digest(enc) {
+ if (enc === 'hex')
+ return utils.toHex32(this.h);
+ else
+ return utils.split32(this.h);
+};
+
+function SHA224() {
+ if (!(this instanceof SHA224))
+ return new SHA224();
+
+ SHA256.call(this);
+ this.h = [ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
+}
+util.inherits(SHA224, SHA256);
+exports.sha224 = SHA224;
+
+SHA224.blockSize = 512;
+SHA224.outSize = 224;
+SHA224.hmacStrength = 192;
+
+SHA224.prototype._digest = function digest(enc) {
+ // Just truncate output
+ if (enc === 'hex')
+ return utils.toHex32(this.h.slice(0, 7));
+ else
+ return utils.split32(this.h.slice(0, 7));
+};
+
+function pad(len, bytes) {
+ var k = bytes - ((len + 8) % bytes);
+ var res = new Array(k + 8);
+ res[0] = 0x80;
+ for (var i = 1; i < k + 4; i++)
+ res[i] = 0;
+
+ // Append big-endian length
+ len <<= 3;
+ res[i++] = (len >>> 24) & 0xff;
+ res[i++] = (len >>> 16) & 0xff;
+ res[i++] = (len >>> 8) & 0xff;
+ res[i++] = len & 0xff;
+
+ return res;
+}
+
+
+function rotr32(w, b) {
+ return (w >>> b) | (w << (32 - b));
+}
+
+function rotl32(w, b) {
+ return (w << b) | (w >>> (32 - b));
+}
+
+function sum32(a, b) {
+ var r = (a + b) & 0xffffffff;
+ if (r < 0)
+ r += 0x100000000;
+ return r;
+}
+
+function sum32_4(a, b, c, d) {
+ var r = (a + b + c + d) & 0xffffffff;
+ if (r < 0)
+ r += 0x100000000;
+ return r;
+}
+
+function sum32_5(a, b, c, d, e) {
+ var r = (a + b + c + d + e) & 0xffffffff;
+ if (r < 0)
+ r += 0x100000000;
+ return r;
+}
+
+function ch32(x, y, z) {
+ return (x & y) ^ ((~x) & z);
+}
+
+function maj32(x, y, z) {
+ return (x & y) ^ (x & z) ^ (y & z);
+}
+
+function s0_256(x) {
+ return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
+}
+
+function s1_256(x) {
+ return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
+}
+
+function g0_256(x) {
+ return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
+}
+
+function g1_256(x) {
+ return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
+}
diff --git a/lib/hash/hmac.js b/lib/hash/hmac.js
new file mode 100644
index 0000000..ebffd3f
--- /dev/null
+++ b/lib/hash/hmac.js
@@ -0,0 +1,47 @@
+var hmac = exports;
+
+var assert = require('assert');
+var hash = require('../hash');
+var utils = hash.utils;
+
+function Hmac(hash, key, enc) {
+ if (!(this instanceof Hmac))
+ return new Hmac(hash, key, enc);
+ this.Hash = hash;
+ this.blockSize = hash.blockSize / 8;
+ this.outSize = hash.outSize / 8;
+ this._init(utils.toArray(key, enc));
+}
+module.exports = Hmac;
+
+Hmac.prototype._init = function init(key) {
+ // Shorten key, if needed
+ if (key.length > this.blockSize)
+ key = new this.Hash().update(key).digest();
+ assert(key.length <= this.blockSize);
+
+ // Add padding to key
+ for (var i = key.length; i < this.blockSize; i++)
+ key.push(0);
+
+ var okey = key.slice();
+ for (var i = 0; i < key.length; i++) {
+ key[i] ^= 0x36;
+ okey[i] ^= 0x5c;
+ }
+
+ this.hash = {
+ inner: new this.Hash().update(key),
+ outer: new this.Hash().update(okey)
+ };
+};
+
+Hmac.prototype.update = function update(msg, enc) {
+ this.hash.inner.update(msg, enc);
+ return this;
+};
+
+Hmac.prototype.digest = function digest(enc) {
+ this.hash.outer.update(this.hash.inner.digest());
+ return this.hash.outer.digest(enc);
+};
diff --git a/lib/hash/utils.js b/lib/hash/utils.js
new file mode 100644
index 0000000..bcf49f9
--- /dev/null
+++ b/lib/hash/utils.js
@@ -0,0 +1,106 @@
+var assert = require('assert');
+
+var utils = exports;
+
+function toArray(msg, enc) {
+ if (Array.isArray(msg))
+ return msg.slice();
+ if (!msg)
+ return [];
+ var res = [];
+ if (typeof msg === 'string') {
+ if (!enc) {
+ for (var i = 0; i < msg.length; i++) {
+ var c = msg.charCodeAt(i);
+ var hi = c >> 8;
+ var lo = c & 0xff;
+ if (hi)
+ res.push(hi, lo);
+ else
+ res.push(lo);
+ }
+ } else if (enc === 'hex') {
+ msg = msg.replace(/[^a-z0-9]+/ig, '');
+ if (msg.length % 2 != 0)
+ msg = '0' + msg;
+ for (var i = 0; i < msg.length; i += 2)
+ res.push(parseInt(msg[i] + msg[i + 1], 16));
+ }
+ } else {
+ for (var i = 0; i < msg.length; i++)
+ res[i] = msg[i] | 0;
+ }
+ return res;
+}
+utils.toArray = toArray;
+
+function toHex(msg) {
+ var res = '';
+ for (var i = 0; i < msg.length; i++)
+ res += zero2(msg[i].toString(16));
+ return res;
+}
+utils.toHex = toHex;
+
+function toHex32(msg) {
+ var res = '';
+ for (var i = 0; i < msg.length; i++)
+ res += zero8(msg[i].toString(16));
+ return res;
+}
+utils.toHex32 = toHex32;
+
+function zero2(word) {
+ if (word.length === 1)
+ return '0' + word;
+ else
+ return word;
+}
+utils.zero2 = zero2;
+
+function zero8(word) {
+ if (word.length === 7)
+ return '0' + word;
+ else if (word.length === 6)
+ return '00' + word;
+ else if (word.length === 5)
+ return '000' + word;
+ else if (word.length === 4)
+ return '0000' + word;
+ else if (word.length === 3)
+ return '00000' + word;
+ else if (word.length === 2)
+ return '000000' + word;
+ else if (word.length === 1)
+ return '0000000' + word;
+ else
+ return word;
+}
+utils.zero8 = zero8;
+
+function join32(msg) {
+ assert.equal(msg.length % 4, 0);
+ var res = new Array(msg.length / 4);
+ for (var i = 0, k = 0; i < res.length; i++, k += 4) {
+ var w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) |
+ msg[k + 3];
+ if (w < 0)
+ w += 0x100000000;
+ res[i] = w;
+ }
+ return res;
+}
+utils.join32 = join32;
+
+function split32(msg) {
+ var res = new Array(msg.length * 4);
+ for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
+ var m = msg[i];
+ res[k] = m >>> 24;
+ res[k + 1] = (m >>> 16) & 0xff;
+ res[k + 2] = (m >>> 8) & 0xff;
+ res[k + 3] = m & 0xff;
+ }
+ return res;
+}
+utils.split32 = split32;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..756f85d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "hash.js",
+ "version": "0.0.0",
+ "description": "Various hash functions that could be run by both browser and node",
+ "main": "lib/hash.js",
+ "scripts": {
+ "test": "mocha --reporter=spec test/*-test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git at github.com:indutny/hash.js"
+ },
+ "keywords": [
+ "hash",
+ "sha256",
+ "sha224",
+ "hmac"
+ ],
+ "author": "Fedor Indutny <fedor at indutny.com>",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/indutny/hash.js/issues"
+ },
+ "homepage": "https://github.com/indutny/hash.js",
+ "devDependencies": {
+ "mocha": "^1.18.2"
+ }
+}
diff --git a/test/hash-test.js b/test/hash-test.js
new file mode 100644
index 0000000..77da2a6
--- /dev/null
+++ b/test/hash-test.js
@@ -0,0 +1,64 @@
+var assert = require('assert');
+var hash = require('../');
+
+describe('Hash', function() {
+ it('should support sha256', function() {
+ assert.equal(hash.sha256.blockSize, 512);
+ assert.equal(hash.sha256.outSize, 256);
+
+ var test = [
+ [ 'abc',
+ 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' ],
+ [ 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
+ '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1' ],
+ [ 'deadbeef',
+ '5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953',
+ 'hex' ],
+ ];
+ for (var i = 0; i < test.length; i++) {
+ var msg = test[i][0];
+ var res = test[i][1];
+ var enc = test[i][2];
+
+ var dgst = hash.sha256().update(msg, enc).digest('hex');
+ assert.equal(dgst, res);
+
+ // Split message
+ var dgst = hash.sha256()
+ .update(msg.slice(0, 2), enc)
+ .update(msg.slice(2), enc)
+ .digest('hex');
+ assert.equal(dgst, res);
+ }
+ });
+
+ it('should support sha224', function() {
+ assert.equal(hash.sha224.blockSize, 512);
+ assert.equal(hash.sha224.outSize, 224);
+
+ var test = [
+ [ 'abc',
+ '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7' ],
+ [ 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
+ '75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525' ],
+ [ 'deadbeef',
+ '55b9eee5f60cc362ddc07676f620372611e22272f60fdbec94f243f8',
+ 'hex' ],
+ ];
+ for (var i = 0; i < test.length; i++) {
+ var msg = test[i][0];
+ var res = test[i][1];
+ var enc = test[i][2];
+
+ var dgst = hash.sha224().update(msg, enc).digest('hex');
+ assert.equal(dgst, res);
+
+ // Split message
+ var dgst = hash.sha224()
+ .update(msg.slice(0, 2), enc)
+ .update(msg.slice(2), enc)
+ .digest('hex');
+ assert.equal(dgst, res);
+ }
+ });
+});
diff --git a/test/hmac-test.js b/test/hmac-test.js
new file mode 100644
index 0000000..0a9647e
--- /dev/null
+++ b/test/hmac-test.js
@@ -0,0 +1,59 @@
+var assert = require('assert');
+var hash = require('../');
+var utils = hash.utils;
+
+describe('Hmac', function() {
+ describe('mixed test vector', function() {
+ test({
+ name: 'nist 1',
+ key: '00010203 04050607 08090A0B 0C0D0E0F' +
+ '10111213 14151617 18191A1B 1C1D1E1F 20212223 24252627' +
+ '28292A2B 2C2D2E2F 30313233 34353637 38393A3B 3C3D3E3F',
+ msg: 'Sample message for keylen=blocklen',
+ res: '8bb9a1db9806f20df7f77b82138c7914d174d59e13dc4d0169c9057b133e1d62'
+ });
+ test({
+ name: 'nist 2',
+ key: '00010203 04050607' +
+ '08090A0B 0C0D0E0F 10111213 14151617 18191A1B 1C1D1E1F',
+ msg: 'Sample message for keylen<blocklen',
+ res: 'a28cf43130ee696a98f14a37678b56bcfcbdd9e5cf69717fecf5480f0ebdf790'
+ });
+ test({
+ name: 'nist 3',
+ key: '00010203' +
+ '04050607 08090A0B 0C0D0E0F 10111213 14151617 18191A1B' +
+ '1C1D1E1F 20212223 24252627 28292A2B 2C2D2E2F 30313233' +
+ '34353637 38393A3B 3C3D3E3F 40414243 44454647 48494A4B' +
+ '4C4D4E4F 50515253 54555657 58595A5B 5C5D5E5F 60616263',
+ msg: 'Sample message for keylen=blocklen',
+ res: 'bdccb6c72ddeadb500ae768386cb38cc41c63dbb0878ddb9c7a38a431b78378d'
+ });
+ test({
+ name: 'nist 4',
+ key: '00' +
+ '01020304 05060708 090A0B0C 0D0E0F10 11121314 15161718' +
+ '191A1B1C 1D1E1F20 21222324 25262728 292A2B2C 2D2E2F30',
+ msg: 'Sample message for keylen<blocklen, with truncated tag',
+ res: '27a8b157839efeac98df070b331d593618ddb985d403c0c786d23b5d132e57c7'
+ });
+ test({
+ name: 'regression 1',
+ key: '48f38d0c6a344959cc94502b7b5e8dffb6a5f41795d9066fc9a649557167ee2f',
+ msg: '1d495eef7761b65dccd0a983d2d7204fea28b5c81f1758046e062eb043755ea1',
+ msgEnc: 'hex',
+ res: 'cf5ad5984f9e43917aa9087380dac46e410ddc8a7731859c84e9d0f31bd43655'
+ });
+
+ function test(opt) {
+ it('should not fail at ' + opt.name, function() {
+ var h = hash.hmac(hash.sha256, opt.key, 'hex');
+ assert.equal(h.update(opt.msg, opt.msgEnc).digest('hex'), opt.res);
+ var h = hash.hmac(hash.sha256, opt.key, 'hex');
+ assert.equal(h.update(opt.msg.slice(0, 10), opt.msgEnc)
+ .update(opt.msg.slice(10), opt.msgEnc)
+ .digest('hex'), opt.res);
+ });
+ }
+ });
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-hash.js.git
More information about the Pkg-javascript-commits
mailing list