/*
 * Copyright (c) 2003-2005  Tom Wu
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 *
 * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * In addition, the following condition applies:
 *
 * All redistributions must retain an intact copy of this copyright notice
 * and disclaimer.
 */


// Random number generator - requires a PRNG backend, e.g. prng4.js

// For best results, put code like
// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
// in your main HTML document.

var rng_state = null;
var rng_pool  = null;
var rng_pptr  = null;

// Konstruktor fuer SecureRandom

function SecureRandom() 
{
	this.nextBytes = rng_get_bytes;
}

// Mix in a 32-bit integer into the pool
function rng_seed_int(x) 
{
	rng_pool[rng_pptr++] ^= x & 255;
	rng_pool[rng_pptr++] ^= (x >> 8) & 255;
	rng_pool[rng_pptr++] ^= (x >> 16) & 255;
	rng_pool[rng_pptr++] ^= (x >> 24) & 255;
	
	if( rng_pptr >= rng_psize )
	{
		rng_pptr -= rng_psize;
	}
}

// Mix in the current time (w/milliseconds) into the pool
function rng_seed_time() 
{
	rng_seed_int( new Date().getTime() );
}

// Initialize the pool with junk if needed.

if( rng_pool == null ) 
{
	rng_pool = new Array();
	rng_pptr = 0;
	
	if( ( navigator.appName == "Netscape" ) && ( navigator.appVersion < "5" ) && ( window.crypto ) ) 
	{
		// Extract entropy (256 bits) from NS4 RNG if available 
		
		// FIXME (8.x) Das geht nur im NS4. Brauchen wir das dann?
		
		var randomString = window.crypto.random(32);
		
		for( var counter = 0; counter < randomString.length; ++counter ) 
		{
			rng_pool[rng_pptr++] = randomString.charCodeAt( counter ) & 255;
		}
	}
	
	// extract some randomness from Math.random()
	
	var tempRandom = null;
	
	while(rng_pptr < rng_psize) 
	{  
		tempRandom = Math.floor( 65536 * Math.random() );
		
		rng_pool[rng_pptr++] = tempRandom >>> 8;
		rng_pool[rng_pptr++] = tempRandom & 255;
	}
	
	rng_pptr = 0;
	rng_seed_time();
}

function rng_get_byte() 
{
	if( rng_state == null ) {
		
		rng_seed_time();
		
		rng_state = prng_newstate();
		
		rng_state.init( rng_pool );
		
		for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) 
		{
			rng_pool[rng_pptr] = 0;
		}
		
		rng_pptr = 0;
	}

	// TODO: allow reseeding after first request
	
	return ( rng_state.next() );
}

function rng_get_bytes( byteArray ) {
	
	for( var counter = 0; counter < byteArray.length; ++counter) 
	{
		byteArray[counter] = rng_get_byte();
	}
}

