| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| /* |
| * Cryptographic strong random number generator |
| * |
| * Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers |
| * Slow - but secure |
| * |
| * See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification |
| */ |
| |
| /* Marsaglia & Zaman Random number generator constants */ |
| |
| |
| var RAND=function() |
| { |
| /* Cryptographically strong pseudo-random number generator */ |
| this.ira=[]; /* random number... */ |
| this.rndptr=0; /* ...array & pointer */ |
| this.borrow=0; |
| this.pool_ptr=0; |
| this.pool=[]; /* random pool */ |
| this.clean(); |
| }; |
| |
| RAND.prototype= |
| { |
| NK:21, |
| NJ:6, |
| NV:8, |
| |
| /* Terminate and clean up */ |
| clean : function() |
| { |
| var i; |
| for (i=0;i<32;i++) this.pool[i]=0; |
| for (i=0;i<this.NK;i++) this.ira[i]=0; |
| this.rndptr=0; |
| this.borrow=0; |
| this.pool_ptr=0; |
| }, |
| |
| sbrand: function() |
| { /* Marsaglia & Zaman random number generator */ |
| var i,k; |
| var pdiff,t; /* unsigned 32-bit */ |
| |
| this.rndptr++; |
| if (this.rndptr<this.NK) return this.ira[this.rndptr]; |
| this.rndptr=0; |
| for (i=0,k=this.NK-this.NJ;i<this.NK;i++,k++) |
| { /* calculate next NK values */ |
| if (k==this.NK) k=0; |
| t=this.ira[k]>>>0; |
| pdiff=(t - this.ira[i] - this.borrow)|0; |
| pdiff>>>=0; /* This is seriously wierd shit. I got to do this to get a proper unsigned comparison... */ |
| if (pdiff<t) this.borrow=0; |
| if (pdiff>t) this.borrow=1; |
| this.ira[i]=(pdiff|0); |
| } |
| return this.ira[0]; |
| }, |
| |
| sirand: function(seed) |
| { |
| var i,inn; |
| var t,m=1; |
| this.borrow=0; |
| this.rndptr=0; |
| seed>>>=0; |
| this.ira[0]^=seed; |
| |
| for (i=1;i<this.NK;i++) |
| { /* fill initialisation vector */ |
| inn=(this.NV*i)%this.NK; |
| this.ira[inn]^=m; /* note XOR */ |
| t=m; |
| m=(seed-m)|0; |
| seed=t; |
| } |
| |
| for (i=0;i<10000;i++) this.sbrand(); /* "warm-up" & stir the generator */ |
| }, |
| |
| fill_pool: function() |
| { |
| var sh=new HASH256(); |
| for (var i=0;i<128;i++) sh.process(this.sbrand()); |
| this.pool=sh.hash(); |
| this.pool_ptr=0; |
| }, |
| |
| /* Initialize RNG with some real entropy from some external source */ |
| seed: function(rawlen,raw) |
| { /* initialise from at least 128 byte string of raw random entropy */ |
| var i; |
| var digest=[]; |
| var b=[]; |
| var sh=new HASH256(); |
| this.pool_ptr=0; |
| for (i=0;i<this.NK;i++) this.ira[i]=0; |
| if (rawlen>0) |
| { |
| for (i=0;i<rawlen;i++) |
| sh.process(raw[i]); |
| digest=sh.hash(); |
| |
| /* initialise PRNG from distilled randomness */ |
| for (i=0;i<8;i++) |
| { |
| b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]; |
| this.sirand(RAND.pack(b)); |
| } |
| } |
| this.fill_pool(); |
| }, |
| |
| /* get random byte */ |
| getByte: function() |
| { |
| var r=this.pool[this.pool_ptr++]; |
| if (this.pool_ptr>=32) this.fill_pool(); |
| return (r&0xff); |
| } |
| }; |
| |
| RAND.pack= function(b) |
| { /* pack 4 bytes into a 32-bit Word */ |
| return (((b[3])&0xff)<<24)|((b[2]&0xff)<<16)|((b[1]&0xff)<<8)|(b[0]&0xff); |
| }; |
| |