├── LICENSE
├── README.md
├── isaacCSPRNG-1.1.js
└── isaacCSPRNG-1.1.min.js
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, William McMeans
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🔣 isaacCSPRNG [](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity) [](https://opensource.org/licenses/BSD-3-Clause)
2 | [ISAAC](https://en.wikipedia.org/wiki/ISAAC_(cipher)) is a *cryptographically secure* pseudo-random number generator ([CSPRNG](https://en.wikipedia.org/wiki/Cryptographically-secure_pseudorandom_number_generator)), meant to be usable as a [stream cipher](https://archive.is/cOe1D), created by [Robert J. Jenkins Jr.](https://en.wikipedia.org/wiki/Robert_John_Jenkins_Junior), in 1996, based on [RC4](https://en.wikipedia.org/wiki/RC4). Designed for speed and security, ISAAC (Indirection, Shift, Accumulate, Add, and Count) generates 32-bit random numbers. On average, cycles are 28295 values long, and are guaranteed to be at least 240 values long. The results are uniformly distributed, unbiased, and unpredictable unless you know the seed. Speaking of which, it’s the responsibility of the user to seed ISAAC with a strong entropy source.
3 |
4 | Internally, my implementation here is largely Rinquin’s logic (see [REFS](https://github.com/macmcmeans/isaacCSPRNG/blob/master/README.md#refs)) which appears to be quite similar to Jenkins’ original work (in C) which he released into the Public Domain. My contributions are a [namespace](https://archive.is/fqM9P), so that separate instances may be created; as well as helper functions to spit out random bytes, and random strings, of desired lengths. Going further, my *int32*, *double* and *range* methods expand the output options from the orginal *random* and *rand* methods; and where Rinquin extends the String object, my version uses separate functions in lieu of extending the native prototype.
5 |
6 | Since this is a CSPRNG, or alternatively, a Deterministic Random Bit Generator (DRBG), I added logic to directly perform simple [vernam](https://en.wikipedia.org/wiki/One-time_pad) (XOR) encryption. As an academic option, I created the ability to get and set the generator’s internal state. Lastly, unseeded instances will internally set themselves with a default value from [Window.crypto](https://archive.ph/4h0zE) values, which would be suitable for Monte Carlo simulations where deterministic output is not required.
7 |
8 | There are surprisingly few JavaScript examples of ISAAC. Considering it’s almost 30 years old, and has never been proven broken, one would expect more mention of it.
9 |
10 | This generator is emoji-friendly 🧐😲😊👍, which is to say that seeds, cipher keys and plaintexts are multi-byte Unicode-safe.
11 |
12 |
13 | Version 1.1
14 | Author: William P. "Mac" McMeans
15 | Date: 3 MAY 2018
16 |
17 |
18 |
19 |
20 |
21 | “The generation of random numbers is too important to be left to chance.”
~ Robert R. Coveyou
22 |
23 |
24 |
25 |
26 | ## Application:
27 | Use this to produce high-quality random numbers, and to encipher discrete messages and streams. You may also create arbitrary length byte arrays and text strings of random composition. Note: This generator is cryptographically secure. If you don’t need a secure generator then consider ALEA for your application, an RNG created by Johannes Baagøe having excellent statistical properties.
28 |
29 |
30 | ## Dependencies:
31 | None.
32 |
33 |
34 |
35 | ## Period:
36 | Average 28295 (not less than 240)
37 |
38 |
39 |
40 | ## Example usage:
41 |
42 | ```
43 | // return an instance of the generator initialized internally with Window.crypto (Monte Carlo)
44 | > prng0 = isaacCSPRNG();
45 |
46 |
47 | // return a 32-bit fraction in the range [0, 1]
48 | > prng0.random(); --> some random value
49 |
50 |
51 | // return an instance of the generator initialized with a specified seed (deterministic)
52 | > prng1 = isaacCSPRNG( 'this is a test' );
53 |
54 |
55 | // return a 32-bit fraction in the range [0, 1]
56 | > prng1.random(); --> 0.9519342305138707
57 |
58 |
59 | // return a signed random integer in the range [-2^31, 2^31]
60 | > prng1.rand(); --> 2052729692
61 |
62 |
63 | // advance the generator the specified number of cycles
64 | > prng1.prng( 6 );
65 |
66 |
67 | // return an unsigned random integer in the range [0, 2^32]
68 | > prng1.int32(); --> 288117856
69 |
70 |
71 | // return a 53-bit fraction in the range [0, 1]
72 | > prng1.double(); --> 0.4613288596233964
73 |
74 |
75 | // return 32-bit range (inclusive) //
76 | // from -27 to 400.65
77 | > prng1.range( -27, 400.625 ); --> 267.45789149729535
78 |
79 | // from 0 to 100
80 | > prng1.range( 100 ); --> 37
81 |
82 |
83 | // return an array of random bytes
84 | > prng1.bytes( 10 ); --> (10) [192, 182, 240, 253, 228, 223, 55, 207, 168, 102]
85 |
86 |
87 | // return a string of random 7-bit ASCII graphemes
88 | > prng1.chars( 10 ); --> "<3%;&mK6GH"
89 |
90 |
91 | // return vernam encryption of plaintext message, in hex format
92 | > secret = prng1.encipher( 'key', 'message', 1 ) --> "002900470041003b0021001e003f"
93 |
94 | // return vernam decryption of ciphertext message, from hex-formatted data
95 | > prng1.decipher( 'key', secret, 1 ) --> "message"
96 |
97 |
98 | // return vernam encryption of plaintext message (raw XOR)
99 | > secret = prng1.encipher( 'key', 'message' ) --> ")GA;!?"
100 |
101 | // return vernam decryption of ciphertext message
102 | > secret = prng1.encipher( 'key', secret ) --> "message"
103 |
104 |
105 | // export an object that describes the generator’s internal state
106 | > state = prng1.export(); --> JSON
107 |
108 |
109 | // import an object that will set the generator’s internal state
110 | > prng1.import( state );
111 |
112 |
113 | // zeroize the generator
114 | > prng1.reset();
115 |
116 |
117 | // re-seed existing generator (with a sample Gujarati phrase)
118 | > prng1.seed( 'પ્રિઝમ સાઇફર' );
119 |
120 |
121 | > prng1.random(); --> 0.22731631994247437
122 |
123 |
124 | // re-instantiate the prng1 generator with a seed (emoji and script pseudo-alphabet)
125 | > prng1 = isaacCSPRNG( '⛄⚽🙈𝓾𝓷𝓲𝓬𝓸𝓭𝓮' );
126 |
127 |
128 | // range parameters can be given in either order
129 | > prng1.range( 10, -20); --> -15
130 |
131 |
132 | // return ciphertext message, in hex (using Malayalam, Bengali, emoji and Unicode math symbols)
133 | > secret = prng1.encipher( '𝙠𝙚𝙮 ⚷🔑⚿ എൻക്രിപ്റ്റ് ചെയ്യുക', '𝖒𝖊𝖘𝖘𝖆𝖌𝖊 📧 📩 💌 📬 প্রিজম সাইফার', true ); -->
134 | "d810ddabd85ddda7d804ddd8d84dddeed86adde7d813ddafd842ddbe005cd810dcd70019d81fdcbf0014d803dcb20049d85cdca2004009cf09a0099b09de09ae09fe005d099f099609a209c609fd09dc"
135 |
136 |
137 | // restore the plaintext (from hex input)
138 | > prng1.decipher( '𝙠𝙚𝙮 ⚷🔑⚿ എൻക്രിപ്റ്റ് ചെയ്യുക', secret, true ); -->
139 | "𝖒𝖊𝖘𝖘𝖆𝖌𝖊 📧 📩 💌 📬 প্রিজম সাইফার"
140 |
141 | ```
142 | NOTE: Specifiying a seed on generator instantiation, or using the seed() method, or using either of the encipher() or decipher() methods will all produce the same effect of specifically setting the generator's internal seed. In the case of enciphering/deciphering, the key provided becomes the seed.
143 |
144 |
145 |
146 | ## REFS:
147 | https://github.com/rubycon/isaac.js
148 |
149 | [http://www.burtleburtle.net/bob/rand/isaacafa.html](https://archive.is/sysF)
150 |
151 | [http://www.burtleburtle.net/bob/c/readable.c](https://archive.ph/5Mzx2)
152 |
153 | [http://rosettacode.org/wiki/The_ISAAC_Cipher](https://archive.ph/WEctB)
154 |
155 | https://crypto.stackexchange.com/questions/42907/why-is-isaac-not-a-pseudo-random-number-generator
156 |
157 |
158 |
159 | ## Tested:
160 | Google Chrome on Win 10 (x64)
161 |
162 |
163 | ## Version notes:
164 | * 1.1 - 3 MAY 2018
165 | ``feature`` Expose generator internal state, set/get
166 |
167 | * 1.0 - 22 JUL 2017
168 | ``release`` Initial release
169 |
170 |
171 | ## Academic papers:
172 | https://eprint.iacr.org/2006/438.pdf
173 |
174 |
175 | # License (BSD)
176 | Copyright (c) 2017, 2018 William McMeans
177 |
178 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
179 |
180 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
181 |
182 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
183 |
184 | 3. Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
185 |
186 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
187 |
--------------------------------------------------------------------------------
/isaacCSPRNG-1.1.js:
--------------------------------------------------------------------------------
1 | /*///////////////////////////////////////////////////////////////////////////////////////////////////
2 | isaacCSPRNG 1.1
3 | /////////////////////////////////////////////////////////////////////////////////////////////////////
4 | https://github.com/macmcmeans/isaacCSPRNG/blob/master/isaacCSPRNG-1.1.js
5 | /////////////////////////////////////////////////////////////////////////////////////////////////////
6 | This is a derivative work copyright (c) 2018, William P. "Mac" McMeans, under BSD license.
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 | 3. Neither the name of isaacCSPRNG nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 | Original work copyright (c) 2012 Yves-Marie K. Rinquin, under MIT license.
13 | https://github.com/rubycon/isaac.js
14 | ///////////////////////////////////////////////////////////////////////////////////////////////////*/
15 | isaacCSPRNG = function( specifiedSeed ){
16 | return (function( userSeed ) {
17 | "use strict";
18 |
19 | /* private: internal states */
20 | var m = new Array( 256 ) // internal memory
21 | , acc = 0 // accumulator
22 | , brs = 0 // last result
23 | , cnt = 0 // counter
24 | , r = new Array( 256 ) // result array
25 | , gnt = 0 // generation counter
26 | ;
27 |
28 | var _version = '1.1';
29 |
30 | ////////////////////////////////////////////////////
31 | /* initial random seed */
32 |
33 | // seed( Math.random() * 0xffffffff ); // 4294967295
34 |
35 | var internalSeed
36 | , uinta = new Uint32Array( 2 )
37 | , defaultInternalSeed = new Array()
38 | ;
39 | window.crypto.getRandomValues( uinta );
40 | defaultInternalSeed = uinta[ 0 ] + uinta[ 1 ];
41 |
42 | internalSeed = userSeed || defaultInternalSeed;
43 |
44 | seed( internalSeed );
45 | ////////////////////////////////////////////////////
46 |
47 |
48 |
49 | /* private: 32-bit integer safe adder */
50 | function _add( x, y ) {
51 | var lsb = ( x & 0xffff ) + ( y & 0xffff )
52 | , msb = ( x >>> 16 ) + ( y >>> 16 ) + ( lsb >>> 16 )
53 | ;
54 |
55 | return ( msb << 16 ) | ( lsb & 0xffff );
56 | };
57 |
58 |
59 |
60 | /* private: return data converted from hex string */
61 | function _hexDecode( data ){
62 | var j
63 | , hexes = data.match(/.{1,4}/g) || []
64 | , back = ""
65 | ;
66 |
67 | for( j = 0; j < hexes.length; j++ ) {
68 | back += String.fromCharCode( parseInt( hexes[ j ], 16 ) );
69 | }
70 |
71 | return back;
72 | };
73 |
74 |
75 |
76 | /* private: return data converted to hex string */
77 | function _hexEncode( data ){
78 | var hex
79 | , i
80 | ;
81 |
82 | var result = "";
83 | for( i = 0; i < data.length; i++ ) {
84 | hex = data.charCodeAt( i ).toString( 16 );
85 | result += ( "000" + hex ).slice( -4 );
86 | }
87 |
88 | return result;
89 | };
90 |
91 |
92 |
93 | /* private: return the CSPRNG _internals in an object (for get/set) */
94 | function _internals() {
95 | return {
96 | a : acc
97 | , b : brs
98 | , c : cnt
99 | , m : m
100 | , r : r
101 | , g : gnt
102 | };
103 | };
104 |
105 |
106 |
107 | /* private: check if number is integer */
108 | function _isInteger( n ) {
109 | return parseInt( n ) === n;
110 | };
111 |
112 |
113 |
114 | /* private: convert string to integer array */
115 | /* js string (ucs-2/utf16) to a 32-bit integer (utf-8 chars, little-endian) array */
116 | function _toIntArray( string ) {
117 | var w1
118 | , w2
119 | , u
120 | , r4 = []
121 | , r = []
122 | , i = 0
123 | , s = string + '\0\0\0' // pad string to avoid discarding last chars
124 | , l = s.length - 1
125 | ;
126 |
127 | while( i < l ) {
128 | w1 = s.charCodeAt( i++ );
129 | w2 = s.charCodeAt( i + 1 );
130 |
131 | // 0x0000 - 0x007f code point: basic ascii
132 | if( w1 < 0x0080 ) {
133 | r4.push( w1 );
134 |
135 | } else
136 |
137 | // 0x0080 - 0x07ff code point
138 | if( w1 < 0x0800 ) {
139 | r4.push( ( ( w1 >>> 6 ) & 0x1f ) | 0xc0 );
140 | r4.push( ( ( w1 >>> 0 ) & 0x3f ) | 0x80 );
141 |
142 | } else
143 |
144 | // 0x0800 - 0xd7ff / 0xe000 - 0xffff code point
145 | if( ( w1 & 0xf800 ) != 0xd800 ) {
146 | r4.push( ( ( w1 >>> 12 ) & 0x0f ) | 0xe0 );
147 | r4.push( ( ( w1 >>> 6 ) & 0x3f ) | 0x80 );
148 | r4.push( ( ( w1 >>> 0 ) & 0x3f ) | 0x80 );
149 |
150 | } else
151 |
152 | // 0xd800 - 0xdfff surrogate / 0x10ffff - 0x10000 code point
153 | if( ( ( w1 & 0xfc00 ) == 0xd800 ) && ( ( w2 & 0xfc00 ) == 0xdc00 ) ) {
154 | u = ( ( w2 & 0x3f ) | ( ( w1 & 0x3f ) << 10 ) ) + 0x10000;
155 | r4.push( ( ( u >>> 18 ) & 0x07 ) | 0xf0 );
156 | r4.push( ( ( u >>> 12 ) & 0x3f ) | 0x80 );
157 | r4.push( ( ( u >>> 6 ) & 0x3f ) | 0x80 );
158 | r4.push( ( ( u >>> 0 ) & 0x3f ) | 0x80 );
159 | i++;
160 |
161 | } else {
162 | // invalid char
163 | }
164 |
165 | /* _add integer (four utf-8 value) to array */
166 | if( r4.length > 3 ) {
167 |
168 | // little endian
169 | r.push(
170 | ( r4.shift() << 0 ) | ( r4.shift() << 8 ) | ( r4.shift() << 16 ) | ( r4.shift() << 24 )
171 | );
172 | }
173 | }
174 |
175 | return r;
176 | };
177 |
178 |
179 |
180 | /* private: return a Vernam (XOR) transform of msg */
181 | function _vernam( msg ) {
182 | var out = "";
183 |
184 | for( var i = 0; i < msg.length; i++) {
185 | var ra = range( 33, 126 );
186 | out += String.fromCharCode( ra ^ msg.charCodeAt( i ) );
187 | }
188 |
189 | return out;
190 | };
191 |
192 |
193 |
194 | /* public: return an array of amount elements consisting of unsigned random integers in the range [0, 255] */
195 | function bytes( amount ) {
196 | var out = new Array( amount );
197 |
198 | for( var i = 0; i < amount; i++ ) {
199 | out[ i ] = range( 255 );
200 | }
201 |
202 | return out;
203 | };
204 |
205 |
206 |
207 | /* public: return a string of length (safe) characters consisting of random 7-bit ASCII graphemes */
208 | function chars( length ) {
209 | //var str = " ~`'\"_-+={}[]<>/\\,.:;?|!@#$%^&*()0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
210 | var str = " ~`_-+={}[]<>/,.:;?|!@#$%^&*()0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
211 | , out = ''
212 | ;
213 |
214 | for( var i = 0; i < length; i++ ) {
215 | out += str[ range( 0, str.length - 1 ) ];
216 | }
217 |
218 | return out;
219 | };
220 |
221 |
222 |
223 | /* public: return vernam transform on ciphertext string data/hex string data */
224 | function decipher( key, msg, flag ) {
225 | seed( key );
226 |
227 | if( Number( flag ) === 1 ) {
228 | return _vernam( _hexDecode( msg ) );
229 |
230 | } else {
231 | return _vernam( msg );
232 | }
233 | };
234 |
235 |
236 |
237 | /* public: return a 53-bit fraction in the range [0, 1] */
238 | function double() {
239 | return random() + ( random() * 0x200000 | 0 ) * 1.1102230246251565e-16; // 2^-53
240 | };
241 |
242 |
243 |
244 | /* public: return vernam transform on plaintext string data/hex string data */
245 | function encipher( key, msg, flag ) {
246 | seed( key );
247 |
248 | if( Number( flag ) === 1 ) {
249 | return _hexEncode( _vernam( msg ) );
250 |
251 | } else {
252 | return _vernam( msg );
253 | }
254 | };
255 |
256 |
257 |
258 | /* public: export object describing CSPRNG internal state */
259 | function get() {
260 | return JSON.stringify( _internals() );
261 | };
262 |
263 |
264 |
265 | /* public: return an unsigned random integer in the range [0, 2^32] */
266 | function int32() {
267 | var _r = rand();
268 | return _r < 0 ? -_r : _r;
269 | };
270 |
271 |
272 |
273 | /* public: expose internals */
274 | function internals() {
275 | return {
276 | a: acc
277 | , b: brs
278 | , c: cnt
279 | , m: m
280 | , r: r
281 | };
282 | };
283 |
284 |
285 |
286 | /* public: isaac generator, n = number of runs */
287 | function prng( n ){
288 | var i
289 | , x
290 | , y
291 | ;
292 |
293 | n = ( n && typeof n === 'number' ? Math.abs( Math.floor( n ) ) : 1 );
294 |
295 | while( n-- ) {
296 | cnt = _add( cnt, 1 );
297 | brs = _add( brs, cnt );
298 |
299 | for( i = 0; i < 256; i++ ) {
300 | switch( i & 3 ) {
301 | case 0: acc ^= acc << 13; break;
302 | case 1: acc ^= acc >>> 6; break;
303 | case 2: acc ^= acc << 2; break;
304 | case 3: acc ^= acc >>> 16; break;
305 | }
306 |
307 | acc = _add( m[ ( i + 128 ) & 0xff ], acc ); x = m[ i ];
308 | m[i] = y = _add( m[ ( x >>> 2 ) & 0xff ], _add( acc, brs ) );
309 | r[i] = brs = _add( m[ ( y >>> 10 ) & 0xff ], x );
310 | }
311 | }
312 | };
313 |
314 |
315 |
316 | /* public: return a signed random integer in the range [-2^31, 2^31] */
317 | function rand() {
318 | if( !gnt-- ) {
319 | prng();
320 | gnt = 255;
321 | }
322 |
323 | return r[ gnt ];
324 | };
325 |
326 |
327 |
328 | /* public: return a 32-bit fraction in the range [0, 1] */
329 | function random() {
330 | return 0.5 + rand() * 2.3283064365386963e-10; // 2^-32
331 | };
332 |
333 |
334 |
335 | /* public: return inclusive range */
336 | function range() {
337 | var loBound
338 | , hiBound
339 | ;
340 |
341 | if( arguments.length === 1 ) {
342 | loBound = 0;
343 | hiBound = arguments[ 0 ];
344 |
345 | } else {
346 | loBound = arguments[ 0 ];
347 | hiBound = arguments[ 1 ];
348 | }
349 |
350 | if( arguments[ 0 ] > arguments[ 1 ] ) {
351 | loBound = arguments[ 1 ];
352 | hiBound = arguments[ 0 ];
353 | }
354 |
355 | // return integer
356 | if( _isInteger( loBound ) && _isInteger( hiBound ) ) {
357 | return Math.floor( random() * ( hiBound - loBound + 1 ) ) + loBound;
358 |
359 | // return float
360 | } else {
361 | return random() * ( hiBound - loBound ) + loBound;
362 | }
363 | };
364 |
365 |
366 |
367 | /* public: zeroize the CSPRNG */
368 | function reset() {
369 | acc = brs = cnt = 0;
370 |
371 | for( var i = 0; i < 256; ++i ) {
372 | m[ i ] = r[ i ] = 0;
373 | }
374 |
375 | gnt = 0;
376 | };
377 |
378 |
379 |
380 | /* public: seeding function */
381 | function seed( seed ) {
382 | var a
383 | , b
384 | , c
385 | , d
386 | , e
387 | , f
388 | , g
389 | , h
390 | , i
391 | ;
392 |
393 | /* seeding the seeds of love */
394 | a = b = c = d = e = f = g = h =
395 |
396 | /* the golden ratio ( 2654435769 ),
397 | see https://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine
398 | */
399 | 0x9e3779b9
400 | ;
401 |
402 | if( seed && typeof seed === 'string' ) { seed = _toIntArray( seed ); }
403 |
404 | if( seed && typeof seed === 'number' ) { seed = [ seed ]; }
405 |
406 | if( seed instanceof Array ) {
407 | reset();
408 |
409 | for( i = 0; i < seed.length; i++ ) {
410 | r[ i & 0xff ] += ( typeof seed[ i ] === 'number' ? seed[ i ] : 0 );
411 | }
412 | }
413 |
414 | /* private: seed mixer */
415 | function _seed_mix() {
416 | a ^= b << 11; d = _add( d, a ); b = _add( b, c );
417 | b ^= c >>> 2; e = _add( e, b ); c = _add( c, d );
418 | c ^= d << 8; f = _add( f, c ); d = _add( d, e );
419 | d ^= e >>> 16; g = _add( g, d ); e = _add( e, f );
420 | e ^= f << 10; h = _add( h, e ); f = _add( f, g );
421 | f ^= g >>> 4; a = _add( a, f ); g = _add( g, h );
422 | g ^= h << 8; b = _add( b, g ); h = _add( h, a );
423 | h ^= a >>> 9; c = _add( c, h ); a = _add( a, b );
424 | }
425 |
426 | /* scramble it */
427 | for( i = 0; i < 4; i++ ) { _seed_mix(); }
428 |
429 | for( i = 0; i < 256; i += 8 ) {
430 |
431 | /* use all the information in the seed */
432 | if( seed ) {
433 | a = _add( a, r[ i + 0 ] ); b = _add( b, r[ i + 1 ] );
434 | c = _add( c, r[ i + 2 ] ); d = _add( d, r[ i + 3 ] );
435 | e = _add( e, r[ i + 4 ] ); f = _add( f, r[ i + 5 ] );
436 | g = _add( g, r[ i + 6 ] ); h = _add( h, r[ i + 7 ] );
437 | }
438 |
439 | _seed_mix();
440 |
441 | /* fill in m[] with messy stuff */
442 | m[ i + 0 ] = a; m[ i + 1 ] = b; m[ i + 2 ] = c; m[ i + 3 ] = d;
443 | m[ i + 4 ] = e; m[ i + 5 ] = f; m[ i + 6 ] = g; m[ i + 7 ] = h;
444 | }
445 |
446 | /* do a second pass to make all of the seed affect all of m[] */
447 | if( seed ) {
448 | for( i = 0; i < 256; i += 8 ) {
449 | a = _add( a, m[ i + 0 ] ); b = _add( b, m[ i + 1 ] );
450 | c = _add( c, m[ i + 2 ] ); d = _add( d, m[ i + 3 ] );
451 | e = _add( e, m[ i + 4 ] ); f = _add( f, m[ i + 5 ] );
452 | g = _add( g, m[ i + 6 ] ); h = _add( h, m[ i + 7 ] );
453 |
454 | _seed_mix();
455 |
456 | /* fill in m[] with messy stuff (again) */
457 | m[ i + 0 ] = a; m[ i + 1 ] = b; m[ i + 2 ] = c; m[ i + 3 ] = d;
458 | m[ i + 4 ] = e; m[ i + 5 ] = f; m[ i + 6 ] = g; m[ i + 7 ] = h;
459 | }
460 | }
461 |
462 | /* fill in the first set of results */
463 | prng();
464 |
465 | /* prepare to use the first set of results */;
466 | gnt = 256;
467 | };
468 |
469 |
470 |
471 | /* public: import object and use it to set CSPRNG internal state */
472 | function set( incoming ) {
473 | var imported = JSON.parse( incoming );
474 | acc = imported.a;
475 | brs = imported.b;
476 | cnt = imported.c;
477 | m = imported.m;
478 | r = imported.r;
479 | gnt = imported.g;
480 | };
481 |
482 |
483 |
484 | /* public: show version */
485 | function version() {
486 | return _version;
487 | };
488 |
489 |
490 |
491 | /* return class object */
492 | return {
493 | 'bytes' : bytes
494 | , 'chars' : chars
495 | , 'decipher' : decipher
496 | , 'double' : double
497 | , 'encipher' : encipher
498 | , 'export' : get
499 | , 'import' : set
500 | , 'int32' : int32
501 | , 'internals' : internals
502 | , 'prng' : prng
503 | , 'rand' : rand
504 | , 'range' : range
505 | , 'random' : random
506 | , 'reset' : reset
507 | , 'seed' : seed
508 | , 'version' : version
509 | };
510 |
511 | })( specifiedSeed );
512 | };
513 |
--------------------------------------------------------------------------------
/isaacCSPRNG-1.1.min.js:
--------------------------------------------------------------------------------
1 | /*///////////////////////////////////////////
2 | isaacCSPRNG 1.1
3 | https://github.com/macmcmeans/isaacCSPRNG/blob/master/isaacCSPRNG-1.1.min.js
4 | /////////////////////////////////////////////
5 | Copyright (c) 2018, William P. "Mac" McMeans
6 | LICENSE: BSD 3-Clause License
7 | */
8 | isaacCSPRNG=function(r){return function(r){"use strict";function n(r,n){var t=(65535&r)+(65535&n);return(r>>>16)+(n>>>16)+(t>>>16)<<16|65535&t}function t(r){return parseInt(r)===r}function e(r){for(var n="",t=0;t>>6;break;case 2:p^=p<<2;break;case 3:p^=p>>>16}p=n(h[t+128&255],p),e=h[t],h[t]=o=n(h[e>>>2&255],n(p,g)),b[t]=g=n(h[o>>>10&255],e)}}function u(){return l--||(o(),l=255),b[l]}function a(){return.5+2.3283064365386963e-10*u()}function f(){var r,n;return 1===arguments.length?(r=0,n=arguments[0]):(r=arguments[0],n=arguments[1]),arguments[0]>arguments[1]&&(r=arguments[1],n=arguments[0]),t(r)&&t(n)?Math.floor(a()*(n-r+1))+r:a()*(n-r)+r}function i(){p=g=v=0;for(var r=0;r<256;++r)h[r]=b[r]=0;l=0}function c(r){function t(){f=n(f,e^=u<<11),u=n(u,a),c=n(c,u^=a>>>2),a=n(a,f),s=n(s,a^=f<<8),f=n(f,c),p=n(p,f^=c>>>16),c=n(c,s),g=n(g,c^=s<<10),s=n(s,p),e=n(e,s^=p>>>4),p=n(p,g),u=n(u,p^=g<<8),g=n(g,e),a=n(a,g^=e>>>9),e=n(e,u)}var e,u,a,f,c,s,p,g,v;if(e=u=a=f=c=s=p=g=2654435769,r&&"string"==typeof r&&(r=function(r){for(var n,t,e,o=[],u=[],a=0,f=r+"\0\0\0",i=f.length-1;a>>6&31|192),o.push(n>>>0&63|128)):55296!=(63488&n)?(o.push(n>>>12&15|224),o.push(n>>>6&63|128),o.push(n>>>0&63|128)):55296==(64512&n)&&56320==(64512&t)&&(e=65536+(63&t|(63&n)<<10),o.push(e>>>18&7|240),o.push(e>>>12&63|128),o.push(e>>>6&63|128),o.push(e>>>0&63|128),a++),o.length>3&&u.push(o.shift()<<0|o.shift()<<8|o.shift()<<16|o.shift()<<24);return u}(r)),r&&"number"==typeof r&&(r=[r]),r instanceof Array)for(i(),v=0;v