Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 91 additions & 63 deletions cubehash.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@
}
}(this, function () {
// Init vector was computed by 10r rounds as described in the specification
var init = [

var Cubehash = function(r, b, f, h) {
var self = this;
// Currently initialization is hardcoded to 10
// if (i == undefined) i = 16;
if (r === undefined) { r = 1; }
if (b === undefined) { b = 32; }
if (f === undefined) { f = 10; }
if (h === undefined) { h = 8; }

var init = [
-2096419883, 658334063, -679114902, 1246757400,
-1523021469, -289996037, 1196718146, 1168084361,
-2027445816, -1170162360, -822837272, 625197683,
Expand All @@ -28,79 +38,97 @@
19608647852, 9541915967, 5144979599, -4355863926
];

function rotate(a, b) {
return (a << b) | (a >>> (32 - b));
}

function intToHex(v) {
var s = '';
// Left shit a, b bits. If the number gets too large
self.rotate = function(a, b) {
return (a << b) | (a >>> (32 - b));
};

for (; v !== 0; v >>>= 8) {
s += ((v >> 4) & 0xF).toString(16) + (v & 0xF).toString(16);
}
self.intToHex = function(v) {
var s = '';

return s;
}

function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
return arr;
}
// Working from right to left
for(; v !== 0; v >>>= 8){
s = ((v >> 4) & 0xF).toString(16) + (v & 0xf).toString(16) + s;
}

function transform(state) {
var i, r,
y = new Array(16);

for (r = 0;r < 8; r += 1) {
for (i = 0; i < 16; i += 1) { state[i + 16] += y[i^8] = state[i]; }
for (i = 0; i < 16; i += 1) { state[i] = rotate(y[i], 7)^state[i + 16]; }
for (i = 0; i < 16; i += 1) { y[i^2] = state[i + 16]; }
for (i = 0; i < 16; i += 1) { state[i + 16] = y[i] + state[i]; }
for (i = 0; i < 16; i += 1) { y[i^4] = state[i]; }
for (i = 0; i < 16; i += 1) { state[i] = rotate(y[i], 11)^state[i + 16]; }
for (i = 0; i < 16; i += 2) {
swap(state, i + 16, i + 17);
// Prepend zeroes with... zeroes
while(s.length < 8) { s = '0' + s; }

return s;
};

self.swap = function(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
return arr;
};

self.transform = function(state) {
var i, r,
y = new Array(16);

for (r = 0;r < 8; r += 1) {
for (i = 0; i < 16; i += 1) { state[i + 16] += y[i^8] = state[i]; }
for (i = 0; i < 16; i += 1) { state[i] = self.rotate(y[i], 7)^state[i + 16]; }
for (i = 0; i < 16; i += 1) { y[i^2] = state[i + 16]; }
for (i = 0; i < 16; i += 1) { state[i + 16] = y[i] + state[i]; }
for (i = 0; i < 16; i += 1) { y[i^4] = state[i]; }
for (i = 0; i < 16; i += 1) { state[i] = self.rotate(y[i], 11)^state[i + 16]; }
for (i = 0; i < 16; i += 2) {
self.swap(state, i + 16, i + 17);
}
}
}

for (i = 0; i < 16; i += 1) {
y[i] = 0;
}
}
for (i = 0; i < 16; i += 1) {
y[i] = 0;
}
};

function hash(data) {
// init state
var i,
s = '',
state = new Array(32);
self.hash = function(data) {
// init state
var i,
j,
s = '',
state = new Array(32);

for (i = 0; i < 32; i += 1) {
state[i] = init[i];
}
for (i = 0; i < 32; i += 1) {
state[i] = init[i];
}

// update with data
data += String.fromCharCode(128);
// update with data
data += String.fromCharCode(128);

for (i = 0; i < data.length; i += 1) {
state[0] ^= data.charCodeAt(i);
transform(state);
}
while(data.length % 32) {
data += String.fromCharCode(0);
}

// finalize
state[31] ^= 1;
for (i = 0; i < data.length; i += b) {
var block = data.substr(i, b);
// XOR into state
for (j = 0; j < b; j += 1) {
state[j] ^= block.charCodeAt(j);
}

// Perform r identical rounds
for (j = 0; j < r; j += 1){
self.transform(state);
}
}

for (i = 0; i < 10; i += 1) {
transform(state);
}
// finalize
state[31] ^= 1;
for (i = 0; i < f; i += 1) {
self.transform(state);
}

// convert to hex
for (i = 0; i < 8; i += 1) {
s += intToHex(state[i]);
}
return s;
}
// convert to hex
for (i = 0; i < 8; i += 1) {
s += self.intToHex(state[i]);
}
return s;
};
};

return hash;
return Cubehash;
}));
74 changes: 69 additions & 5 deletions test/cubehash-test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,82 @@
/*global describe, it*/

var assert = require('assert'),
cubehash = require('../cubehash');
Cubehash = require('../cubehash');

describe('cubehash', function () {
var cubehash = new Cubehash();

it('Should be a function', function (done) {
assert.equal(typeof cubehash, 'function');
assert.equal(typeof Cubehash, 'function');
done();
});

it('Should rotate with 32 bit modulus', function() {
var i;

for(i = 1; i < 30; i += 1) {
assert.equal(
cubehash.rotate(2, i),
Math.pow(2, i + 1)
);
}
assert.equal(
cubehash.rotate(2, 31),
1
);
assert.equal(
cubehash.rotate(2, 32),
2
);
for(i = 33; i < 62; i += 1) {
assert.equal(
cubehash.rotate(2, i),
Math.pow(2, i % 31)
);
}
assert.equal(
cubehash.rotate(2, 63),
1
);
assert.equal(
cubehash.rotate(2, 64),
2
);
});

var intToHexTests = [
{arg: 0, expect: '00000000'},
{arg: 9001, expect: '00002329'},
{arg: 4294967294, expect: 'fffffffe'},
{arg: -401703733, expect: 'e80e7ccb'},
{arg: 4294967295, expect: 'ffffffff'},
{arg: -42, expect: 'ffffffd6'}
];

intToHexTests.forEach(function(test) {
it('Should call intToHex with ' +
test.arg.toString() + ' and give ' + test.expect, function() {
assert.equal(
cubehash.intToHex(test.arg),
test.expect
);
});
});

it('Should hash correctly', function (done) {
assert.equal(cubehash(''), '38d1e8a22d7baac6fd5262d83de89cacf784a02caa866335299987722aeabc59');
assert.equal(cubehash('Hello'), '692638db57760867326f851bd2376533f37b640bd47a0ddc607a9456b692f70f');
assert.equal(cubehash('The quick brown fox jumps over the lazy dog'), '94e0c958d85cdfaf554919980f0f50b945b88ad08413e0762d6ff0219aff3e55');
cubehash = new Cubehash();
assert.equal(
cubehash.hash(''),
'a2e8d138c6aa7b2dd86252fdac9ce83d2ca084f7356386aa7287992959bcea2a'
);
assert.equal(
cubehash.hash('Hello'),
'd0921f019c8d41c91ccb59bfb48f9b70c4f7fc0e145a738ee7a6c0366c7e332d'
);
assert.equal(
cubehash.hash('The quick brown fox jumps over the lazy dog'),
'd8bf9690315a2d08b4c9cafabd1566de896359d505a32c833797bc8a94aa587b'
);
done();
});
});