123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- package com.oblivm.backend.rand;
- import java.security.SecureRandom;
- import java.security.SecureRandomSpi;
- public class ISAACEngine extends SecureRandomSpi {
-
- private static final long serialVersionUID = 1L;
- private ISAACAlgorithm isaac;
- private byte[] remainder;
- private int remCount = 0;
-
- public ISAACEngine() {
- byte[] temp = new byte[1024];
- new SecureRandom().nextBytes(temp);
- this.isaac = new ISAACAlgorithm(ISAACEngine.packToIntArray(temp));
- }
-
- public byte[] engineGenerateSeed(int numBytes) {
- byte[] seed = new byte[numBytes];
- this.engineNextBytes(seed);
- return (seed);
- }
-
- public void engineNextBytes(byte[] bytes) {
- int index = 0;
- int todo;
- byte[] output = this.remainder;
-
- 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;
- }
-
- 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;
- }
-
- this.remainder = output;
- this.remCount %= 4;
- }
-
- public void engineSetSeed(byte[] seed) {
- this.isaac.supplementSeed(ISAACEngine.packToIntArray(seed));
- }
-
-
-
- private static final int[] mask = new int[] { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF };
-
- 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);
- }
-
- 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);
- }
-
- 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);
- }
- }
|