src/share/classes/sun/security/provider/SeedGenerator.java

Print this page




  46  * activites, which in turn add entropy to the random seed.
  47  * <p> The class also gathers miscellaneous system information, some
  48  * machine dependent, some not. This information is then hashed together
  49  * with the 20 seed bytes.
  50  * <P> The alternative to the above approach is to acquire seed material
  51  * from an entropy gathering device, such as /dev/random. This can be
  52  * accomplished by setting the value of the "securerandom.source"
  53  * security property (in the Java security properties file) to a URL
  54  * specifying the location of the entropy gathering device.
  55  * In the event the specified URL cannot be accessed the default
  56  * mechanism is used.
  57  * The Java security properties file is located in the file named
  58  * &lt;JAVA_HOME&gt;/lib/security/java.security.
  59  * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
  60  * and specifies the directory where the JRE is installed.
  61  *
  62  * @author Joshua Bloch
  63  * @author Gadi Guy
  64  */
  65 
  66 import java.lang.reflect.Method;
  67 import java.lang.reflect.InvocationTargetException;
  68 import java.security.*;
  69 import java.io.*;
  70 import java.util.Properties;
  71 import java.util.Enumeration;
  72 import java.net.*;



  73 import java.util.Random;
  74 import sun.security.util.Debug;
  75 
  76 abstract class SeedGenerator {
  77 
  78     // Static instance is created at link time
  79     private static SeedGenerator instance;
  80 
  81     private static final Debug debug = Debug.getInstance("provider");
  82 
  83     final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;
  84     final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;
  85 
  86     // Static initializer to hook in selected or best performing generator
  87     static {
  88         String egdSource = SunEntries.getSeedSource();
  89 
  90         // Try the URL specifying the source
  91         // e.g. file:/dev/random
  92         //


 160         java.security.AccessController.doPrivileged
 161             (new java.security.PrivilegedAction<Void>() {
 162                 public Void run() {
 163 
 164                     try {
 165                         // System properties can change from machine to machine
 166                         String s;
 167                         Properties p = System.getProperties();
 168                         Enumeration<?> e = p.propertyNames();
 169                         while (e.hasMoreElements()) {
 170                             s =(String)e.nextElement();
 171                             md.update(s.getBytes());
 172                             md.update(p.getProperty(s).getBytes());
 173                         }
 174 
 175                         md.update
 176                             (InetAddress.getLocalHost().toString().getBytes());
 177 
 178                         // The temporary dir
 179                         File f = new File(p.getProperty("java.io.tmpdir"));
 180 
 181                         // Go thru files in the tmp dir using NIO's
 182                         // DirectoryStream. Fallback to File.list()
 183                         // if NIO is not available.
 184                         if (NIODirectoryStream.isAvailable()) {
 185                             int count = 0;
 186                             Iterable<?> stream =
 187                                     NIODirectoryStream.newDirectoryStream(f);
 188                             // We use a Random object to choose what file names
 189                             // should be used. Otherwise on a machine with too
 190                             // many files, the same first 1024 files always get
 191                             // used. Any, We make sure the first 512 files are
 192                             // always used.
 193                             Random r = new Random();
 194                             try {
 195                                 for (Object entry: stream) {
 196                                     if (count < 512 || r.nextBoolean()) {
 197                                         md.update(NIODirectoryStream.getName(
 198                                                 entry).getBytes());
 199                                     }
 200                                     if (count++ > 1024) {
 201                                         break;
 202                                     }
 203                                 }
 204                             } finally {
 205                                 ((Closeable)stream).close();
 206                             }
 207                         } else {
 208                             String[] sa = f.list();
 209                             for(int i = 0; i < sa.length; i++) {
 210                                 md.update(sa[i].getBytes());
 211                             }
 212                         }
 213                     } catch (Exception ex) {
 214                         md.update((byte)ex.hashCode());
 215                     }
 216 
 217                     // get Runtime memory stats
 218                     Runtime rt = Runtime.getRuntime();
 219                     byte[] memBytes = longToByteArray(rt.totalMemory());
 220                     md.update(memBytes, 0, memBytes.length);
 221                     memBytes = longToByteArray(rt.freeMemory());
 222                     md.update(memBytes, 0, memBytes.length);
 223 
 224                     return null;
 225                 }
 226             });
 227         return md.digest();
 228     }
 229 
 230     /**
 231      * Helper function to convert a long into a byte array (least significant
 232      * byte first).


 536         void getSeedBytes(byte[] result) {
 537             int len = result.length;
 538             int read = 0;
 539             try {
 540                 while (read < len) {
 541                     int count = devRandom.read(result, read, len - read);
 542                     // /dev/random blocks - should never have EOF
 543                     if (count < 0)
 544                         throw new InternalError("URLSeedGenerator " + deviceName +
 545                                         " reached end of file");
 546                     read += count;
 547                 }
 548             } catch (IOException ioe) {
 549                 throw new InternalError("URLSeedGenerator " + deviceName +
 550                                         " generated exception: " +
 551                                         ioe.getMessage());
 552             }
 553         }
 554 
 555     }
 556 
 557     /**
 558      * A wrapper of NIO DirectoryStream using reflection.
 559      */
 560     private static class NIODirectoryStream {
 561         private static final Class<?> pathClass =
 562                 getClass("java.nio.file.Path");
 563 
 564         private static final Method toPathMethod =
 565                 (pathClass == null) ? null : getMethod(File.class, "toPath");
 566         private static final Method getNameMethod =
 567                 getMethod(pathClass, "getName");
 568         private static final Method newDirectoryStreamMethod =
 569                 getMethod(pathClass, "newDirectoryStream");
 570 
 571         private static Class<?> getClass(String name) {
 572             try {
 573                 return Class.forName(name, true, null);
 574             } catch (ClassNotFoundException e) {
 575                 return null;
 576             }
 577         }
 578 
 579         private static Method getMethod(Class<?> clazz,
 580                                         String name,
 581                                         Class<?>... paramTypes) {
 582             if (clazz != null) {
 583                 try {
 584                     return clazz.getMethod(name, paramTypes);
 585                 } catch (NoSuchMethodException e) {
 586                     throw new AssertionError(e);
 587                 }
 588             } else {
 589                 return null;
 590             }
 591         }
 592 
 593         static boolean isAvailable() {
 594             return pathClass != null;
 595         }
 596 
 597         static Iterable<?> newDirectoryStream(File dir) throws IOException {
 598             assert pathClass != null;
 599             try {
 600                 Object path = toPathMethod.invoke(dir);
 601                 return (Iterable<?>)newDirectoryStreamMethod.invoke(path);
 602             } catch (InvocationTargetException e) {
 603                 Throwable cause = e.getCause();
 604                 if (cause instanceof IOException)
 605                     throw (IOException)cause;
 606                 if (cause instanceof RuntimeException)
 607                     throw (RuntimeException)cause;
 608                 if (cause instanceof Error)
 609                     throw (Error)cause;
 610                 throw new AssertionError(e);
 611             } catch (IllegalAccessException iae) {
 612                 throw new AssertionError(iae);
 613             }
 614         }
 615 
 616         static String getName(Object path) {
 617             assert pathClass != null;
 618             try {
 619                 Object name = getNameMethod.invoke(path);
 620                 return name.toString();
 621             } catch (InvocationTargetException e) {
 622                 throw new AssertionError(e);
 623             } catch (IllegalAccessException iae) {
 624                 throw new AssertionError(iae);
 625             }
 626         }
 627     }
 628 }
 629 


  46  * activites, which in turn add entropy to the random seed.
  47  * <p> The class also gathers miscellaneous system information, some
  48  * machine dependent, some not. This information is then hashed together
  49  * with the 20 seed bytes.
  50  * <P> The alternative to the above approach is to acquire seed material
  51  * from an entropy gathering device, such as /dev/random. This can be
  52  * accomplished by setting the value of the "securerandom.source"
  53  * security property (in the Java security properties file) to a URL
  54  * specifying the location of the entropy gathering device.
  55  * In the event the specified URL cannot be accessed the default
  56  * mechanism is used.
  57  * The Java security properties file is located in the file named
  58  * &lt;JAVA_HOME&gt;/lib/security/java.security.
  59  * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
  60  * and specifies the directory where the JRE is installed.
  61  *
  62  * @author Joshua Bloch
  63  * @author Gadi Guy
  64  */
  65 


  66 import java.security.*;
  67 import java.io.*;
  68 import java.util.Properties;
  69 import java.util.Enumeration;
  70 import java.net.*;
  71 import java.nio.file.DirectoryStream;
  72 import java.nio.file.Files;
  73 import java.nio.file.Path;
  74 import java.util.Random;
  75 import sun.security.util.Debug;
  76 
  77 abstract class SeedGenerator {
  78 
  79     // Static instance is created at link time
  80     private static SeedGenerator instance;
  81 
  82     private static final Debug debug = Debug.getInstance("provider");
  83 
  84     final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;
  85     final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;
  86 
  87     // Static initializer to hook in selected or best performing generator
  88     static {
  89         String egdSource = SunEntries.getSeedSource();
  90 
  91         // Try the URL specifying the source
  92         // e.g. file:/dev/random
  93         //


 161         java.security.AccessController.doPrivileged
 162             (new java.security.PrivilegedAction<Void>() {
 163                 public Void run() {
 164 
 165                     try {
 166                         // System properties can change from machine to machine
 167                         String s;
 168                         Properties p = System.getProperties();
 169                         Enumeration<?> e = p.propertyNames();
 170                         while (e.hasMoreElements()) {
 171                             s =(String)e.nextElement();
 172                             md.update(s.getBytes());
 173                             md.update(p.getProperty(s).getBytes());
 174                         }
 175 
 176                         md.update
 177                             (InetAddress.getLocalHost().toString().getBytes());
 178 
 179                         // The temporary dir
 180                         File f = new File(p.getProperty("java.io.tmpdir"));





 181                         int count = 0;
 182                         try (DirectoryStream<Path> stream = Files.newDirectoryStream(f.toPath())) {

 183                             // We use a Random object to choose what file names
 184                             // should be used. Otherwise on a machine with too
 185                             // many files, the same first 1024 files always get
 186                             // used. Any, We make sure the first 512 files are
 187                             // always used.
 188                             Random r = new Random();
 189                             for (Path entry: stream) {

 190                                 if (count < 512 || r.nextBoolean()) {
 191                                     md.update(entry.getFileName().toString().getBytes());

 192                                 }
 193                                 if (count++ > 1024) {
 194                                     break;
 195                                 }
 196                             }


 197                         }






 198                     } catch (Exception ex) {
 199                         md.update((byte)ex.hashCode());
 200                     }
 201 
 202                     // get Runtime memory stats
 203                     Runtime rt = Runtime.getRuntime();
 204                     byte[] memBytes = longToByteArray(rt.totalMemory());
 205                     md.update(memBytes, 0, memBytes.length);
 206                     memBytes = longToByteArray(rt.freeMemory());
 207                     md.update(memBytes, 0, memBytes.length);
 208 
 209                     return null;
 210                 }
 211             });
 212         return md.digest();
 213     }
 214 
 215     /**
 216      * Helper function to convert a long into a byte array (least significant
 217      * byte first).


 521         void getSeedBytes(byte[] result) {
 522             int len = result.length;
 523             int read = 0;
 524             try {
 525                 while (read < len) {
 526                     int count = devRandom.read(result, read, len - read);
 527                     // /dev/random blocks - should never have EOF
 528                     if (count < 0)
 529                         throw new InternalError("URLSeedGenerator " + deviceName +
 530                                         " reached end of file");
 531                     read += count;
 532                 }
 533             } catch (IOException ioe) {
 534                 throw new InternalError("URLSeedGenerator " + deviceName +
 535                                         " generated exception: " +
 536                                         ioe.getMessage());
 537             }
 538         }
 539 
 540     }








































































 541 }