137 lines
3.4 KiB
JavaScript
137 lines
3.4 KiB
JavaScript
/*
|
|
Modifications copyright (c) 2014 IOnU Security Inc. All rights reserved
|
|
Added to IonU source repository in April 2014 by Kendrick Webster,
|
|
based on public-domain code by Kendrick Webster.
|
|
-----------------------------------------------------------------------------
|
|
Simple chaos-based hash/PRNG and stream cypher 1991 - 2014
|
|
|
|
Written by Ken Webster <ken@kenwebster.org>
|
|
[ other contributers can add their names here ]
|
|
|
|
To the extent possible under law, the author(s) have dedicated all copyright
|
|
and related and neighboring rights to this software to the public domain
|
|
worldwide. This software is distributed without any warranty.
|
|
|
|
See the CC0 Public Domain Dedication for details:
|
|
<http://creativecommons.org/publicdomain/zero/1.0/>
|
|
-----------------------------------------------------------------------------
|
|
This is a small-footprint hasher and PRNG that incrementally hashes input
|
|
bytes into an evolving chaotic state pool from which pseudo random output
|
|
bytes are extracted. The output passes all dieharder tests.
|
|
---------------------------------------------------------------------------*/
|
|
"use strict";
|
|
|
|
/* how often to seed the RNG entroy pool with a high-res timer sample */
|
|
var RNG_SEED_INTERVAL_MS = 50;
|
|
|
|
function ror16(w) {
|
|
return (w >>> 1) | ((w & 1) ? 0x8000 : 0);
|
|
}
|
|
|
|
function rol32(w) {
|
|
return (w << 1) | ((w & 0x80000000) ? 1 : 0);
|
|
}
|
|
|
|
var HASH_WORDS = 64;
|
|
function Hash() {
|
|
var j;
|
|
this.a = new Array(HASH_WORDS);
|
|
this.b = 0;
|
|
this.i = 0;
|
|
for (j = 0; j < HASH_WORDS; j++) {
|
|
this.a[j] = 0;
|
|
}
|
|
}
|
|
var rng_hash = new Hash();
|
|
|
|
function hashbyte(h, byte) {
|
|
var w;
|
|
h.b += byte;
|
|
w = h.a[h.i];
|
|
w ^= h.b & 0xFFFF;
|
|
w = ror16(w);
|
|
w = (w + 0x5ca3) & 0xFFFF;
|
|
h.a[h.i] = w;
|
|
h.b += w;
|
|
h.b = rol32(h.b);
|
|
h.i = (h.i + 1) % HASH_WORDS;
|
|
return w & 0xFF;
|
|
}
|
|
|
|
function hashbuf(h, buf, len) {
|
|
var i;
|
|
len = len || buf.length;
|
|
for (i = 0; i < len; i++) {
|
|
hashbyte(h, buf[i]);
|
|
}
|
|
}
|
|
|
|
function hashstr(h, str) {
|
|
var i;
|
|
for (i = 0; i < str.length; i++) {
|
|
hashbyte(h, str.charCodeAt(i));
|
|
}
|
|
}
|
|
|
|
function mix(h, n) {
|
|
while (n--) {
|
|
hashbyte(h, 0);
|
|
}
|
|
}
|
|
|
|
function getbuf(h, buf, len) {
|
|
var i;
|
|
len = len || buf.length;
|
|
for (i = 0; i < len; i++) {
|
|
buf[i] = hashbyte(h, 0);
|
|
}
|
|
}
|
|
|
|
function encrypt(h, buf) {
|
|
var c, d, i;
|
|
d = hashbyte(h, 0);
|
|
for (i = 0; i < buf.length; i++) {
|
|
c = hashbyte(h, buf[i]);
|
|
buf[i] ^= d;
|
|
d = c;
|
|
}
|
|
}
|
|
|
|
function decrypt(h, buf) {
|
|
var d, i;
|
|
d = hashbyte(h, 0);
|
|
for (i = 0; i < buf.length; i++) {
|
|
buf[i] ^= d;
|
|
d = hashbyte(h, buf[i]);
|
|
}
|
|
}
|
|
|
|
function get_random_uint32() {
|
|
var r = hashbyte(rng_hash, 0);
|
|
r <<= 8;
|
|
r |= hashbyte(rng_hash, 0);
|
|
r <<= 8;
|
|
r |= hashbyte(rng_hash, 0);
|
|
r <<= 8;
|
|
r |= hashbyte(rng_hash, 0);
|
|
return r >>> 0;
|
|
}
|
|
|
|
setInterval(function () {
|
|
var t = process.hrtime(); /* t[0] is seconds, t[1] is nanoseconds */
|
|
hashbyte(rng_hash, t[1] & 0xFF);
|
|
hashbyte(rng_hash, (t[1] >>> 8) & 0xFF);
|
|
hashbyte(rng_hash, (t[1] >>> 16) & 0xFF);
|
|
}, RNG_SEED_INTERVAL_MS);
|
|
|
|
exports.Hash = Hash;
|
|
exports.rng_hash = rng_hash;
|
|
exports.hashbyte = hashbyte;
|
|
exports.hashbuf = hashbuf;
|
|
exports.hashstr = hashstr;
|
|
exports.mix = mix;
|
|
exports.getbuf = getbuf;
|
|
exports.encrypt = encrypt;
|
|
exports.decrypt = decrypt;
|
|
exports.get_random_uint32 = get_random_uint32;
|