Merge from mainline.
[official-gcc.git] / libjava / classpath / java / security / SecureRandom.java
blobd403d4964286654af54cf38ef7d1a0e474483a41
1 /* SecureRandom.java --- Secure Random class implementation
2 Copyright (C) 1999, 2001, 2002, 2003, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package java.security;
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.Sha160RandomSpi;
46 import java.io.IOException;
47 import java.io.InputStream;
48 import java.net.MalformedURLException;
49 import java.net.URL;
50 import java.util.Enumeration;
51 import java.util.Random;
52 import java.util.logging.Level;
53 import java.util.logging.Logger;
55 /**
56 * An interface to a cryptographically secure pseudo-random number
57 * generator (PRNG). Random (or at least unguessable) numbers are used
58 * in all areas of security and cryptography, from the generation of
59 * keys and initialization vectors to the generation of random padding
60 * bytes.
62 * @author Mark Benvenuto (ivymccough@worldnet.att.net)
63 * @author Casey Marshall
65 public class SecureRandom extends Random
68 // Constants and fields.
69 // ------------------------------------------------------------------------
71 /** Service name for PRNGs. */
72 private static final String SECURE_RANDOM = "SecureRandom";
74 private static final long serialVersionUID = 4940670005562187L;
76 //Serialized Field
77 long counter = 0; //Serialized
78 Provider provider = null;
79 byte[] randomBytes = null; //Always null
80 int randomBytesUsed = 0;
81 SecureRandomSpi secureRandomSpi = null;
82 byte[] state = null;
83 private String algorithm;
85 private boolean isSeeded = false;
87 // Constructors.
88 // ------------------------------------------------------------------------
90 /**
91 Default constructor for SecureRandom. It constructs a
92 new SecureRandom by instantating the first SecureRandom
93 algorithm in the default security provier.
95 It is not seeded and should be seeded using setSeed or else
96 on the first call to getnextBytes it will force a seed.
98 It is maintained for backwards compatibility and programs
99 should use {@link #getInstance(java.lang.String)}.
101 public SecureRandom()
103 Provider[] p = Security.getProviders();
105 //Format of Key: SecureRandom.algname
106 String key;
108 String classname = null;
109 int i;
110 Enumeration e;
111 for (i = 0; i < p.length; i++)
113 e = p[i].propertyNames();
114 while (e.hasMoreElements())
116 key = (String) e.nextElement();
117 if (key.startsWith("SECURERANDOM."))
119 if ((classname = p[i].getProperty(key)) != null)
123 secureRandomSpi = (SecureRandomSpi) Class.
124 forName(classname).newInstance();
125 provider = p[i];
126 algorithm = key.substring(13); // Minus SecureRandom.
127 return;
129 catch (ThreadDeath death)
131 throw death;
133 catch (Throwable t)
135 // Ignore.
142 // Nothing found. Fall back to SHA1PRNG
143 secureRandomSpi = new Sha160RandomSpi();
144 algorithm = "Sha160";
148 A constructor for SecureRandom. It constructs a new
149 SecureRandom by instantating the first SecureRandom algorithm
150 in the default security provier.
152 It is seeded with the passed function and is useful if the user
153 has access to hardware random device (like a radiation detector).
155 It is maintained for backwards compatibility and programs
156 should use getInstance.
158 @param seed Seed bytes for class
160 public SecureRandom(byte[] seed)
162 this();
163 setSeed(seed);
167 A constructor for SecureRandom. It constructs a new
168 SecureRandom using the specified SecureRandomSpi from
169 the specified security provier.
171 @param secureRandomSpi A SecureRandomSpi class
172 @param provider A Provider class
174 protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
176 this(secureRandomSpi, provider, "unknown");
180 * Private constructor called from the getInstance() method.
182 private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider,
183 String algorithm)
185 this.secureRandomSpi = secureRandomSpi;
186 this.provider = provider;
187 this.algorithm = algorithm;
190 // Class methods.
191 // ------------------------------------------------------------------------
194 * Returns an instance of a SecureRandom. It creates the class from
195 * the first provider that implements it.
197 * @param algorithm The algorithm name.
198 * @return A new SecureRandom implementing the given algorithm.
199 * @throws NoSuchAlgorithmException If no installed provider implements
200 * the given algorithm.
202 public static SecureRandom getInstance(String algorithm)
203 throws NoSuchAlgorithmException
205 Provider[] p = Security.getProviders();
207 for (int i = 0; i < p.length; i++)
211 return getInstance(algorithm, p[i]);
213 catch (NoSuchAlgorithmException e)
215 // Ignore.
219 // None found.
220 throw new NoSuchAlgorithmException(algorithm);
224 * Returns an instance of a SecureRandom. It creates the class
225 * for the specified algorithm from the named provider.
227 * @param algorithm The algorithm name.
228 * @param provider The provider name.
229 * @return A new SecureRandom implementing the chosen algorithm.
230 * @throws NoSuchAlgorithmException If the named provider does not implement
231 * the algorithm, or if the implementation cannot be
232 * instantiated.
233 * @throws NoSuchProviderException If no provider named
234 * <code>provider</code> is currently installed.
235 * @throws IllegalArgumentException If <code>provider</code> is null
236 * or is empty.
238 public static SecureRandom getInstance(String algorithm, String provider)
239 throws NoSuchAlgorithmException, NoSuchProviderException
241 if (provider == null || provider.length() == 0)
242 throw new IllegalArgumentException("Illegal provider");
244 Provider p = Security.getProvider(provider);
245 if (p == null)
246 throw new NoSuchProviderException(provider);
248 return getInstance(algorithm, p);
252 * Returns an instance of a SecureRandom. It creates the class for
253 * the specified algorithm from the given provider.
255 * @param algorithm The SecureRandom algorithm to create.
256 * @param provider The provider to get the instance from.
257 * @throws NoSuchAlgorithmException If the algorithm cannot be found, or
258 * if the class cannot be instantiated.
259 * @throws IllegalArgumentException If <code>provider</code> is null.
261 public static SecureRandom getInstance(String algorithm, Provider provider)
262 throws NoSuchAlgorithmException
264 if (provider == null)
265 throw new IllegalArgumentException("Illegal provider");
268 return new SecureRandom((SecureRandomSpi)
269 Engine.getInstance(SECURE_RANDOM, algorithm, provider),
270 provider, algorithm);
272 catch (java.lang.reflect.InvocationTargetException ite)
274 throw new NoSuchAlgorithmException(algorithm);
276 catch (ClassCastException cce)
278 throw new NoSuchAlgorithmException(algorithm);
282 // Instance methods.
283 // ------------------------------------------------------------------------
286 Returns the provider being used by the current SecureRandom class.
288 @return The provider from which this SecureRandom was attained
290 public final Provider getProvider()
292 return provider;
296 * Returns the algorithm name used or "unknown" when the algorithm
297 * used couldn't be determined (as when constructed by the protected
298 * 2 argument constructor).
300 * @since 1.5
302 public String getAlgorithm()
304 return algorithm;
308 Seeds the SecureRandom. The class is re-seeded for each call and
309 each seed builds on the previous seed so as not to weaken security.
311 @param seed seed bytes to seed with
313 public void setSeed(byte[] seed)
315 secureRandomSpi.engineSetSeed(seed);
316 isSeeded = true;
320 Seeds the SecureRandom. The class is re-seeded for each call and
321 each seed builds on the previous seed so as not to weaken security.
323 @param seed 8 seed bytes to seed with
325 public void setSeed(long seed)
327 // This particular setSeed will be called by Random.Random(), via
328 // our own constructor, before secureRandomSpi is initialized. In
329 // this case we can't call a method on secureRandomSpi, and we
330 // definitely don't want to throw a NullPointerException.
331 // Therefore we test.
332 if (secureRandomSpi != null)
334 byte[] tmp = { (byte) (0xff & (seed >> 56)),
335 (byte) (0xff & (seed >> 48)),
336 (byte) (0xff & (seed >> 40)),
337 (byte) (0xff & (seed >> 32)),
338 (byte) (0xff & (seed >> 24)),
339 (byte) (0xff & (seed >> 16)),
340 (byte) (0xff & (seed >> 8)),
341 (byte) (0xff & seed)
343 secureRandomSpi.engineSetSeed(tmp);
344 isSeeded = true;
349 Generates a user specified number of bytes. This function
350 is the basis for all the random functions.
352 @param bytes array to store generated bytes in
354 public void nextBytes(byte[] bytes)
356 if (!isSeeded)
357 setSeed(getSeed(32));
358 randomBytesUsed += bytes.length;
359 counter++;
360 secureRandomSpi.engineNextBytes(bytes);
364 Generates an integer containing the user specified
365 number of random bits. It is right justified and padded
366 with zeros.
368 @param numBits number of random bits to get, 0 <= numBits <= 32;
370 @return the random bits
372 protected final int next(int numBits)
374 if (numBits == 0)
375 return 0;
377 byte[] tmp = new byte[numBits / 8 + (1 * (numBits % 8))];
379 secureRandomSpi.engineNextBytes(tmp);
380 randomBytesUsed += tmp.length;
381 counter++;
383 int ret = 0;
385 for (int i = 0; i < tmp.length; i++)
386 ret |= (tmp[i] & 0xFF) << (8 * i);
388 long mask = (1L << numBits) - 1;
389 return (int) (ret & mask);
393 Returns the given number of seed bytes. This method is
394 maintained only for backwards capability.
396 @param numBytes number of seed bytes to get
398 @return an array containing the seed bytes
400 public static byte[] getSeed(int numBytes)
402 byte[] tmp = new byte[numBytes];
403 generateSeed(tmp);
404 return tmp;
408 Returns the specified number of seed bytes.
410 @param numBytes number of seed bytes to get
412 @return an array containing the seed bytes
414 public byte[] generateSeed(int numBytes)
416 return secureRandomSpi.engineGenerateSeed(numBytes);
419 // Seed methods.
421 private static final String SECURERANDOM_SOURCE = "securerandom.source";
422 private static final String JAVA_SECURITY_EGD = "java.security.egd";
423 private static final Logger logger = Logger.getLogger(SecureRandom.class.getName());
425 private static int generateSeed(byte[] buffer)
427 return generateSeed(buffer, 0, buffer.length);
430 private static int generateSeed(byte[] buffer, int offset, int length)
432 URL sourceUrl = null;
433 String urlStr = null;
435 GetSecurityPropertyAction action = new GetSecurityPropertyAction(SECURERANDOM_SOURCE);
438 urlStr = (String) AccessController.doPrivileged(action);
439 if (urlStr != null)
440 sourceUrl = new URL(urlStr);
442 catch (MalformedURLException ignored)
444 logger.log(Level.WARNING, SECURERANDOM_SOURCE + " property is malformed: {0}",
445 urlStr);
448 if (sourceUrl == null)
452 urlStr = SystemProperties.getProperty(JAVA_SECURITY_EGD);
453 if (urlStr != null)
454 sourceUrl = new URL(urlStr);
456 catch (MalformedURLException mue)
458 logger.log(Level.WARNING, JAVA_SECURITY_EGD + " property is malformed: {0}",
459 urlStr);
463 if (sourceUrl != null)
467 InputStream in = sourceUrl.openStream();
468 return in.read(buffer, offset, length);
470 catch (IOException ioe)
472 logger.log(Level.FINE, "error reading random bytes", ioe);
476 // If we get here, we did not get any seed from a property URL.
477 return VMSecureRandom.generateSeed(buffer, offset, length);