Comparing version 0.1.0 to 0.1.1
{ | ||
"name": "rc4", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "RC4 random number generator", | ||
@@ -5,0 +5,0 @@ "main": "rc4.js", |
236
rc4.js
@@ -6,109 +6,185 @@ "use strict"; | ||
function identityPermutation() { | ||
var s = new Array(256); | ||
for (var i = 0; i < 256; i++) { | ||
s[i] = i; | ||
function createRC4(N) { | ||
function identityPermutation() { | ||
var s = new Array(N); | ||
for (var i = 0; i < N; i++) { | ||
s[i] = i; | ||
} | ||
return s; | ||
} | ||
return s; | ||
} | ||
// :: string | array integer -> array integer | ||
function seed(key) { | ||
if (typeof key === "string") { | ||
// to string | ||
key = "" + key; | ||
key = key.split("").map(function (c) { return c.charCodeAt(0) % 256; }); | ||
} else if (Array.isArray(key)) { | ||
if (!key.every(function (v) { | ||
return typeof v === "number" && v === (v | 0); | ||
})) { | ||
throw new TypeError("invalid seed key specified: not array of integers"); | ||
// :: string | array integer -> array integer | ||
function seed(key) { | ||
if (typeof key === "string") { | ||
// to string | ||
key = "" + key; | ||
key = key.split("").map(function (c) { return c.charCodeAt(0) % N; }); | ||
} else if (Array.isArray(key)) { | ||
if (!key.every(function (v) { | ||
return typeof v === "number" && v === (v | 0); | ||
})) { | ||
throw new TypeError("invalid seed key specified: not array of integers"); | ||
} | ||
} else { | ||
throw new TypeError("invalid seed key specified"); | ||
} | ||
} else { | ||
throw new TypeError("invalid seed key specified"); | ||
} | ||
var keylen = key.length; | ||
var keylen = key.length; | ||
// resed state | ||
var s = identityPermutation(); | ||
// resed state | ||
var s = identityPermutation(); | ||
var j = 0; | ||
for (var i = 0; i < 255; i++) { | ||
j = (j + s[i] + key[i % keylen]) % 256; | ||
var tmp = s[i]; | ||
s[i] = s[j]; | ||
s[j] = tmp; | ||
var j = 0; | ||
for (var i = 0; i < N; i++) { | ||
j = (j + s[i] + key[i % keylen]) % N; | ||
var tmp = s[i]; | ||
s[i] = s[j]; | ||
s[j] = tmp; | ||
} | ||
return s; | ||
} | ||
return s; | ||
} | ||
function RC4(key) { | ||
this.s = seed(key); | ||
this.i = 0; | ||
this.j = 0; | ||
} | ||
function RC4(key) { | ||
this.s = seed(key); | ||
this.i = 0; | ||
this.j = 0; | ||
} | ||
RC4.prototype.randomNative = function () { | ||
this.i = (this.i + 1) % N; | ||
this.j = (this.j + this.s[this.i]) % N; | ||
RC4.prototype.randomByte = function () { | ||
this.i = (this.i + 1) % 256; | ||
this.j = (this.j + this.s[this.i]) % 256; | ||
var tmp = this.s[this.i]; | ||
this.s[this.i] = this.s[this.j]; | ||
this.s[this.j] = tmp; | ||
var tmp = this.s[this.i]; | ||
this.s[this.i] = this.s[this.j]; | ||
this.s[this.j] = tmp; | ||
var k = this.s[(this.s[this.i] + this.s[this.j]) % N]; | ||
var k = this.s[(this.s[this.i] + this.s[this.j]) % 256]; | ||
return k; | ||
}; | ||
return k; | ||
}; | ||
RC4.prototype.randomUInt32 = function () { | ||
var a = this.randomByte(); | ||
var b = this.randomByte(); | ||
var c = this.randomByte(); | ||
var d = this.randomByte(); | ||
RC4.prototype.randomFloat = function () { | ||
var a = this.randomByte(); | ||
var b = this.randomByte(); | ||
var c = this.randomByte(); | ||
var d = this.randomByte(); | ||
return ((a * 256 + b) * 256 + c) * 256 + d; | ||
}; | ||
var e = ((a * 256 + b) * 256 + c) * 256 + d; | ||
return e / 0x100000000; | ||
}; | ||
RC4.prototype.randomFloat = function () { | ||
return this.randomUInt32() / 0x100000000; | ||
}; | ||
RC4.prototype.currentState = function () { | ||
return { | ||
i: this.i, | ||
j: this.j, | ||
s: this.s.slice(), // copy | ||
RC4.prototype.random = function() { | ||
var a, b; | ||
if (arguments.length === 1) { | ||
a = 0; | ||
b = arguments[0]; | ||
} else if (arguments.length === 2) { | ||
a = arguments[0]; | ||
b = arguments[1]; | ||
} else { | ||
throw new TypeError("random takes one or two integer arguments"); | ||
} | ||
if (a !== (a | 0) || b !== (b | 0)) { | ||
throw new TypeError("random takes one or two integer arguments"); | ||
} | ||
return a + this.randomUInt32() % (b - a + 1); | ||
}; | ||
RC4.prototype.currentState = function () { | ||
return { | ||
i: this.i, | ||
j: this.j, | ||
s: this.s.slice(), // copy | ||
}; | ||
}; | ||
RC4.prototype.setState = function(state) { | ||
var s = state.s; | ||
var i = state.i; | ||
var j = state.j; | ||
if (!(i === (i | 0) && 0 <= i && i < N)) { | ||
throw new Error("state.i should be integer [0, " + (N-1) + "]"); | ||
} | ||
if (!(j === (j | 0) && 0 <= j && j < N)) { | ||
throw new Error("state.j should be integer [0, " + (N-1) + "]"); | ||
} | ||
// check length | ||
if (!Array.isArray(s) || s.length !== N) { | ||
throw new Error("state should be array of length " + N); | ||
} | ||
// check that all params are there | ||
for (var k = 0; k < N; k++) { | ||
if (s.indexOf(k) === -1) { | ||
throw new Error("state should be permutation of 0.." + (N-1) + ": " + k + " is missing"); | ||
} | ||
} | ||
this.i = i; | ||
this.j = j; | ||
this.s = s.slice(); // assign copy | ||
}; | ||
return RC4; | ||
} | ||
var RC4 = createRC4(256); | ||
RC4.prototype.randomByte = RC4.prototype.randomNative; | ||
var RC4small = createRC4(16); | ||
RC4small.prototype.randomByte = function () { | ||
var a = this.randomNative(); | ||
var b = this.randomNative(); | ||
return a * 16 + b; | ||
}; | ||
RC4.prototype.setState = function(state) { | ||
var s = state.s; | ||
var i = state.i; | ||
var j = state.j; | ||
var ordA = "a".charCodeAt(0); | ||
var ord0 = "0".charCodeAt(0); | ||
if (!(i === (i | 0) && 0 <= i && i < 256)) { | ||
throw new Error("state.i should be integer [0, 255]"); | ||
} | ||
function toHex(n) { | ||
return n < 10 ? String.fromCharCode(ord0 + n) : String.fromCharCode(ordA + n - 10); | ||
} | ||
if (!(j === (j | 0) && 0 <= j && j < 256)) { | ||
throw new Error("state.i should be integer [0, 255]"); | ||
} | ||
function fromHex(c) { | ||
return parseInt(c, 16); | ||
} | ||
// check length | ||
if (!Array.isArray(s) || s.length !== 256) { | ||
throw new Error("state should be array of length 256"); | ||
} | ||
RC4small.prototype.currentStateString = function () { | ||
var state = this.currentState(); | ||
// check that all params are there | ||
for (var k = 0; k < 256; k++) { | ||
if (s.indexOf(k) === -1) { | ||
throw new Error("state should be permutation of 0..255: " + k + " is missing"); | ||
} | ||
var i = toHex(state.i); | ||
var j = toHex(state.j); | ||
var res = i + j + state.s.map(toHex).join(""); | ||
return res; | ||
}; | ||
RC4small.prototype.setStateString = function (stateString) { | ||
if (!stateString.match(/^[0-9a-f]{18}$/)) { | ||
throw new TypeError("RC4small stateString should be 18 hex character string"); | ||
} | ||
this.i = i; | ||
this.j = j; | ||
this.s = s.slice(); // assign copy | ||
var i = fromHex(stateString[0]); | ||
var j = fromHex(stateString[1]); | ||
var s = stateString.split("").slice(2).map(fromHex); | ||
this.setState({ | ||
i: i, | ||
j: j, | ||
s: s, | ||
}); | ||
}; | ||
RC4.RC4small = RC4small; | ||
module.exports = RC4; |
# rc4 | ||
RC4 random number generator | ||
[RC4](http://en.wikipedia.org/wiki/RC4) random number generator | ||
@@ -29,1 +29,28 @@ [![Build Status](https://secure.travis-ci.org/phadej/rc4.png?branch=master)](http://travis-ci.org/phadej/rc4) | ||
``` | ||
## RC4small | ||
There is also `RC4small` generator, with smaller internal state: | ||
``` | ||
var RC4small = require("rc4").RC4small; | ||
var generator = new RC4small("my seed"); | ||
var stateString = generator.currentStateString(); // 18 character hexadecimal string | ||
console.log(generator.randomFloat()); // 0.9362740234937519 | ||
generator.setStateString(stateString); | ||
console.log(generator.randomFloat()); // 0.9362740234937519 | ||
``` | ||
## API | ||
Both `RC4` and `RC4small` have following random value generating methods: | ||
``` | ||
randomByte : () ⇒ { x : ℕ | x ∈ [0, 255] } | ||
randomUInt32 : () ⇒ { x : ℕ | x ∈ [0, 2^32-1] } | ||
randomFloat : () ⇒ { x : R | x ∈ [0, 1) } | ||
random : (a : ℤ) ⇒ { x : ℤ | x ∈ [0, a] } | ||
random : (a : ℤ, b : ℤ) ⇒ { x : ℤ | x ∈ [a, b] } | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8123
149
56