nativeseedgenerator.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 296 行

JAVA
296
字号
/* * @(#)NativeSeedGenerator.java	1.5 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */package sun.security.provider;import java.io.BufferedInputStream;import java.io.IOException;import java.net.URL;import sun.security.util.Debug;/** * Native seed generator for Linix systems. Inherit everything from * URLSeedGenerator. * * @version 1.2, 01/23/03 */class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {    private static final Debug debug = Debug.getInstance("provider");    private String deviceName;    private BufferedInputStream devRandom;    // For CDC/FP 1.1.1 we provide a fallback mechanism to deal with    // the fact that on some devices the entropy gathering device    // can block. The ThreadedSeedGenerator approach is not an ideal    // solution for the range of devices which CDC/FP addresses, so    // we will use /dev/urandom, which will not block.    final static String URL_FALLBACK = "file:/dev/urandom";    // Allow the fallback mechanism to be disabled if desired. This    // could mean that an application's main threat will hang,    // but it allows for stronger random seed generation.    private final static String PROP_NOFALLBACK =         "microedition.securerandom.nofallback";    private static boolean createFallback = true;    // The actual fallback InputStream from which we read.    private BufferedInputStream fallback;    // An object to sit between the main thread and the    // entropy generation device, to avoid blocking an    // application if there is not sufficient entropy.    private static RandomReader ranReader = null;    NativeSeedGenerator() throws IOException {        this(SeedGenerator.URL_DEV_RANDOM);    }    NativeSeedGenerator(String egdurl) throws IOException {        if (egdurl == null) {            throw new IOException("No random source specified");        }        this.deviceName = egdurl;        // Because of the problems of blocking I/O on smaller        // devices, we do not read the random device directly,        // but rather do so in a separate thread from which we        // can retrieve data when it is available.        if ( ranReader == null ) {            ranReader = new RandomReader( egdurl );            if (ranReader == null) {                throw new InternalError( "RandomReader thread creation failure" );            }        }        // Check to see whether the fallback mechanism is disabled.        Boolean noFallback =            (Boolean)java.security.AccessController.doPrivileged            (new java.security.PrivilegedAction() {                    public Object run() {                        String prop = System.getProperty(PROP_NOFALLBACK,                                                         "false");                        return Boolean.valueOf(prop);                    }                });        createFallback = ! noFallback.booleanValue();    }    // For CDC/FP, if the fallback mechanism is not disabled    // and we are going to block on the default entropy generation    // device, we'll open the fallback URL instead.    private void createFallback() throws IOException {        if (debug != null) {            debug.println("Creating fallback seed generator");        }        final URL fallbackDevice = new URL(this.URL_FALLBACK);        fallback =            (BufferedInputStream)java.security.AccessController.doPrivileged            (new java.security.PrivilegedAction() {                    public Object run() {                        try {                            return new BufferedInputStream(fallbackDevice.openStream());                        } catch ( IOException ioe ) {                            return null;                        }                    }                });        if (fallback == null) {            throw new IOException( "failed to open " +                                   this.URL_FALLBACK );        }        return;    }    synchronized byte getSeedByte() {        byte b[] = new byte[1];        int stat;        // If we would block trying to read from the entropy        // generation device, and we haven't been instructed        // not to, use a fallback alternative which will not        // block.        if (ranReader.available() == 0 && createFallback == true) {            try {                if (fallback == null) {                    createFallback();                }                // Do the actual read. If we get a byte of                // data, give it to whomever wanted it.                stat = fallback.read(b, 0, b.length);                if (stat == b.length) {                    return b[0];                }            } catch (IOException ioe) {                throw new InternalError("NativeSeedGenerator " +                                         this.URL_FALLBACK +                                        " generated exception: " +                                        ioe.getMessage());            } catch (Exception e) {                throw new InternalError("NativeSeedGenerator " +                                         this.URL_FALLBACK +                                        " generated exception: " +                                        e.getMessage());            }            // The read didn't generate an exception but gave us            // bad data in any case.            throw new InternalError("NativeSeedGenerator " +                                    this.URL_FALLBACK +                                    " failed read: " + stat );        }        // Read from the main entropy device. This happens if data is        // available *or* if the property has been set which        // instructs us not to use the fallback device no matter        // what.        return ranReader.getSeedByte();    }    /*     * CR 6260366. Because of varying methods for generating     * entropy in the default random device (/dev/random, generally),     * we will read from it in a separate thread. This will allow     * reads to block until the device has generated sufficient     * entropy. If the device will block, we will instead default     * to file:/dev/urandom.     */    private static class RandomReader implements Runnable {        private String deviceName;        private BufferedInputStream randomDevReader;        private Thread readerThread;        byte[] buf = new byte[ 20 ];        int start = 0;        int end = 0;        RandomReader(String egdurl) throws IOException {            if (egdurl == null) {                throw new IOException("No random source specified");            }            deviceName = egdurl;            init();        }                   // Initialize ourselves. Open the specified device and        // start the run() method.         void init() throws IOException {            final URL device = new URL(deviceName);            randomDevReader =                (BufferedInputStream)java.security.AccessController.doPrivileged                (new java.security.PrivilegedAction() {                        public Object run() {                            try {                                return new BufferedInputStream(device.openStream(), 1);                            } catch (IOException ioe) {                                return null;                            }                        }                    });            // Oops. Check for failure.            if (randomDevReader == null) {                throw new IOException("failed to open " + device);            }                        // Create a thread which will do the actual reading.            readerThread = (Thread)java.security.AccessController.doPrivileged                (new java.security.PrivilegedAction() {                        public Object run() {                            Thread newT = new Thread(Thread.currentThread().getThreadGroup(),                                                     RandomReader.this,                                             "Random Device Reader Thread");                            newT.setPriority(Thread.MIN_PRIORITY);                            newT.setDaemon(true);                            return newT;                        }                    });            if (readerThread == null) {                throw new InternalError("Cannot create RandomReader thread for " + deviceName);            }            readerThread.start();            return;        }        // The real work of RandomReader is done here. Read from the        // random device (which may block in some implementations).        // Retrieved bytes will be taken from our  buffer by the        // getSeedByte() method.        public void run() {            while (true) {                try {                    // If we don't need to read any data, wait until                    // the buffer is empty.                    synchronized(this) {                        while (start < end) {                            wait();                        }                    }                    // Read to fill the buffer                    end = randomDevReader.read( buf, 0, buf.length );                    if (end < 0) {                        throw new InternalError("RandomReader read failed on " + deviceName);                    }                    start = 0;                    // Notify anyone looking for data that the                    // buffer is full.                    synchronized(this) {                        notify();                    }                } catch (Exception e) {                    throw new InternalError("RandomReader thread generated exception: " +                                             e.getMessage());                }            }        }        // Is there anything available in the buffer to consume?        int available() {            return end - start;        }        // Take a byte from the buffer.        byte getSeedByte() {            byte b = 0;            try {                synchronized(this) {                    // If we have no data, wait until it becomes                    // available. The buffer will be populated by                    // the run() method.                    if (start == end) {                        wait();                    }                    b = buf[start++];                    notifyAll();                }            } catch (Exception e) {                throw new InternalError("RandomReader thread failed getSeedByte");            }            return b;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?