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