OSDN Git Service

Add license clarification.
[pf3gnuchains/gcc-fork.git] / libjava / java / security / SecureRandom.java
1 /* SecureRandom.java --- Secure Random class implmentation
2    Copyright (C) 1999, 2001 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 import java.io.Serializable;
40 import java.util.Random;
41 import java.util.Enumeration;
42
43 /**
44    SecureRandom is the class interface for using SecureRandom
45    providers. It provides an interface to the SecureRandomSpi
46    engine so that programmers can generate pseudo-random numbers.
47
48    @author Mark Benvenuto <ivymccough@worldnet.att.net>
49  */
50 public class SecureRandom extends Random
51 {
52   //Serialized Field
53   long counter = 0;             //Serialized
54   MessageDigest digest = null;
55   Provider provider = null;
56   byte[] randomBytes = null;    //Always null
57   int randomBytesUsed = 0;
58   SecureRandomSpi secureRandomSpi = null;
59   byte[] state = null;
60
61   /**
62      Default constructor for SecureRandom. It constructs a 
63      new SecureRandom by instantating the first SecureRandom 
64      algorithm in the default security provier. 
65
66      It is not seeded and should be seeded using setSeed or else
67      on the first call to getnextBytes it will force a seed.
68
69      It is maintained for backwards compatibility and programs
70      should use getInstance.
71    */
72   public SecureRandom()
73   {
74     Provider p[] = Security.getProviders();
75
76     //Format of Key: SecureRandom.algname
77     String key;
78
79     String classname = null;
80     int i, flag = 0;
81     Enumeration e;
82     for (i = 0; i < p.length; i++)
83       {
84         e = p[i].propertyNames();
85         while (e.hasMoreElements())
86           {
87             key = (String) e.nextElement();
88             if (key.startsWith("SecureRandom."))
89               if ((classname = p[i].getProperty(key)) != null)
90                 break;
91           }
92         if (classname != null)
93             break;
94       }
95
96     //if( classname == null)
97     //  throw new NoSuchAlgorithmException();
98
99     try
100       {
101         this.secureRandomSpi =
102           (SecureRandomSpi) Class.forName(classname).newInstance();
103
104         //s.algorithm = algorithm;
105         this.provider = p[i];
106       }
107     catch (ClassNotFoundException cnfe)
108       {
109         //throw new NoSuchAlgorithmException("Class not found");
110       }
111     catch (InstantiationException ie)
112       {
113         //throw new NoSuchAlgorithmException("Class instantiation failed");
114       }
115     catch (IllegalAccessException iae)
116       {
117         //throw new NoSuchAlgorithmException("Illegal Access");
118       }
119   }
120
121   /**
122      A constructor for SecureRandom. It constructs a new 
123      SecureRandom by instantating the first SecureRandom algorithm 
124      in the default security provier. 
125
126      It is seeded with the passed function and is useful if the user
127      has access to hardware random device (like a radiation detector).
128
129      It is maintained for backwards compatibility and programs
130      should use getInstance.
131
132      @param seed Seed bytes for class
133    */
134   public SecureRandom(byte[] seed)
135   {
136     this();
137     setSeed(seed);
138   }
139
140   /**
141      A constructor for SecureRandom. It constructs a new 
142      SecureRandom using the specified SecureRandomSpi from
143      the specified security provier. 
144
145      @param secureRandomSpi A SecureRandomSpi class
146      @param provider A Provider class
147    */
148   protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
149   {
150     this.secureRandomSpi = secureRandomSpi;
151     this.provider = provider;
152   }
153
154   /**
155      Returns an instance of a SecureRandom. It creates the class
156      for the specified algorithm if it exists from a provider.
157
158      @param algorithm A SecureRandom algorithm to use
159
160      @return Returns a new SecureRandom implmenting the chosen algorithm
161
162      @throws NoSuchAlgorithmException if the algorithm cannot be found
163    */
164   public static SecureRandom getInstance(String algorithm) throws
165     NoSuchAlgorithmException
166   {
167     Provider p[] = Security.getProviders();
168
169     //Format of Key: SecureRandom.algname
170     StringBuffer key = new StringBuffer("SecureRandom.");
171     key.append(algorithm);
172
173     String classname = null;
174     int i;
175     for (i = 0; i < p.length; i++)
176       {
177         if ((classname = p[i].getProperty(key.toString())) != null)
178           break;
179       }
180
181     if (classname == null)
182         throw new NoSuchAlgorithmException();
183
184     try
185       {
186         return new SecureRandom((SecureRandomSpi) Class.forName(classname).
187                                 newInstance(), p[i]);
188       }
189     catch (ClassNotFoundException cnfe)
190       {
191         throw new NoSuchAlgorithmException("Class not found");
192       }
193     catch (InstantiationException ie)
194       {
195         throw new NoSuchAlgorithmException("Class instantiation failed");
196       }
197     catch (IllegalAccessException iae)
198       {
199         throw new NoSuchAlgorithmException("Illegal Access");
200       }
201
202   }
203
204   /**
205      Returns an instance of a SecureRandom. It creates the class
206      for the specified algorithm from the specified provider.
207
208      @param algorithm A SecureRandom algorithm to use
209      @param provider A security provider to use
210
211      @return Returns a new SecureRandom implmenting the chosen algorithm
212
213      @throws NoSuchAlgorithmException if the algorithm cannot be found
214      @throws NoSuchProviderException if the provider cannot be found
215    */
216   public static SecureRandom getInstance(String algorithm,
217                                          String provider) throws
218     NoSuchAlgorithmException, NoSuchProviderException
219   {
220     Provider p = Security.getProvider(provider);
221     if (p == null)
222       throw new NoSuchProviderException();
223
224     //Format of Key: SecureRandom.algName
225     StringBuffer key = new StringBuffer("SecureRandom.");
226     key.append(algorithm);
227
228     String classname = p.getProperty(key.toString());
229     if (classname == null)
230       throw new NoSuchAlgorithmException();
231
232     try
233       {
234         return new SecureRandom((SecureRandomSpi) Class.forName(classname).
235                                 newInstance(), p);
236       }
237     catch (ClassNotFoundException cnfe)
238       {
239         throw new NoSuchAlgorithmException("Class not found");
240       }
241     catch (InstantiationException ie)
242       {
243         throw new NoSuchAlgorithmException("Class instantiation failed");
244       }
245     catch (IllegalAccessException iae)
246       {
247         throw new NoSuchAlgorithmException("Illegal Access");
248       }
249
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    */
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    */
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    */
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    */
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    */
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] << (8 * i);
338
339     return ret;
340   }
341
342   /**
343      Returns the given number of seed bytes. This method is
344      maintained only for backwards capability. 
345
346      @param numBytes number of seed bytes to get
347
348      @return an array containing the seed bytes
349    */
350   public static byte[] getSeed(int numBytes)
351   {
352     byte tmp[] = new byte[numBytes];
353
354     new Random().nextBytes(tmp);
355     return tmp;
356     //return secureRandomSpi.engineGenerateSeed( numBytes );
357   }
358
359   /**
360      Returns the specified number of seed bytes.
361
362      @param numBytes number of seed bytes to get
363
364      @return an array containing the seed bytes
365    */
366   public byte[] generateSeed(int numBytes)
367   {
368     return secureRandomSpi.engineGenerateSeed(numBytes);
369   }
370
371 }