// AES based pseudorandom number generator /* Constructor. Called with an array of 32 byte (0-255) values containing the initial seed. */ function AESprng(seed) { this.key = new Array(); this.key = seed; this.itext = hexToByteArray("9F489613248148F9C27945C6AE62EECA3E3367BB14064E4E6DC67A9F28AB3BD1"); this.nbytes = 0; // Bytes left in buffer this.next = AESprng_next; this.nextbits = AESprng_nextbits; this.nextInt = AESprng_nextInt; this.round = AESprng_round; /* Encrypt the initial text with the seed key three times, feeding the output of the encryption back into the key for the next round. */ bsb = blockSizeInBits; blockSizeInBits = 256; var i, ct; for (i = 0; i < 3; i++) { this.key = rijndaelEncrypt(this.itext, this.key, "ECB"); } /* Now make between one and four additional key-feedback rounds, with the number determined by bits from the result of the first three rounds. */ var n = 1 + (this.key[3] & 2) + (this.key[9] & 1); for (i = 0; i < n; i++) { this.key = rijndaelEncrypt(this.itext, this.key, "ECB"); } blockSizeInBits = bsb; } function AESprng_round() { bsb = blockSizeInBits; blockSizeInBits = 256; this.key = rijndaelEncrypt(this.itext, this.key, "ECB"); this.nbytes = 32; blockSizeInBits = bsb; } // Return next byte from the generator function AESprng_next() { if (this.nbytes <= 0) { this.round(); } return(this.key[--this.nbytes]); } // Return n bit integer value (up to maximum integer size) function AESprng_nextbits(n) { var i, w = 0, nbytes = Math.floor((n + 7) / 8); for (i = 0; i < nbytes; i++) { w = (w << 8) | this.next(); } return w & ((1 << n) - 1); } // Return integer between 0 and n inclusive function AESprng_nextInt(n) { var p = 1, nb = 0; // Determine smallest p, 2^p > n // nb = log_2 p while (n >= p) { p <<= 1; nb++; } p--; /* Generate values from 0 through n by first generating values v from 0 to (2^p)-1, then discarding any results v > n. For the rationale behind this (and why taking values mod (n + 1) is biased toward smaller values, see Ferguson and Schneier, "Practical Cryptography", ISBN 0-471-22357-3, section 10.8). */ while (true) { var v = this.nextbits(nb) & p; if (v <= n) { return v; } } }