blob: 3245eabb7473332b35948c67d24fcf418825f32b [file] [log] [blame]
package org.bouncycastle.crypto.prng;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
/**
* A secure random that returns pre-seeded data to calls of nextBytes() or generateSeed().
*/
public class FixedSecureRandom
extends SecureRandom
{
private byte[] _data;
private int _index;
private int _intPad;
public FixedSecureRandom(byte[] value)
{
this(false, new byte[][] { value });
}
public FixedSecureRandom(
byte[][] values)
{
this(false, values);
}
/**
* Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
* implementation.
*/
public FixedSecureRandom(
boolean intPad,
byte[] value)
{
this(intPad, new byte[][] { value });
}
/**
* Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
* implementation.
*/
public FixedSecureRandom(
boolean intPad,
byte[][] values)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
for (int i = 0; i != values.length; i++)
{
try
{
bOut.write(values[i]);
}
catch (IOException e)
{
throw new IllegalArgumentException("can't save value array.");
}
}
_data = bOut.toByteArray();
if (intPad)
{
_intPad = _data.length % 4;
}
}
public void nextBytes(byte[] bytes)
{
System.arraycopy(_data, _index, bytes, 0, bytes.length);
_index += bytes.length;
}
public byte[] generateSeed(int numBytes)
{
byte[] bytes = new byte[numBytes];
this.nextBytes(bytes);
return bytes;
}
//
// classpath's implementation of SecureRandom doesn't currently go back to nextBytes
// when next is called. We can't override next as it's a final method.
//
public int nextInt()
{
int val = 0;
val |= nextValue() << 24;
val |= nextValue() << 16;
if (_intPad == 2)
{
_intPad--;
}
else
{
val |= nextValue() << 8;
}
if (_intPad == 1)
{
_intPad--;
}
else
{
val |= nextValue();
}
return val;
}
//
// classpath's implementation of SecureRandom doesn't currently go back to nextBytes
// when next is called. We can't override next as it's a final method.
//
public long nextLong()
{
long val = 0;
val |= (long)nextValue() << 56;
val |= (long)nextValue() << 48;
val |= (long)nextValue() << 40;
val |= (long)nextValue() << 32;
val |= (long)nextValue() << 24;
val |= (long)nextValue() << 16;
val |= (long)nextValue() << 8;
val |= (long)nextValue();
return val;
}
public boolean isExhausted()
{
return _index == _data.length;
}
private int nextValue()
{
return _data[_index++] & 0xff;
}
}