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