Frames | No Frames |
1: /* SecureRandom.java --- Secure Random class implementation 2: Copyright (C) 1999, 2001, 2002, 2003, 2005, 2006 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: package java.security; 40: 41: import gnu.classpath.SystemProperties; 42: import gnu.java.security.Engine; 43: import gnu.java.security.action.GetSecurityPropertyAction; 44: import gnu.java.security.jce.prng.SecureRandomAdapter; 45: import gnu.java.security.jce.prng.Sha160RandomSpi; 46: 47: import java.io.IOException; 48: import java.io.InputStream; 49: import java.net.MalformedURLException; 50: import java.net.URL; 51: import java.util.Enumeration; 52: import java.util.Random; 53: import java.util.logging.Level; 54: import java.util.logging.Logger; 55: 56: /** 57: * An interface to a cryptographically secure pseudo-random number 58: * generator (PRNG). Random (or at least unguessable) numbers are used 59: * in all areas of security and cryptography, from the generation of 60: * keys and initialization vectors to the generation of random padding 61: * bytes. 62: * 63: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 64: * @author Casey Marshall 65: */ 66: public class SecureRandom extends Random 67: { 68: 69: // Constants and fields. 70: // ------------------------------------------------------------------------ 71: 72: /** Service name for PRNGs. */ 73: private static final String SECURE_RANDOM = "SecureRandom"; 74: 75: private static final long serialVersionUID = 4940670005562187L; 76: 77: //Serialized Field 78: long counter = 0; //Serialized 79: Provider provider = null; 80: byte[] randomBytes = null; //Always null 81: int randomBytesUsed = 0; 82: SecureRandomSpi secureRandomSpi = null; 83: byte[] state = null; 84: private String algorithm; 85: 86: private boolean isSeeded = false; 87: 88: // Constructors. 89: // ------------------------------------------------------------------------ 90: 91: /** 92: Default constructor for SecureRandom. It constructs a 93: new SecureRandom by instantating the first SecureRandom 94: algorithm in the default security provier. 95: 96: It is not seeded and should be seeded using setSeed or else 97: on the first call to getnextBytes it will force a seed. 98: 99: It is maintained for backwards compatibility and programs 100: should use {@link #getInstance(java.lang.String)}. 101: */ 102: public SecureRandom() 103: { 104: Provider[] p = Security.getProviders(); 105: 106: //Format of Key: SecureRandom.algname 107: String key; 108: 109: String classname = null; 110: int i; 111: Enumeration e; 112: for (i = 0; i < p.length; i++) 113: { 114: e = p[i].propertyNames(); 115: while (e.hasMoreElements()) 116: { 117: key = (String) e.nextElement(); 118: if (key.startsWith("SECURERANDOM.")) 119: { 120: if ((classname = p[i].getProperty(key)) != null) 121: { 122: try 123: { 124: secureRandomSpi = (SecureRandomSpi) Class. 125: forName(classname).newInstance(); 126: provider = p[i]; 127: algorithm = key.substring(13); // Minus SecureRandom. 128: return; 129: } 130: catch (ThreadDeath death) 131: { 132: throw death; 133: } 134: catch (Throwable t) 135: { 136: // Ignore. 137: } 138: } 139: } 140: } 141: } 142: 143: // Nothing found. Fall back to SHA1PRNG 144: secureRandomSpi = new Sha160RandomSpi(); 145: algorithm = "Sha160"; 146: } 147: 148: /** 149: A constructor for SecureRandom. It constructs a new 150: SecureRandom by instantating the first SecureRandom algorithm 151: in the default security provier. 152: 153: It is seeded with the passed function and is useful if the user 154: has access to hardware random device (like a radiation detector). 155: 156: It is maintained for backwards compatibility and programs 157: should use getInstance. 158: 159: @param seed Seed bytes for class 160: */ 161: public SecureRandom(byte[] seed) 162: { 163: this(); 164: setSeed(seed); 165: } 166: 167: /** 168: A constructor for SecureRandom. It constructs a new 169: SecureRandom using the specified SecureRandomSpi from 170: the specified security provier. 171: 172: @param secureRandomSpi A SecureRandomSpi class 173: @param provider A Provider class 174: */ 175: protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider) 176: { 177: this(secureRandomSpi, provider, "unknown"); 178: } 179: 180: /** 181: * Private constructor called from the getInstance() method. 182: */ 183: private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider, 184: String algorithm) 185: { 186: this.secureRandomSpi = secureRandomSpi; 187: this.provider = provider; 188: this.algorithm = algorithm; 189: } 190: 191: // Class methods. 192: // ------------------------------------------------------------------------ 193: 194: /** 195: * Returns an instance of a SecureRandom. It creates the class from 196: * the first provider that implements it. 197: * 198: * @param algorithm The algorithm name. 199: * @return A new SecureRandom implementing the given algorithm. 200: * @throws NoSuchAlgorithmException If no installed provider implements 201: * the given algorithm. 202: */ 203: public static SecureRandom getInstance(String algorithm) 204: throws NoSuchAlgorithmException 205: { 206: Provider[] p = Security.getProviders(); 207: 208: for (int i = 0; i < p.length; i++) 209: { 210: try 211: { 212: return getInstance(algorithm, p[i]); 213: } 214: catch (NoSuchAlgorithmException e) 215: { 216: // Ignore. 217: } 218: } 219: 220: // None found. 221: throw new NoSuchAlgorithmException(algorithm); 222: } 223: 224: /** 225: * Returns an instance of a SecureRandom. It creates the class 226: * for the specified algorithm from the named provider. 227: * 228: * @param algorithm The algorithm name. 229: * @param provider The provider name. 230: * @return A new SecureRandom implementing the chosen algorithm. 231: * @throws NoSuchAlgorithmException If the named provider does not implement 232: * the algorithm, or if the implementation cannot be 233: * instantiated. 234: * @throws NoSuchProviderException If no provider named 235: * <code>provider</code> is currently installed. 236: * @throws IllegalArgumentException If <code>provider</code> is null 237: * or is empty. 238: */ 239: public static SecureRandom getInstance(String algorithm, String provider) 240: throws NoSuchAlgorithmException, NoSuchProviderException 241: { 242: if (provider == null || provider.length() == 0) 243: throw new IllegalArgumentException("Illegal provider"); 244: 245: Provider p = Security.getProvider(provider); 246: if (p == null) 247: throw new NoSuchProviderException(provider); 248: 249: return getInstance(algorithm, p); 250: } 251: 252: /** 253: * Returns an instance of a SecureRandom. It creates the class for 254: * the specified algorithm from the given provider. 255: * 256: * @param algorithm The SecureRandom algorithm to create. 257: * @param provider The provider to get the instance from. 258: * @throws NoSuchAlgorithmException If the algorithm cannot be found, or 259: * if the class cannot be instantiated. 260: * @throws IllegalArgumentException If <code>provider</code> is null. 261: */ 262: public static SecureRandom getInstance(String algorithm, Provider provider) 263: throws NoSuchAlgorithmException 264: { 265: if (provider == null) 266: throw new IllegalArgumentException("Illegal provider"); 267: try 268: { 269: return new SecureRandom((SecureRandomSpi) 270: Engine.getInstance(SECURE_RANDOM, algorithm, provider), 271: provider, algorithm); 272: } 273: catch (java.lang.reflect.InvocationTargetException ite) 274: { 275: throw new NoSuchAlgorithmException(algorithm); 276: } 277: catch (ClassCastException cce) 278: { 279: throw new NoSuchAlgorithmException(algorithm); 280: } 281: } 282: 283: // Instance methods. 284: // ------------------------------------------------------------------------ 285: 286: /** 287: Returns the provider being used by the current SecureRandom class. 288: 289: @return The provider from which this SecureRandom was attained 290: */ 291: public final Provider getProvider() 292: { 293: return provider; 294: } 295: 296: /** 297: * Returns the algorithm name used or "unknown" when the algorithm 298: * used couldn't be determined (as when constructed by the protected 299: * 2 argument constructor). 300: * 301: * @since 1.5 302: */ 303: public String getAlgorithm() 304: { 305: return algorithm; 306: } 307: 308: /** 309: Seeds the SecureRandom. The class is re-seeded for each call and 310: each seed builds on the previous seed so as not to weaken security. 311: 312: @param seed seed bytes to seed with 313: */ 314: public void setSeed(byte[] seed) 315: { 316: secureRandomSpi.engineSetSeed(seed); 317: isSeeded = true; 318: } 319: 320: /** 321: Seeds the SecureRandom. The class is re-seeded for each call and 322: each seed builds on the previous seed so as not to weaken security. 323: 324: @param seed 8 seed bytes to seed with 325: */ 326: public void setSeed(long seed) 327: { 328: // This particular setSeed will be called by Random.Random(), via 329: // our own constructor, before secureRandomSpi is initialized. In 330: // this case we can't call a method on secureRandomSpi, and we 331: // definitely don't want to throw a NullPointerException. 332: // Therefore we test. 333: if (secureRandomSpi != null) 334: { 335: byte[] tmp = { (byte) (0xff & (seed >> 56)), 336: (byte) (0xff & (seed >> 48)), 337: (byte) (0xff & (seed >> 40)), 338: (byte) (0xff & (seed >> 32)), 339: (byte) (0xff & (seed >> 24)), 340: (byte) (0xff & (seed >> 16)), 341: (byte) (0xff & (seed >> 8)), 342: (byte) (0xff & seed) 343: }; 344: secureRandomSpi.engineSetSeed(tmp); 345: isSeeded = true; 346: } 347: } 348: 349: /** 350: Generates a user specified number of bytes. This function 351: is the basis for all the random functions. 352: 353: @param bytes array to store generated bytes in 354: */ 355: public void nextBytes(byte[] bytes) 356: { 357: if (!isSeeded) 358: setSeed(getSeed(32)); 359: randomBytesUsed += bytes.length; 360: counter++; 361: secureRandomSpi.engineNextBytes(bytes); 362: } 363: 364: /** 365: Generates an integer containing the user specified 366: number of random bits. It is right justified and padded 367: with zeros. 368: 369: @param numBits number of random bits to get, 0 <= numBits <= 32; 370: 371: @return the random bits 372: */ 373: protected final int next(int numBits) 374: { 375: if (numBits == 0) 376: return 0; 377: 378: byte[] tmp = new byte[(numBits + 7) / 8]; 379: this.nextBytes(tmp); 380: int ret = 0; 381: for (int i = 0; i < tmp.length; i++) 382: ret |= (tmp[i] & 0xFF) << (8 * i); 383: 384: long mask = (1L << numBits) - 1; 385: return (int) (ret & mask); 386: } 387: 388: /** 389: Returns the given number of seed bytes. This method is 390: maintained only for backwards capability. 391: 392: @param numBytes number of seed bytes to get 393: 394: @return an array containing the seed bytes 395: */ 396: public static byte[] getSeed(int numBytes) 397: { 398: return SecureRandomAdapter.getSeed(numBytes); 399: } 400: 401: /** 402: Returns the specified number of seed bytes. 403: 404: @param numBytes number of seed bytes to get 405: 406: @return an array containing the seed bytes 407: */ 408: public byte[] generateSeed(int numBytes) 409: { 410: return secureRandomSpi.engineGenerateSeed(numBytes); 411: } 412: 413: }