📄 csprng.java
字号:
catch (InstantiationException ie) { } catch (IllegalAccessException iae) { } } attrib.put(OTHER_SOURCES, l); instance.init(attrib); return instance; } private static String getProperty(final String name) { return (String) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return Properties.getProperty(name); } }); } private static List parseString(String s) throws NumberFormatException { StringTokenizer tok = new StringTokenizer(s, ";"); if (tok.countTokens() != 4) { throw new IllegalArgumentException("malformed property"); } Double quality = new Double(tok.nextToken()); Integer offset = new Integer(tok.nextToken()); Integer length = new Integer(tok.nextToken()); String str = tok.nextToken(); return new SimpleList(quality, offset, length, str); } private static List parseURL(String s) throws MalformedURLException, NumberFormatException { StringTokenizer tok = new StringTokenizer(s, ";"); if (tok.countTokens() != 4) { throw new IllegalArgumentException("malformed property"); } Double quality = new Double(tok.nextToken()); Integer offset = new Integer(tok.nextToken()); Integer length = new Integer(tok.nextToken()); URL url = new URL(tok.nextToken()); return new SimpleList(quality, offset, length, url); } // Instance methods. // ------------------------------------------------------------------------- public Object clone() { return new CSPRNG(); } public void setup(Map attrib) { List list = null; if (DEBUG) { debug(String.valueOf(attrib)); } try { list = (List) attrib.get(FILE_SOURCES); if (DEBUG) { debug(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 (l.size() != 4) { if (DEBUG) { debug("file list too small: " + l.size()); } throw new IllegalArgumentException("invalid file list"); } Double quality = (Double) l.get(0); Integer offset = (Integer) l.get(1); Integer length = (Integer) l.get(2); String source = (String) l.get(3); files.add(new SimpleList(quality, offset, length, source)); } } } catch (ClassCastException cce) { if (DEBUG) { debug("bad file list: " + cce.getMessage()); cce.printStackTrace(); } throw new IllegalArgumentException("invalid file list"); } try { list = (List) attrib.get(URL_SOURCES); if (DEBUG) { debug(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 (l.size() != 4) { if (DEBUG) { debug("URL list too small: " + l.size()); } throw new IllegalArgumentException("invalid URL list"); } Double quality = (Double) l.get(0); Integer offset = (Integer) l.get(1); Integer length = (Integer) l.get(2); URL source = (URL) l.get(3); urls.add(new SimpleList(quality, offset, length, source)); } } } catch (ClassCastException cce) { if (DEBUG) { debug("bad URL list: " + cce.getMessage()); cce.printStackTrace(); } throw new IllegalArgumentException("invalid URL list"); } try { list = (List) attrib.get(PROGRAM_SOURCES); if (DEBUG) { debug(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 (l.size() != 4) { if (DEBUG) { debug("program list too small: " + l.size()); } throw new IllegalArgumentException("invalid program list"); } Double quality = (Double) l.get(0); Integer offset = (Integer) l.get(1); Integer length = (Integer) l.get(2); String source = (String) l.get(3); progs.add(new SimpleList(quality, offset, length, source)); } } } catch (ClassCastException cce) { if (DEBUG) { debug("bad program list: " + cce.getMessage()); cce.printStackTrace(); } throw new IllegalArgumentException("invalid program list"); } try { list = (List) attrib.get(OTHER_SOURCES); if (DEBUG) { debug(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 (src == null) { throw new NullPointerException("null source in source list"); } other.add(src); } } } catch (ClassCastException cce) { throw new IllegalArgumentException("invalid source list"); } try { Boolean block = (Boolean) attrib.get(BLOCKING); if (block != null) { blocking = block.booleanValue(); } else { blocking = true; } } catch (ClassCastException cce) { throw new IllegalArgumentException("invalid blocking parameter"); } poller = new Poller(files, urls, progs, other, this); try { fillBlock(); } catch (LimitReachedException lre) { throw new RuntimeException("bootstrapping CSPRNG failed"); } } public void fillBlock() throws LimitReachedException { if (DEBUG) { debug("fillBlock"); } if (getQuality() < 100.0) { if (DEBUG) { debug("doing slow poll"); } slowPoll(); } do { fastPoll(); mixRandomPool(); } while (mixCount < MIX_COUNT); if (!x917init || x917count >= X917_LIFETIME) { mixRandomPool(pool); Map attr = new HashMap(); byte[] key = new byte[32]; System.arraycopy(pool, 0, key, 0, 32); cipher.reset(); attr.put(IBlockCipher.KEY_MATERIAL, key); try { cipher.init(attr); } catch (InvalidKeyException ike) { throw new Error(ike.toString()); } mixRandomPool(pool); generateX917(pool); mixRandomPool(pool); generateX917(pool); if (x917init) { 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); } mixRandomPool(); mixRandomPool(export); generateX917(export); for (int i = 0; i < OUTPUT_SIZE; i++) { 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). * * @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>. */ public synchronized void addRandomBytes(byte[] buf, int off, int len) { if (off < 0 || len < 0 || off + len > buf.length) { throw new ArrayIndexOutOfBoundsException(); } if (DEBUG) { debug("adding random bytes:"); debug(Util.toString(buf, off, len)); } final int count = off + len; for (int i = off; i < count; i++) { pool[index++] ^= buf[i]; if (index == pool.length) { mixRandomPool(); index = 0; } } } /** * 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)); } pool[index++] ^= b; if (index >= pool.length) { mixRandomPool(); index = 0; } } // Package methods. // ------------------------------------------------------------------------- synchronized void addQuality(double quality) { if (DEBUG) { debug("adding quality " + quality); } if (this.quality < 100) { this.quality += quality; } if (DEBUG) { debug("quality now " + this.quality); } } synchronized double getQuality() { 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. */ private void mixRandomPool(byte[] buf) { int hashSize = hash.hashSize(); for (int i = 0; i < buf.length; i += hashSize) { // First update the bytes [p-19..p-1]. if (i == 0) { hash.update(buf, buf.length - hashSize, hashSize); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -