// Cryptographically secure random number generator.
// Needs good initial seed.
// RFC 4086.

var ZERO_ARRAY = generate_array(1, 0);
var UNITY_ARRAY = generate_array(1, 1);

function generate_array(size, value)
{
    var result = new Array(size);

    for (var i = 0; i < size; i++) {
	result[i] = value;
    }

    return result;
}

function Randpool(hmac_object, entropy)
{
    var hash_size = hmac_object.output_size();

    this.hmac_object = hmac_object;
    this.hash_size = function() { return hash_size; };
    this.hmac = function(key, text) { return this.hmac_object.calculate(key, text); };
    this.get_bytes = Randpool_get_bytes;

    this.V = generate_array(hash_size, 1);
    this.K = generate_array(hash_size, 0);

    this.K = this.hmac(this.K, this.V.concat(ZERO_ARRAY, entropy));
    this.V = this.hmac(this.K, this.V);

    this.K = this.hmac(this.K, this.V.concat(UNITY_ARRAY, entropy));
    this.V = this.hmac(this.K, this.V);

    this.pool = new Array();
    this.pool_size = 0;
}

function Randpool_get_bytes(count)
{
    var increment = this.hash_size();
    var result;

    if (this.pool_size < count) {
	do {
	    this.V = this.hmac(this.K, this.V);

	    this.pool = this.pool.concat(this.V);
	    this.pool_size += increment;
	} while (this.pool_size < count);

	this.K = this.hmac(this.K, this.V.concat(ZERO_ARRAY));
	this.V = this.hmac(this.K, this.V);
    }


    result = this.pool.slice(0, count);
    this.pool = this.pool.slice(count);
    this.pool_size = this.pool_size - count;

    return result;
}

