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.lang.CPStringBuilder; 43: import gnu.java.security.Engine; 44: import gnu.java.security.action.GetSecurityPropertyAction; 45: import gnu.java.security.jce.prng.SecureRandomAdapter; 46: import gnu.java.security.jce.prng.Sha160RandomSpi; 47: 48: import java.io.IOException; 49: import java.io.InputStream; 50: import java.lang.reflect.InvocationTargetException; 51: import java.net.MalformedURLException; 52: import java.net.URL; 53: import java.util.Enumeration; 54: import java.util.Random; 55: import java.util.logging.Level; 56: import java.util.logging.Logger; 57: 58: /** 59: * An interface to a cryptographically secure pseudo-random number 60: * generator (PRNG). Random (or at least unguessable) numbers are used 61: * in all areas of security and cryptography, from the generation of 62: * keys and initialization vectors to the generation of random padding 63: * bytes. 64: * 65: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 66: * @author Casey Marshall 67: */ 68: public class SecureRandom extends Random 69: { 70: 71: // Constants and fields. 72: // ------------------------------------------------------------------------ 73: 74: /** Service name for PRNGs. */ 75: private static final String SECURE_RANDOM = "SecureRandom"; 76: 77: private static final long serialVersionUID = 4940670005562187L; 78: 79: //Serialized Field 80: long counter = 0; //Serialized 81: Provider provider = null; 82: byte[] randomBytes = null; //Always null 83: int randomBytesUsed = 0; 84: SecureRandomSpi secureRandomSpi = null; 85: byte[] state = null; 86: private String algorithm; 87: 88: private boolean isSeeded = false; 89: 90: // Constructors. 91: // ------------------------------------------------------------------------ 92: 93: /** 94: Default constructor for SecureRandom. It constructs a 95: new SecureRandom by instantating the first SecureRandom 96: algorithm in the default security provier. 97: 98: It is not seeded and should be seeded using setSeed or else 99: on the first call to getnextBytes it will force a seed. 100: 101: It is maintained for backwards compatibility and programs 102: should use {@link #getInstance(java.lang.String)}. 103: */ 104: public SecureRandom() 105: { 106: Provider[] p = Security.getProviders(); 107: 108: //Format of Key: SecureRandom.algname 109: String key; 110: 111: String classname = null; 112: int i; 113: Enumeration e; 114: for (i = 0; i < p.length; i++) 115: { 116: e = p[i].propertyNames(); 117: while (e.hasMoreElements()) 118: { 119: key = (String) e.nextElement(); 120: if (key.startsWith("SECURERANDOM.")) 121: { 122: if ((classname = p[i].getProperty(key)) != null) 123: { 124: try 125: { 126: secureRandomSpi = (SecureRandomSpi) Class. 127: forName(classname).newInstance(); 128: provider = p[i]; 129: algorithm = key.substring(13); // Minus SecureRandom. 130: return; 131: } 132: catch (ThreadDeath death) 133: { 134: throw death; 135: } 136: catch (Throwable t) 137: { 138: // Ignore. 139: } 140: } 141: } 142: } 143: } 144: 145: // Nothing found. Fall back to SHA1PRNG 146: secureRandomSpi = new Sha160RandomSpi(); 147: algorithm = "Sha160"; 148: } 149: 150: /** 151: A constructor for SecureRandom. It constructs a new 152: SecureRandom by instantating the first SecureRandom algorithm 153: in the default security provier. 154: 155: It is seeded with the passed function and is useful if the user 156: has access to hardware random device (like a radiation detector). 157: 158: It is maintained for backwards compatibility and programs 159: should use getInstance. 160: 161: @param seed Seed bytes for class 162: */ 163: public SecureRandom(byte[] seed) 164: { 165: this(); 166: setSeed(seed); 167: } 168: 169: /** 170: A constructor for SecureRandom. It constructs a new 171: SecureRandom using the specified SecureRandomSpi from 172: the specified security provier. 173: 174: @param secureRandomSpi A SecureRandomSpi class 175: @param provider A Provider class 176: */ 177: protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider) 178: { 179: this(secureRandomSpi, provider, "unknown"); 180: } 181: 182: /** 183: * Private constructor called from the getInstance() method. 184: */ 185: private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider, 186: String algorithm) 187: { 188: this.secureRandomSpi = secureRandomSpi; 189: this.provider = provider; 190: this.algorithm = algorithm; 191: } 192: 193: /** 194: * Returns an instance of a <code>SecureRandom</code> from the first provider 195: * that implements it. 196: * 197: * @param algorithm The algorithm name. 198: * @return A new <code>SecureRandom</code> implementing the given algorithm. 199: * @throws NoSuchAlgorithmException If no installed provider implements the 200: * given algorithm. 201: * @throws IllegalArgumentException if <code>algorithm</code> is 202: * <code>null</code> or is an empty string. 203: */ 204: public static SecureRandom getInstance(String algorithm) 205: throws NoSuchAlgorithmException 206: { 207: Provider[] p = Security.getProviders(); 208: NoSuchAlgorithmException lastException = null; 209: for (int i = 0; i < p.length; i++) 210: try 211: { 212: return getInstance(algorithm, p[i]); 213: } 214: catch (NoSuchAlgorithmException x) 215: { 216: lastException = x; 217: } 218: if (lastException != null) 219: throw lastException; 220: throw new NoSuchAlgorithmException(algorithm); 221: } 222: 223: /** 224: * Returns an instance of a <code>SecureRandom</code> for the specified 225: * algorithm from the named provider. 226: * 227: * @param algorithm The algorithm name. 228: * @param provider The provider name. 229: * @return A new <code>SecureRandom</code> implementing the chosen 230: * algorithm. 231: * @throws NoSuchAlgorithmException If the named provider does not implement 232: * the algorithm, or if the implementation cannot be instantiated. 233: * @throws NoSuchProviderException If no provider named <code>provider</code> 234: * is currently installed. 235: * @throws IllegalArgumentException if either <code>algorithm</code> or 236: * <code>provider</code> is <code>null</code> or empty. 237: */ 238: public static SecureRandom getInstance(String algorithm, String provider) 239: throws NoSuchAlgorithmException, NoSuchProviderException 240: { 241: if (provider == null) 242: throw new IllegalArgumentException("provider MUST NOT be null"); 243: provider = provider.trim(); 244: if (provider.length() == 0) 245: throw new IllegalArgumentException("provider MUST NOT be empty"); 246: Provider p = Security.getProvider(provider); 247: if (p == null) 248: throw new NoSuchProviderException(provider); 249: return getInstance(algorithm, p); 250: } 251: 252: /** 253: * Returns an instance of a <code>SecureRandom</code> for the specified 254: * algorithm from the given provider. 255: * 256: * @param algorithm The <code>SecureRandom</code> algorithm to create. 257: * @param provider The provider to use. 258: * @throws NoSuchAlgorithmException If the algorithm cannot be found, or if 259: * the class cannot be instantiated. 260: * @throws IllegalArgumentException if either <code>algorithm</code> or 261: * <code>provider</code> is <code>null</code>, or if 262: * <code>algorithm</code> is an empty string. 263: */ 264: public static SecureRandom getInstance(String algorithm, Provider provider) 265: throws NoSuchAlgorithmException 266: { 267: CPStringBuilder sb = new CPStringBuilder("SecureRandom for algorithm [") 268: .append(algorithm).append("] from provider[") 269: .append(provider).append("] could not be created"); 270: Throwable cause; 271: try 272: { 273: Object spi = Engine.getInstance(SECURE_RANDOM, algorithm, provider); 274: return new SecureRandom((SecureRandomSpi) spi, provider, algorithm); 275: } 276: catch (InvocationTargetException x) 277: { 278: cause = x.getCause(); 279: if (cause instanceof NoSuchAlgorithmException) 280: throw (NoSuchAlgorithmException) cause; 281: if (cause == null) 282: cause = x; 283: } 284: catch (ClassCastException x) 285: { 286: cause = x; 287: } 288: NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); 289: x.initCause(cause); 290: throw x; 291: } 292: 293: /** 294: Returns the provider being used by the current SecureRandom class. 295: 296: @return The provider from which this SecureRandom was attained 297: */ 298: public final Provider getProvider() 299: { 300: return provider; 301: } 302: 303: /** 304: * Returns the algorithm name used or "unknown" when the algorithm 305: * used couldn't be determined (as when constructed by the protected 306: * 2 argument constructor). 307: * 308: * @since 1.5 309: */ 310: public String getAlgorithm() 311: { 312: return algorithm; 313: } 314: 315: /** 316: Seeds the SecureRandom. The class is re-seeded for each call and 317: each seed builds on the previous seed so as not to weaken security. 318: 319: @param seed seed bytes to seed with 320: */ 321: public void setSeed(byte[] seed) 322: { 323: secureRandomSpi.engineSetSeed(seed); 324: isSeeded = true; 325: } 326: 327: /** 328: Seeds the SecureRandom. The class is re-seeded for each call and 329: each seed builds on the previous seed so as not to weaken security. 330: 331: @param seed 8 seed bytes to seed with 332: */ 333: public void setSeed(long seed) 334: { 335: // This particular setSeed will be called by Random.Random(), via 336: // our own constructor, before secureRandomSpi is initialized. In 337: // this case we can't call a method on secureRandomSpi, and we 338: // definitely don't want to throw a NullPointerException. 339: // Therefore we test. 340: if (secureRandomSpi != null) 341: { 342: byte[] tmp = { (byte) (0xff & (seed >> 56)), 343: (byte) (0xff & (seed >> 48)), 344: (byte) (0xff & (seed >> 40)), 345: (byte) (0xff & (seed >> 32)), 346: (byte) (0xff & (seed >> 24)), 347: (byte) (0xff & (seed >> 16)), 348: (byte) (0xff & (seed >> 8)), 349: (byte) (0xff & seed) 350: }; 351: secureRandomSpi.engineSetSeed(tmp); 352: isSeeded = true; 353: } 354: } 355: 356: /** 357: Generates a user specified number of bytes. This function 358: is the basis for all the random functions. 359: 360: @param bytes array to store generated bytes in 361: */ 362: public void nextBytes(byte[] bytes) 363: { 364: if (!isSeeded) 365: setSeed(getSeed(32)); 366: randomBytesUsed += bytes.length; 367: counter++; 368: secureRandomSpi.engineNextBytes(bytes); 369: } 370: 371: /** 372: Generates an integer containing the user specified 373: number of random bits. It is right justified and padded 374: with zeros. 375: 376: @param numBits number of random bits to get, 0 <= numBits <= 32; 377: 378: @return the random bits 379: */ 380: protected final int next(int numBits) 381: { 382: if (numBits == 0) 383: return 0; 384: 385: byte[] tmp = new byte[(numBits + 7) / 8]; 386: this.nextBytes(tmp); 387: int ret = 0; 388: for (int i = 0; i < tmp.length; i++) 389: ret |= (tmp[i] & 0xFF) << (8 * i); 390: 391: long mask = (1L << numBits) - 1; 392: return (int) (ret & mask); 393: } 394: 395: /** 396: Returns the given number of seed bytes. This method is 397: maintained only for backwards capability. 398: 399: @param numBytes number of seed bytes to get 400: 401: @return an array containing the seed bytes 402: */ 403: public static byte[] getSeed(int numBytes) 404: { 405: return SecureRandomAdapter.getSeed(numBytes); 406: } 407: 408: /** 409: Returns the specified number of seed bytes. 410: 411: @param numBytes number of seed bytes to get 412: 413: @return an array containing the seed bytes 414: */ 415: public byte[] generateSeed(int numBytes) 416: { 417: return secureRandomSpi.engineGenerateSeed(numBytes); 418: } 419: 420: }