diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java')
-rw-r--r-- | libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java | 1019 |
1 files changed, 368 insertions, 651 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java b/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java index 6585dcb907a..2cf75a96644 100644 --- a/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java +++ b/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.javax.crypto.prng; +import gnu.java.security.Configuration; import gnu.java.security.Properties; import gnu.java.security.Registry; import gnu.java.security.hash.HashFactory; @@ -48,7 +49,6 @@ import gnu.java.security.prng.IRandom; import gnu.java.security.prng.LimitReachedException; import gnu.java.security.util.SimpleList; import gnu.java.security.util.Util; - import gnu.javax.crypto.cipher.CipherFactory; import gnu.javax.crypto.cipher.IBlockCipher; @@ -56,15 +56,11 @@ import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.PrintStream; - import java.net.MalformedURLException; import java.net.URL; - import java.security.AccessController; import java.security.InvalidKeyException; import java.security.PrivilegedAction; - -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -73,115 +69,85 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; /** - * <p>An entropy pool-based pseudo-random number generator based on the PRNG - * in Peter Gutmann's cryptlib (<a - * href="http://www.cs.auckland.ac.nz/~pgut001/cryptlib/">http://www.cs.auckland.ac.nz/~pgut001/cryptlib/</a>).</p> - * - * <p>The basic properties of this generator are:</p> - * + * An entropy pool-based pseudo-random number generator based on the PRNG in + * Peter Gutmann's cryptlib (<a + * href="http://www.cs.auckland.ac.nz/~pgut001/cryptlib/">http://www.cs.auckland.ac.nz/~pgut001/cryptlib/</a>). + * <p> + * The basic properties of this generator are: * <ol> * <li>The internal state cannot be determined by knowledge of the input.</li> * <li>It is resistant to bias introduced by specific inputs.</li> * <li>The output does not reveal the state of the generator.</li> * </ol> */ -public class CSPRNG extends BasePRNG +public class CSPRNG + extends BasePRNG { - - // Constants and fields. - // ------------------------------------------------------------------------- - - private static final boolean DEBUG = false; - - private static void debug(String msg) - { - System.err.print(">>> CSPRNG: "); - System.err.println(msg); - } - + private static final Logger log = Logger.getLogger(CSPRNG.class.getName()); /** - * Property name for the list of files to read for random values. The - * mapped value is a list with the following values: - * + * Property name for the list of files to read for random values. The mapped + * value is a list with the following values: * <ol> * <li>A {@link Double}, indicating the suggested <i>quality</i> of this * source. This value must be between 0 and 100.</li> - * <li>An {@link Integer}, indicating the number of bytes to skip in the file - * before reading bytes. This can be any nonnegative value.</li> + * <li>An {@link Integer}, indicating the number of bytes to skip in the + * file before reading bytes. This can be any nonnegative value.</li> * <li>An {@link Integer}, indicating the number of bytes to read.</li> * <li>A {@link String}, indicating the path to the file.</li> * </ol> - * - * @see gnu.crypto.util.SimpleList + * + * @see gnu.java.security.util.SimpleList */ public static final String FILE_SOURCES = "gnu.crypto.prng.pool.files"; - /** - * Property name for the list of URLs to poll for random values. The - * mapped value is a list formatted similarly as in {@link #FILE_SOURCES}, - * but the fourth member is a {@link URL}. + * Property name for the list of URLs to poll for random values. The mapped + * value is a list formatted similarly as in {@link #FILE_SOURCES}, but the + * fourth member is a {@link URL}. */ public static final String URL_SOURCES = "gnu.crypto.prng.pool.urls"; - /** - * Property name for the list of programs to execute, and use the output - * as new random bytes. The mapped property is formatted similarly an in - * {@link #FILE_SOURCES} and {@link #URL_SOURCES}, except the fourth - * member is a {@link String} of the program to execute. + * Property name for the list of programs to execute, and use the output as + * new random bytes. The mapped property is formatted similarly an in + * {@link #FILE_SOURCES} and {@link #URL_SOURCES}, except the fourth member + * is a {@link String} of the program to execute. */ public static final String PROGRAM_SOURCES = "gnu.crypto.prng.pool.programs"; - /** - * Property name for a list of other sources of entropy. The mapped - * value must be a list of {@link EntropySource} objects. + * Property name for a list of other sources of entropy. The mapped value must + * be a list of {@link EntropySource} objects. */ public static final String OTHER_SOURCES = "gnu.crypto.prng.pool.other"; - /** - * Property name for whether or not to wait for the slow poll to - * complete, passed as a {@link Boolean}. The default value is true. + * Property name for whether or not to wait for the slow poll to complete, + * passed as a {@link Boolean}. The default value is true. */ public static final String BLOCKING = "gnu.crypto.prng.pool.blocking"; - private static final String FILES = "gnu.crypto.csprng.file."; - private static final String URLS = "gnu.crypto.csprng.url."; - private static final String PROGS = "gnu.crypto.csprng.program."; - private static final String OTHER = "gnu.crypto.csprng.other."; - private static final String BLOCK = "gnu.crypto.csprng.blocking"; - private static final int POOL_SIZE = 256; - private static final int ALLOC_SIZE = 260; - private static final int OUTPUT_SIZE = POOL_SIZE / 2; - private static final int X917_POOL_SIZE = 16; - private static final String HASH_FUNCTION = Registry.SHA160_HASH; - private static final String CIPHER = Registry.AES_CIPHER; - private static final int MIX_COUNT = 10; - private static final int X917_LIFETIME = 8192; - // FIXME this should be configurable. private static final int SPINNER_COUNT = 8; - /** * The spinner group singleton. We use this to add a small amount of - * randomness (in addition to the current time and the amount of - * free memory) based on the randomness (if any) present due to - * system load and thread scheduling. + * randomness (in addition to the current time and the amount of free memory) + * based on the randomness (if any) present due to system load and thread + * scheduling. */ private static final Spinner[] SPINNERS = new Spinner[SPINNER_COUNT]; - private static final Thread[] SPINNER_THREADS = new Thread[SPINNER_COUNT]; static { @@ -194,87 +160,38 @@ public class CSPRNG extends BasePRNG SPINNER_THREADS[i].start(); } } - - /** - * The message digest (SHA-1) used in the mixing function. - */ + /** The message digest (SHA-1) used in the mixing function. */ private final IMessageDigest hash; - - /** - * The cipher (AES) used in the output masking function. - */ + /** The cipher (AES) used in the output masking function. */ private final IBlockCipher cipher; - - /** - * The number of times the pool has been mixed. - */ + /** The number of times the pool has been mixed. */ private int mixCount; - - /** - * The entropy pool. - */ + /** The entropy pool. */ private final byte[] pool; - - /** - * The quality of the random pool (percentage). - */ + /** The quality of the random pool (percentage). */ private double quality; - - /** - * The index of the next byte in the entropy pool. - */ + /** The index of the next byte in the entropy pool. */ private int index; - - /** - * The pool for the X9.17-like generator. - */ + /** The pool for the X9.17-like generator. */ private byte[] x917pool; - - /** - * The number of iterations of the X9.17-like generators. - */ + /** The number of iterations of the X9.17-like generators. */ private int x917count; - - /** - * Whether or not the X9.17-like generator is initialized. - */ + /** Whether or not the X9.17-like generator is initialized. */ private boolean x917init; - - /** - * The list of file soures. - */ + /** The list of file soures. */ private final List files; - - /** - * The list of URL sources. - */ + /** The list of URL sources. */ private final List urls; - - /** - * The list of program sources. - */ + /** The list of program sources. */ private final List progs; - - /** - * The list of other sources. - */ + /** The list of other sources. */ private final List other; - - /** - * Whether or not to wait for the slow poll to complete. - */ + /** Whether or not to wait for the slow poll to complete. */ private boolean blocking; - - /** - * The thread that polls for random data. - */ + /** The thread that polls for random data. */ private Poller poller; - private Thread pollerThread; - // Constructor. - // ------------------------------------------------------------------------- - public CSPRNG() { super("CSPRNG"); @@ -294,69 +211,75 @@ public class CSPRNG extends BasePRNG other = new LinkedList(); } - // Class methods. - // ------------------------------------------------------------------------- - /** - * <p>Create and initialize a CSPRNG instance with the "system" parameters; - * the files, URLs, programs, and {@link EntropySource} sources used by - * the instance are derived from properties set in the system {@link - * Properties}.</p> - * - * <p>All properties are of the from <i>name</i>.</i>N</i>, where <i>name</i> + * Create and initialize a CSPRNG instance with the "system" parameters; the + * files, URLs, programs, and {@link EntropySource} sources used by the + * instance are derived from properties set in the system {@link Properties}. + * <p> + * All properties are of the from <i>name</i>.</i>N</i>, where <i>name</i> * is the name of the source, and <i>N</i> is an integer (staring at 1) that - * indicates the preference number for that source.</p> - * - * <p>The following vales for <i>name</i> are used here:</p> - * + * indicates the preference number for that source. + * <p> + * The following vales for <i>name</i> are used here: * <dl> * <dt>gnu.crypto.csprng.file</dt> - * <dd><p>These properties are file sources, passed as the {@link #FILE_SOURCES} - * parameter of the instance. The property value is a 4-tuple formatted as:</p> - * + * <dd> + * <p> + * These properties are file sources, passed as the {@link #FILE_SOURCES} + * parameter of the instance. The property value is a 4-tuple formatted as: + * </p> * <blockquote><i>quality</i> ; <i>offset</i> ; <i>count</i> ; <i>path</i></blockquote> - * - * <p>The parameters are mapped to the parameters defined for {@link - * #FILE_SOURCES}. Leading or trailing spaces on any item are trimmed - * off.</p></dd> - * + * <p> + * The parameters are mapped to the parameters defined for {@link + * #FILE_SOURCES}. Leading or trailing spaces on any item are trimmed off. + * </p> + * </dd> * <dt>gnu.crypto.csprng.url</dt> - * <dd><p>These properties are URL sources, passed as the {@link #URL_SOURCES} + * <dd> + * <p> + * These properties are URL sources, passed as the {@link #URL_SOURCES} * parameter of the instance. The property is formatted the same way as file - * sources, but the <i>path</i> argument must be a valid URL.</p></dd> - * + * sources, but the <i>path</i> argument must be a valid URL. + * </p> + * </dd> * <dt>gnu.crypto.csprng.program</dt> - * <dd><p>These properties are program sources, passed as the {@link - * #PROGRAM_SOURCES} parameter of the instance. This property is formatted - * the same way as file and URL sources, but the last argument is a program - * and its arguments.</p></dd> - * + * <dd> + * <p> + * These properties are program sources, passed as the {@link + * #PROGRAM_SOURCES} parameter of the instance. This property is formatted the + * same way as file and URL sources, but the last argument is a program and + * its arguments. + * </p> + * </dd> * <dt>gnu.crypto.cspring.other</dt> - * <dd><p>These properties are other sources, passed as the {@link OTHER_SOURCES} - * parameter of the instance. The property value must be the full name - * of a class that implements the {@link EntropySource} interface and has a - * public no-argument constructor.</p></dd> + * <dd> + * <p> + * These properties are other sources, passed as the {@link #OTHER_SOURCES} + * parameter of the instance. The property value must be the full name of a + * class that implements the {@link EntropySource} interface and has a public + * no-argument constructor. + * </p> + * </dd> * </dl> - * - * <p>Finally, a boolean property "gnu.crypto.csprng.blocking" can be set to - * the desired value of {@link #BLOCKING}.</p> - * - * <p>An example of valid properties would be:</p> - * + * <p> + * Finally, a boolean property "gnu.crypto.csprng.blocking" can be set to the + * desired value of {@link #BLOCKING}. + * <p> + * An example of valid properties would be: * <pre> - * gnu.crypto.csprng.blocking=true - * - * gnu.crypto.csprng.file.1=75.0;0;256;/dev/random - * gnu.crypto.csprng.file.2=10.0;0;100;/home/user/file - * - * gnu.crypto.csprng.url.1=5.0;0;256;http://www.random.org/cgi-bin/randbyte?nbytes=256 - * gnu.crypto.csprng.url.2=0;256;256;http://slashdot.org/ - * - * gnu.crypto.csprng.program.1=0.5;0;10;last -n 50 - * gnu.crypto.csprng.program.2=0.5;0;10;tcpdump -c 5 - * - * gnu.crypto.csprng.other.1=foo.bar.MyEntropySource - * gnu.crypto.csprng.other.2=com.company.OtherEntropySource + * gnu.crypto.csprng.blocking=true + * + * gnu.crypto.csprng.file.1=75.0;0;256;/dev/random + * gnu.crypto.csprng.file.2=10.0;0;100;/home/user/file + * + * gnu.crypto.csprng.url.1=5.0;0;256;http://www.random.org/cgi-bin/randbyte?nbytes=256 + * gnu.crypto.csprng.url.2=0;256;256;http://slashdot.org/ + * + * gnu.crypto.csprng.program.1=0.5;0;10;last -n 50 + * gnu.crypto.csprng.program.2=0.5;0;10;tcpdump -c 5 + * + * gnu.crypto.csprng.other.1=foo.bar.MyEntropySource + * gnu.crypto.csprng.other.2=com.company.OtherEntropySource * </pre> */ public static IRandom getSystemInstance() throws ClassNotFoundException, @@ -366,70 +289,57 @@ public class CSPRNG extends BasePRNG HashMap attrib = new HashMap(); attrib.put(BLOCKING, Boolean.valueOf(getProperty(BLOCK))); String s = null; - // Get each file source "gnu.crypto.csprng.file.N". List l = new LinkedList(); for (int i = 0; (s = getProperty(FILES + i)) != null; i++) - { - try - { - l.add(parseString(s.trim())); - } - catch (NumberFormatException nfe) - { - } - } + try + { + l.add(parseString(s.trim())); + } + catch (NumberFormatException nfe) + { + } attrib.put(FILE_SOURCES, l); - l = new LinkedList(); for (int i = 0; (s = getProperty(URLS + i)) != null; i++) - { - try - { - l.add(parseURL(s.trim())); - } - catch (NumberFormatException nfe) - { - } - catch (MalformedURLException mue) - { - } - } + try + { + l.add(parseURL(s.trim())); + } + catch (NumberFormatException nfe) + { + } + catch (MalformedURLException mue) + { + } attrib.put(URL_SOURCES, l); - l = new LinkedList(); for (int i = 0; (s = getProperty(PROGS + i)) != null; i++) - { - try - { - l.add(parseString(s.trim())); - } - catch (NumberFormatException nfe) - { - } - } + try + { + l.add(parseString(s.trim())); + } + catch (NumberFormatException nfe) + { + } attrib.put(PROGRAM_SOURCES, l); - l = new LinkedList(); for (int i = 0; (s = getProperty(OTHER + i)) != null; i++) - { - try - { - Class c = Class.forName(s.trim()); - l.add(c.newInstance()); - } - catch (ClassNotFoundException cnfe) - { - } - catch (InstantiationException ie) - { - } - catch (IllegalAccessException iae) - { - } - } + try + { + Class c = Class.forName(s.trim()); + l.add(c.newInstance()); + } + catch (ClassNotFoundException cnfe) + { + } + catch (InstantiationException ie) + { + } + catch (IllegalAccessException iae) + { + } attrib.put(OTHER_SOURCES, l); - instance.init(attrib); return instance; } @@ -449,9 +359,7 @@ public class CSPRNG extends BasePRNG { StringTokenizer tok = new StringTokenizer(s, ";"); if (tok.countTokens() != 4) - { - throw new IllegalArgumentException("malformed property"); - } + throw new IllegalArgumentException("malformed property"); Double quality = new Double(tok.nextToken()); Integer offset = new Integer(tok.nextToken()); Integer length = new Integer(tok.nextToken()); @@ -464,9 +372,7 @@ public class CSPRNG extends BasePRNG { StringTokenizer tok = new StringTokenizer(s, ";"); if (tok.countTokens() != 4) - { - throw new IllegalArgumentException("malformed property"); - } + throw new IllegalArgumentException("malformed property"); Double quality = new Double(tok.nextToken()); Integer offset = new Integer(tok.nextToken()); Integer length = new Integer(tok.nextToken()); @@ -474,9 +380,6 @@ public class CSPRNG extends BasePRNG return new SimpleList(quality, offset, length, url); } - // Instance methods. - // ------------------------------------------------------------------------- - public Object clone() { return new CSPRNG(); @@ -485,34 +388,25 @@ public class CSPRNG extends BasePRNG public void setup(Map attrib) { List list = null; - - if (DEBUG) - { - debug(String.valueOf(attrib)); - } + if (Configuration.DEBUG) + log.fine("attrib=" + String.valueOf(attrib)); try { list = (List) attrib.get(FILE_SOURCES); - if (DEBUG) - { - debug(String.valueOf(list)); - } + if (Configuration.DEBUG) + log.fine("list=" + String.valueOf(list)); if (list != null) { files.clear(); for (Iterator it = list.iterator(); it.hasNext();) { List l = (List) it.next(); - if (DEBUG) - { - debug("l=" + l); - } + if (Configuration.DEBUG) + log.fine("l=" + l); if (l.size() != 4) { - if (DEBUG) - { - debug("file list too small: " + l.size()); - } + if (Configuration.DEBUG) + log.fine("file list too small: " + l.size()); throw new IllegalArgumentException("invalid file list"); } Double quality = (Double) l.get(0); @@ -525,37 +419,27 @@ public class CSPRNG extends BasePRNG } catch (ClassCastException cce) { - if (DEBUG) - { - debug("bad file list: " + cce.getMessage()); - cce.printStackTrace(); - } + if (Configuration.DEBUG) + log.log(Level.FINE, "bad file list", cce); throw new IllegalArgumentException("invalid file list"); } - try { list = (List) attrib.get(URL_SOURCES); - if (DEBUG) - { - debug(String.valueOf(list)); - } + if (Configuration.DEBUG) + log.fine("list=" + String.valueOf(list)); if (list != null) { urls.clear(); for (Iterator it = list.iterator(); it.hasNext();) { List l = (List) it.next(); - if (DEBUG) - { - debug("l=" + l); - } + if (Configuration.DEBUG) + log.fine("l=" + l); if (l.size() != 4) { - if (DEBUG) - { - debug("URL list too small: " + l.size()); - } + if (Configuration.DEBUG) + log.fine("URL list too small: " + l.size()); throw new IllegalArgumentException("invalid URL list"); } Double quality = (Double) l.get(0); @@ -568,37 +452,27 @@ public class CSPRNG extends BasePRNG } catch (ClassCastException cce) { - if (DEBUG) - { - debug("bad URL list: " + cce.getMessage()); - cce.printStackTrace(); - } + if (Configuration.DEBUG) + log.log(Level.FINE, "bad URL list", cce); throw new IllegalArgumentException("invalid URL list"); } - try { list = (List) attrib.get(PROGRAM_SOURCES); - if (DEBUG) - { - debug(String.valueOf(list)); - } + if (Configuration.DEBUG) + log.fine("list=" + String.valueOf(list)); if (list != null) { progs.clear(); for (Iterator it = list.iterator(); it.hasNext();) { List l = (List) it.next(); - if (DEBUG) - { - debug("l=" + l); - } + if (Configuration.DEBUG) + log.fine("l=" + l); if (l.size() != 4) { - if (DEBUG) - { - debug("program list too small: " + l.size()); - } + if (Configuration.DEBUG) + log.fine("program list too small: " + l.size()); throw new IllegalArgumentException("invalid program list"); } Double quality = (Double) l.get(0); @@ -611,35 +485,25 @@ public class CSPRNG extends BasePRNG } catch (ClassCastException cce) { - if (DEBUG) - { - debug("bad program list: " + cce.getMessage()); - cce.printStackTrace(); - } + if (Configuration.DEBUG) + log.log(Level.FINE, "bad program list", cce); throw new IllegalArgumentException("invalid program list"); } - try { list = (List) attrib.get(OTHER_SOURCES); - if (DEBUG) - { - debug(String.valueOf(list)); - } + if (Configuration.DEBUG) + log.fine("list=" + String.valueOf(list)); if (list != null) { other.clear(); for (Iterator it = list.iterator(); it.hasNext();) { EntropySource src = (EntropySource) it.next(); - if (DEBUG) - { - debug("src=" + src); - } + if (Configuration.DEBUG) + log.fine("src=" + src); if (src == null) - { - throw new NullPointerException("null source in source list"); - } + throw new NullPointerException("null source in source list"); other.add(src); } } @@ -653,19 +517,14 @@ public class CSPRNG extends BasePRNG { Boolean block = (Boolean) attrib.get(BLOCKING); if (block != null) - { - blocking = block.booleanValue(); - } + blocking = block.booleanValue(); else - { - blocking = true; - } + blocking = true; } catch (ClassCastException cce) { throw new IllegalArgumentException("invalid blocking parameter"); } - poller = new Poller(files, urls, progs, other, this); try { @@ -679,27 +538,21 @@ public class CSPRNG extends BasePRNG public void fillBlock() throws LimitReachedException { - if (DEBUG) - { - debug("fillBlock"); - } + if (Configuration.DEBUG) + log.fine("fillBlock"); if (getQuality() < 100.0) { - if (DEBUG) - { - debug("doing slow poll"); - } + if (Configuration.DEBUG) + log.fine("doing slow poll"); slowPoll(); } - do { fastPoll(); mixRandomPool(); } while (mixCount < MIX_COUNT); - - if (!x917init || x917count >= X917_LIFETIME) + if (! x917init || x917count >= X917_LIFETIME) { mixRandomPool(pool); Map attr = new HashMap(); @@ -715,59 +568,45 @@ public class CSPRNG extends BasePRNG { throw new Error(ike.toString()); } - mixRandomPool(pool); generateX917(pool); mixRandomPool(pool); generateX917(pool); - if (x917init) - { - quality = 0.0; - } + quality = 0.0; x917init = true; x917count = 0; } - byte[] export = new byte[ALLOC_SIZE]; for (int i = 0; i < ALLOC_SIZE; i++) - { - export[i] = (byte) (pool[i] ^ 0xFF); - } - + export[i] = (byte)(pool[i] ^ 0xFF); mixRandomPool(); mixRandomPool(export); - generateX917(export); - for (int i = 0; i < OUTPUT_SIZE; i++) - { - buffer[i] = (byte) (export[i] ^ export[i + OUTPUT_SIZE]); - } + buffer[i] = (byte)(export[i] ^ export[i + OUTPUT_SIZE]); Arrays.fill(export, (byte) 0); } /** - * Add an array of bytes into the randomness pool. Note that this method - * will <i>not</i> increment the pool's quality counter (this can only be - * done via a source provided to the setup method). - * + * Add an array of bytes into the randomness pool. Note that this method will + * <i>not</i> increment the pool's quality counter (this can only be done via + * a source provided to the setup method). + * * @param buf The byte array. * @param off The offset from whence to start reading bytes. * @param len The number of bytes to add. * @throws ArrayIndexOutOfBoundsException If <i>off</i> or <i>len</i> are - * out of the range of <i>buf</i>. + * out of the range of <i>buf</i>. */ public synchronized void addRandomBytes(byte[] buf, int off, int len) { if (off < 0 || len < 0 || off + len > buf.length) + throw new ArrayIndexOutOfBoundsException(); + if (Configuration.DEBUG) { - throw new ArrayIndexOutOfBoundsException(); - } - if (DEBUG) - { - debug("adding random bytes:"); - debug(Util.toString(buf, off, len)); + log.fine("adding random bytes:"); + log.fine(Util.toString(buf, off, len)); } final int count = off + len; for (int i = off; i < count; i++) @@ -782,18 +621,16 @@ public class CSPRNG extends BasePRNG } /** - * Add a single random byte to the randomness pool. Note that this method - * will <i>not</i> increment the pool's quality counter (this can only be - * done via a source provided to the setup method). - * + * Add a single random byte to the randomness pool. Note that this method will + * <i>not</i> increment the pool's quality counter (this can only be done via + * a source provided to the setup method). + * * @param b The byte to add. */ public synchronized void addRandomByte(byte b) { - if (DEBUG) - { - debug("adding byte " + Integer.toHexString(b)); - } + if (Configuration.DEBUG) + log.fine("adding byte " + Integer.toHexString(b)); pool[index++] ^= b; if (index >= pool.length) { @@ -802,23 +639,14 @@ public class CSPRNG extends BasePRNG } } - // Package methods. - // ------------------------------------------------------------------------- - synchronized void addQuality(double quality) { - if (DEBUG) - { - debug("adding quality " + quality); - } + if (Configuration.DEBUG) + log.fine("adding quality " + quality); if (this.quality < 100) - { - this.quality += quality; - } - if (DEBUG) - { - debug("quality now " + this.quality); - } + this.quality += quality; + if (Configuration.DEBUG) + log.fine("quality now " + this.quality); } synchronized double getQuality() @@ -826,13 +654,10 @@ public class CSPRNG extends BasePRNG return quality; } - // Own methods. - // ------------------------------------------------------------------------- - /** - * The mix operation. This method will, for every 20-byte block in the - * random pool, hash that block, the previous 20 bytes, and the next - * 44 bytes with SHA-1, writing the result back into that block. + * The mix operation. This method will, for every 20-byte block in the random + * pool, hash that block, the previous 20 bytes, and the next 44 bytes with + * SHA-1, writing the result back into that block. */ private void mixRandomPool(byte[] buf) { @@ -841,25 +666,17 @@ public class CSPRNG extends BasePRNG { // First update the bytes [p-19..p-1]. if (i == 0) - { - hash.update(buf, buf.length - hashSize, hashSize); - } + hash.update(buf, buf.length - hashSize, hashSize); else - { - hash.update(buf, i - hashSize, hashSize); - } - + hash.update(buf, i - hashSize, hashSize); // Now the next 64 bytes. if (i + 64 < buf.length) - { - hash.update(buf, i, 64); - } + hash.update(buf, i, 64); else { hash.update(buf, i, buf.length - i); hash.update(buf, 0, 64 - (buf.length - i)); } - byte[] digest = hash.digest(); System.arraycopy(digest, 0, buf, i, hashSize); } @@ -878,28 +695,22 @@ public class CSPRNG extends BasePRNG { int copy = Math.min(buf.length - i, X917_POOL_SIZE); for (int j = 0; j < copy; j++) - { - x917pool[j] ^= pool[off + j]; - } - + x917pool[j] ^= pool[off + j]; cipher.encryptBlock(x917pool, 0, x917pool, 0); System.arraycopy(x917pool, 0, buf, off, copy); cipher.encryptBlock(x917pool, 0, x917pool, 0); - off += copy; x917count++; } } /** - * Add random data always immediately available into the random pool, such - * as the values of the eight asynchronous counters, the current time, the - * current memory usage, the calling thread name, and the current stack - * trace. - * - * <p>This method does not alter the quality counter, and is provided more - * to maintain randomness, not to seriously improve the current random - * state. + * Add random data always immediately available into the random pool, such as + * the values of the eight asynchronous counters, the current time, the + * current memory usage, the calling thread name, and the current stack trace. + * <p> + * This method does not alter the quality counter, and is provided more to + * maintain randomness, not to seriously improve the current random state. */ private void fastPoll() { @@ -909,14 +720,12 @@ public class CSPRNG extends BasePRNG addRandomByte(b); addRandomByte((byte) System.currentTimeMillis()); addRandomByte((byte) Runtime.getRuntime().freeMemory()); - String s = Thread.currentThread().getName(); if (s != null) { byte[] buf = s.getBytes(); addRandomBytes(buf, 0, buf.length); } - ByteArrayOutputStream bout = new ByteArrayOutputStream(1024); PrintStream pout = new PrintStream(bout); Throwable t = new Throwable(); @@ -928,12 +737,10 @@ public class CSPRNG extends BasePRNG private void slowPoll() throws LimitReachedException { - if (DEBUG) - { - debug("poller is alive? " - + (pollerThread == null ? false : pollerThread.isAlive())); - } - if (pollerThread == null || !pollerThread.isAlive()) + if (Configuration.DEBUG) + log.fine("poller is alive? " + + (pollerThread == null ? false : pollerThread.isAlive())); + if (pollerThread == null || ! pollerThread.isAlive()) { boolean interrupted = false; pollerThread = new Thread(poller); @@ -941,27 +748,21 @@ public class CSPRNG extends BasePRNG pollerThread.setPriority(Thread.NORM_PRIORITY - 1); pollerThread.start(); if (blocking) - { - try - { - pollerThread.join(); - } - catch (InterruptedException ie) - { - interrupted = true; - } - } - + try + { + pollerThread.join(); + } + catch (InterruptedException ie) + { + interrupted = true; + } // If the full slow poll has completed after we waited for it, // and there in insufficient randomness, throw an exception. - if (!interrupted && blocking && quality < 100.0) + if (! interrupted && blocking && quality < 100.0) { - if (DEBUG) - { - debug("insufficient quality: " + quality); - } - throw new LimitReachedException( - "insufficient randomness was polled"); + if (Configuration.DEBUG) + log.fine("insufficient quality: " + quality); + throw new LimitReachedException("insufficient randomness was polled"); } } } @@ -979,33 +780,21 @@ public class CSPRNG extends BasePRNG Arrays.fill(buffer, (byte) 0); } - // Inner classes. - // ------------------------------------------------------------------------- - /** - * A simple thread that constantly updates a byte counter. This class is - * used in a group of lowest-priority threads and the values of their - * counters (updated in competition with all other threads) is used as a - * source of entropy bits. + * A simple thread that constantly updates a byte counter. This class is used + * in a group of lowest-priority threads and the values of their counters + * (updated in competition with all other threads) is used as a source of + * entropy bits. */ - private static class Spinner implements Runnable + private static class Spinner + implements Runnable { - - // Field. - // ----------------------------------------------------------------------- - - private byte counter; - - // Constructor. - // ----------------------------------------------------------------------- + protected byte counter; private Spinner() { } - // Instance methods. - // ----------------------------------------------------------------------- - public void run() { while (true) @@ -1022,27 +811,16 @@ public class CSPRNG extends BasePRNG } } - private final class Poller implements Runnable + private final class Poller + implements Runnable { - - // Fields. - // ----------------------------------------------------------------------- - private final List files; - private final List urls; - private final List progs; - private final List other; - private final CSPRNG pool; - private boolean running; - // Constructor. - // ----------------------------------------------------------------------- - Poller(List files, List urls, List progs, List other, CSPRNG pool) { super(); @@ -1053,17 +831,14 @@ public class CSPRNG extends BasePRNG this.pool = pool; } - // Instance methods. - // ----------------------------------------------------------------------- - public void run() { running = true; - if (DEBUG) + if (Configuration.DEBUG) { - debug("files: " + files); - debug("URLs: " + urls); - debug("progs: " + progs); + log.fine("files: " + files); + log.fine("URLs: " + urls); + log.fine("progs: " + progs); } Iterator files_it = files.iterator(); Iterator urls_it = urls.iterator(); @@ -1073,190 +848,132 @@ public class CSPRNG extends BasePRNG while (files_it.hasNext() || urls_it.hasNext() || prog_it.hasNext() || other_it.hasNext()) { - // There is enough random data. Go away. - if (pool.getQuality() >= 100.0 || !running) - { - return; - } - + if (pool.getQuality() >= 100.0 || ! running) + return; if (files_it.hasNext()) - { - try - { - List l = (List) files_it.next(); - if (DEBUG) - { - debug(l.toString()); - } - double qual = ((Double) l.get(0)).doubleValue(); - int offset = ((Integer) l.get(1)).intValue(); - int count = ((Integer) l.get(2)).intValue(); - String src = (String) l.get(3); - InputStream in = new FileInputStream(src); - byte[] buf = new byte[count]; - if (offset > 0) - { - in.skip(offset); - } - int len = in.read(buf); - if (len >= 0) - { - pool.addRandomBytes(buf, 0, len); - pool.addQuality(qual * ((double) len / (double) count)); - } - if (DEBUG) - { - debug("got " + len + " bytes from " + src); - } - } - catch (Exception x) - { - if (DEBUG) - { - debug(x.toString()); - x.printStackTrace(); - } - } - } - - if (pool.getQuality() >= 100.0 || !running) - { - return; - } - + try + { + List l = (List) files_it.next(); + if (Configuration.DEBUG) + log.fine(l.toString()); + double qual = ((Double) l.get(0)).doubleValue(); + int offset = ((Integer) l.get(1)).intValue(); + int count = ((Integer) l.get(2)).intValue(); + String src = (String) l.get(3); + InputStream in = new FileInputStream(src); + byte[] buf = new byte[count]; + if (offset > 0) + in.skip(offset); + int len = in.read(buf); + if (len >= 0) + { + pool.addRandomBytes(buf, 0, len); + pool.addQuality(qual * ((double) len / (double) count)); + } + if (Configuration.DEBUG) + log.fine("got " + len + " bytes from " + src); + } + catch (Exception x) + { + if (Configuration.DEBUG) + log.throwing(this.getClass().getName(), "run", x); + } + if (pool.getQuality() >= 100.0 || ! running) + return; if (urls_it.hasNext()) - { - try - { - List l = (List) urls_it.next(); - if (DEBUG) - { - debug(l.toString()); - } - double qual = ((Double) l.get(0)).doubleValue(); - int offset = ((Integer) l.get(1)).intValue(); - int count = ((Integer) l.get(2)).intValue(); - URL src = (URL) l.get(3); - InputStream in = src.openStream(); - byte[] buf = new byte[count]; - if (offset > 0) - { - in.skip(offset); - } - int len = in.read(buf); - if (len >= 0) - { - pool.addRandomBytes(buf, 0, len); - pool.addQuality(qual * ((double) len / (double) count)); - } - if (DEBUG) - { - debug("got " + len + " bytes from " + src); - } - } - catch (Exception x) - { - if (DEBUG) - { - debug(x.toString()); - x.printStackTrace(); - } - } - } - - if (pool.getQuality() >= 100.0 || !running) - { - return; - } - + try + { + List l = (List) urls_it.next(); + if (Configuration.DEBUG) + log.fine(l.toString()); + double qual = ((Double) l.get(0)).doubleValue(); + int offset = ((Integer) l.get(1)).intValue(); + int count = ((Integer) l.get(2)).intValue(); + URL src = (URL) l.get(3); + InputStream in = src.openStream(); + byte[] buf = new byte[count]; + if (offset > 0) + in.skip(offset); + int len = in.read(buf); + if (len >= 0) + { + pool.addRandomBytes(buf, 0, len); + pool.addQuality(qual * ((double) len / (double) count)); + } + if (Configuration.DEBUG) + log.fine("got " + len + " bytes from " + src); + } + catch (Exception x) + { + if (Configuration.DEBUG) + log.throwing(this.getClass().getName(), "run", x); + } + if (pool.getQuality() >= 100.0 || ! running) + return; Process proc = null; if (prog_it.hasNext()) - { - try - { - List l = (List) prog_it.next(); - if (DEBUG) - { - debug(l.toString()); - } - double qual = ((Double) l.get(0)).doubleValue(); - int offset = ((Integer) l.get(1)).intValue(); - int count = ((Integer) l.get(2)).intValue(); - String src = (String) l.get(3); - proc = null; - proc = Runtime.getRuntime().exec(src); - InputStream in = proc.getInputStream(); - byte[] buf = new byte[count]; - if (offset > 0) - { - in.skip(offset); - } - int len = in.read(buf); - if (len >= 0) - { - pool.addRandomBytes(buf, 0, len); - pool.addQuality(qual * ((double) len / (double) count)); - } - proc.destroy(); - proc.waitFor(); - if (DEBUG) - { - debug("got " + len + " bytes from " + src); - } - } - catch (Exception x) - { - if (DEBUG) - { - debug(x.toString()); - x.printStackTrace(); - } - try - { - if (proc != null) - { - proc.destroy(); - proc.waitFor(); - } - } - catch (Exception ignored) - { - } - } - } - - if (pool.getQuality() >= 100.0 || !running) - { - return; - } - + try + { + List l = (List) prog_it.next(); + if (Configuration.DEBUG) + log.finer(l.toString()); + double qual = ((Double) l.get(0)).doubleValue(); + int offset = ((Integer) l.get(1)).intValue(); + int count = ((Integer) l.get(2)).intValue(); + String src = (String) l.get(3); + proc = null; + proc = Runtime.getRuntime().exec(src); + InputStream in = proc.getInputStream(); + byte[] buf = new byte[count]; + if (offset > 0) + in.skip(offset); + int len = in.read(buf); + if (len >= 0) + { + pool.addRandomBytes(buf, 0, len); + pool.addQuality(qual * ((double) len / (double) count)); + } + proc.destroy(); + proc.waitFor(); + if (Configuration.DEBUG) + log.fine("got " + len + " bytes from " + src); + } + catch (Exception x) + { + if (Configuration.DEBUG) + log.throwing(this.getClass().getName(), "run", x); + try + { + if (proc != null) + { + proc.destroy(); + proc.waitFor(); + } + } + catch (Exception ignored) + { + } + } + if (pool.getQuality() >= 100.0 || ! running) + return; if (other_it.hasNext()) - { - try - { - EntropySource src = (EntropySource) other_it.next(); - byte[] buf = src.nextBytes(); - if (pool == null) - { - return; - } - pool.addRandomBytes(buf, 0, buf.length); - pool.addQuality(src.quality()); - if (DEBUG) - { - debug("got " + buf.length + " bytes from " + src); - } - } - catch (Exception x) - { - if (DEBUG) - { - debug(x.toString()); - x.printStackTrace(); - } - } - } + try + { + EntropySource src = (EntropySource) other_it.next(); + byte[] buf = src.nextBytes(); + if (pool == null) + return; + pool.addRandomBytes(buf, 0, buf.length); + pool.addQuality(src.quality()); + if (Configuration.DEBUG) + log.fine("got " + buf.length + " bytes from " + src); + } + catch (Exception x) + { + if (Configuration.DEBUG) + log.throwing(this.getClass().getName(), "run", x); + } } } @@ -1265,4 +982,4 @@ public class CSPRNG extends BasePRNG running = false; } } -}
\ No newline at end of file +} |