123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- package com.oblivm.backend.rand;
- import java.security.SecureRandom;
- import java.security.SecureRandomSpi;
- /**
- * This class defines the Service Provider for the ISAAC algorithm.
- *
- * @author Daniel Berlin
- */
- public class ISAACEngine extends SecureRandomSpi {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private ISAACAlgorithm isaac;
- private byte[] remainder;
- private int remCount = 0;
- /**
- * Creates a new instance and seeds it with random data obtained from
- * <code>java.security.SecureRandom</code>'s <code>getSeed()</code> method.
- */
- public ISAACEngine() {
- byte[] temp = new byte[1024];// SecureRandom.getSeed (1024);
- new SecureRandom().nextBytes(temp);
- this.isaac = new ISAACAlgorithm(ISAACEngine.packToIntArray(temp));
- }
- /**
- * Returns the given number of seed bytes computed using the ISAAC
- * algorithm.<br>
- * It just calls <code>engineNextBytes()</code> internally.<br>
- * This call may be used to seed other random number generators.
- *
- * @param numBytes
- * The number of seed bytes to generate.
- * @return The seed bytes.
- */
- public byte[] engineGenerateSeed(int numBytes) {
- byte[] seed = new byte[numBytes];
- this.engineNextBytes(seed);
- return (seed);
- }
- /**
- * Generates a user-specified number of random bytes.
- *
- * @param bytes
- * The array to fill with random bytes.
- */
- public void engineNextBytes(byte[] bytes) {
- int index = 0;
- int todo;
- byte[] output = this.remainder;
- // First use remainder from last time
- int rC = this.remCount;
- if (rC > 0) {
- todo = (bytes.length - index) < (4 - rC) ? (bytes.length - index) : (4 - rC);
- for (int i = 0; i < todo; i++, rC++)
- bytes[i] = output[rC];
- this.remCount += todo;
- index += todo;
- }
- // If we need more bytes, get them
- while (index < bytes.length) {
- output = ISAACEngine.toByteArray(this.isaac.nextInt());
- todo = (bytes.length - index) > 4 ? 4 : (bytes.length - index);
- for (int i = 0; i < todo; i++, index++)
- bytes[index] = output[i];
- this.remCount += todo;
- }
- // Store remainder for next time
- this.remainder = output;
- this.remCount %= 4;
- }
- /**
- * Reseeds this random object. The given seed supplements, rather than
- * replaces, the existing seed.
- *
- * @param seed
- * The seed.
- */
- public void engineSetSeed(byte[] seed) {
- this.isaac.supplementSeed(ISAACEngine.packToIntArray(seed));
- }
- // ====================================
- // ===== private "helper" methods =====
- // ====================================
- private static final int[] mask = new int[] { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF };
- /**
- * Returns a byte array containing the two's-complement representation of
- * the integer.<br>
- * The byte array will be in big-endian byte-order with a fixes length of 4
- * (the least significant byte is in the 4th element).<br>
- * <br>
- * <u>Example:</u><br>
- * <code>toByteArray(258)</code> returns { 0, 0, 1, 2 },<br>
- * <code>BigInteger.valueOf(258).toByteArray()</code> returns { 1, 2 }.
- *
- * @param intValue
- * The integer to be converted.
- * @return The byte array of length 4.
- */
- private static byte[] toByteArray(final int intValue) {
- int byteNum = (40 - numberOfLeadingZeros(intValue < 0 ? ~intValue : intValue)) / 8;
- byte[] byteArray = new byte[4];
- for (int i = 0; i < byteNum; i++)
- byteArray[3 - i] = (byte) (intValue >>> (i * 8));
- return (byteArray);
- }
- /**
- * Returns the number of zero bits preceding the highest-order ("leftmost")
- * one-bit in the two's complement binary representation of the specified
- * integer value.
- *
- * @return The number of zero bits preceding the highest-order one-bit in
- * the two's complement binary representation of the specified
- * integer value, or 32 if the value is equal to zero.
- */
- private static int numberOfLeadingZeros(int intValue) {
- if (intValue == 0)
- return (32);
- int num = 1;
- for (int i = 16, j = 16; j > 1; i += j) {
- if (intValue >>> i == 0) {
- num += j;
- intValue <<= j;
- }
- j /= 2;
- }
- num -= intValue >>> 31;
- return (num);
- }
- /**
- * Creates an array of integers and "packs" the bytes from the byte array
- * into it.<br>
- * This method returns an integer array of length zero if <code>ba</code> is
- * <code>null</code>.<br>
- * <br>
- * <u>Example:</u><br>
- * <code>packToIntArray(new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5 })</code>
- * returns an integer array<br>
- * containing the values <code>0x01020304</code> and <code>0x00000005</code>
- * .
- *
- * @param ba
- * The byte array, may be <code>null</code>.
- * @return An array of integers containing the "packed" byte(s).
- */
- private static int[] packToIntArray(final byte[] ba) {
- if (ba == null)
- return (new int[0]);
- int[] ia = new int[(ba.length + 3) / 4];
- for (int i = 0; i < ia.length; i++) {
- int restLen = Math.min(4, ba.length - i * 4);
- for (int b = 0; b < restLen; b++)
- ia[i] |= (ba[b + i * 4] << ((restLen - b - 1) * 8)) & mask[b + 4 - restLen];
- }
- return (ia);
- }
- }
|