/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.rng; import java.io.Serializable; /** * Implements a RNG using the Rijndael block cipher algorithm * (AES) with key and block lengths of 128 bits. A block of 128 bits is * encrypted by the Rijndael algorithm to generate 128 * pseudo-random bits. Those bits are split into four words of 32 bits which are * returned successively by the method nextValue. * The unencrypted block is the state of the generator. * It is incremented by 1 at every four calls to nextValue. * Thus, the period is 2130 and jumping ahead is easy. * The values of V, W and Z are 240, 242 and 282, * respectively (see {@link RandomStream} for their definition). * Seeds/states must be given as 16-dimensional * vectors of bytes (8-bit integers). * The default initial seed is a vector filled with zeros. * *

* The Rijndael implementation used here is that of the * Cryptix Development Team, which can be found on the * Rijndael creators' page * . * */ public class RandRijndael extends RandomStreamBase { private static final long serialVersionUID = 70510L; //La date de modification a l'envers, lire 10/05/2007 private static final int BLOCK_SIZE = 16; private static final int JUMP_STREAM = 10; private static final int JUMP_SUBSTREAM = 5; //actually a Object[] containing 2 int[][] private static Object key; private static byte[] curr_stream; private byte[] stream; private byte[] substream; private byte[] state; private byte[] output; private int outputPos; static { try { key = Rijndael_Algorithm.makeKey(new byte[]{1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16}, BLOCK_SIZE); } catch(Exception e) { //pour que Java soit certain que la clef est initialisee key = new Object[0]; System.exit(1); } curr_stream = new byte[BLOCK_SIZE]; for(int i = 0; i < BLOCK_SIZE; i++) curr_stream[i] = 0; } private static void iterate (byte[] b, int pos) { while((pos < b.length) && (++b[pos++] == 0)); } /** * Constructs a new stream. * */ public RandRijndael() { stream = new byte[BLOCK_SIZE]; substream = new byte[BLOCK_SIZE]; state = new byte[BLOCK_SIZE]; for(int i = 0; i < BLOCK_SIZE; i++) stream[i] = curr_stream[i]; iterate(curr_stream, JUMP_STREAM); resetStartStream(); } /** * Constructs a new stream with the identifier name * (used in the toString method). * * @param name name of the stream * */ public RandRijndael (String name) { this(); this.name = name; } /** * Sets the initial seed for the class RandRijndael to the * 16 bytes of the vector seed[0..15]. * This will be the initial state (or seed) of the next created stream. * The default seed for the first stream is * (0, 0,…, 0, 0). * * @param seed array of 16 elements representing the seed * * */ public static void setPackageSeed (byte seed[]) { if(seed.length != BLOCK_SIZE) throw new IllegalArgumentException("Seed must contain " + BLOCK_SIZE + " values"); for(int i = 0; i < BLOCK_SIZE; i++) curr_stream[i] = seed[i]; } /** * This method is discouraged for normal use. * Initializes the stream at the beginning of a stream with the initial * seed seed[0..15]. * This method only affects the specified stream; the others are not modified, * so the beginning of the streams will not be spaced Z values apart. * For this reason, this method should only be used in very * exceptional cases; proper use of the reset... methods * and of the stream constructor is preferable. * * @param seed array of 16 elements representing the seed * * */ public void setSeed (byte seed[]) { if(seed.length != BLOCK_SIZE) throw new IllegalArgumentException("Seed must contain " + BLOCK_SIZE + " values"); for(int i = 0; i < BLOCK_SIZE; i++) stream[i] = seed[i]; } /** * Returns the current state of the stream, represented as an * array of four integers. * It should be noted that each state of this generator returns 4 successive * values. The particular value of these 4 which will be returned next is not * given by this method. * * @return the current state of the stream * */ public byte[] getState() { byte[] stateCopy = new byte[BLOCK_SIZE]; for(int i = 0; i < BLOCK_SIZE; i++) stateCopy[i] = state[i]; return stateCopy; } /** * Clones the current generator and return its copy. * * @return A deep copy of the current generator * */ public RandRijndael clone() { RandRijndael retour = null; retour = (RandRijndael)super.clone(); retour.stream = new byte[BLOCK_SIZE]; retour.substream = new byte[BLOCK_SIZE]; retour.state = new byte[BLOCK_SIZE]; retour.output = new byte[output.length]; for (int i = 0; i BLOCK_SIZE - 4) nextOutput(); long val = output[outputPos++] & 0xFF; val <<= 8; val |= output[outputPos++] & 0xFF; val <<= 8; val |= output[outputPos++] & 0xFF; val <<= 8; val |= output[outputPos++] & 0xFF; /* long val = ((output[outputPos] & 0xFF) << 24) | ((output[outputPos + 1] & 0xFF) << 16) | ((output[outputPos + 2] & 0xFF) << 8) | ((output[outputPos + 3] & 0xFF)); outputPos += 4; */ return ((double)val + 1) / 0x100000001L; } /* public static void main(String args[]) { int num = Integer.parseInt(args[0]); RandomStream rng = new RandRijn(); for(int i = 0; i < num; i++) { rng.nextDouble(); //System.out.println(rng.nextDouble()); } System.out.println(rng.toString()); } */ }

Ads help maintain this website.