001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris V. Kuznetsov
020: * @version $Revision$
021: */package java.security;
022:
023: import java.util.Iterator;
024: import java.util.Random;
025: import java.util.Set;
026:
027: import org.apache.harmony.security.fortress.Engine;
028: import org.apache.harmony.security.fortress.Services;
029: import org.apache.harmony.security.internal.nls.Messages;
030:
031: import org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl;
032:
033: /**
034: * @com.intel.drl.spec_ref
035: *
036: */
037:
038: public class SecureRandom extends Random {
039:
040: /**
041: * @com.intel.drl.spec_ref
042: *
043: */
044: private static final long serialVersionUID = 4940670005562187L;
045:
046: // The service name.
047: private static final transient String SERVICE = "SecureRandom"; //$NON-NLS-1$
048:
049: // Used to access common engine functionality
050: private static transient Engine engine = new Engine(SERVICE);
051:
052: /**
053: * @com.intel.drl.spec_ref
054: */
055: private Provider provider;
056:
057: /**
058: * @com.intel.drl.spec_ref
059: */
060: private SecureRandomSpi secureRandomSpi;
061:
062: /**
063: * @com.intel.drl.spec_ref
064: */
065: private String algorithm;
066:
067: /**
068: * @com.intel.drl.spec_ref
069: */
070: private byte[] state;
071:
072: /**
073: * @com.intel.drl.spec_ref
074: */
075: private byte[] randomBytes;
076:
077: /**
078: * @com.intel.drl.spec_ref
079: */
080: private int randomBytesUsed;
081:
082: /**
083: * @com.intel.drl.spec_ref
084: */
085: private long counter;
086:
087: // Internal SecureRandom used for getSeed(int)
088: private static transient SecureRandom internalSecureRandom;
089:
090: /**
091: * Constructs a new instance of this class. Users are encouraged to use
092: * <code>getInstance()</code> instead.
093: *
094: * An implementation for the highest-priority provider is returned. The
095: * instance returned will not have been seeded.
096: */
097: public SecureRandom() {
098: super (0);
099: Provider.Service service = findService();
100: if (service == null) {
101: this .provider = null;
102: this .secureRandomSpi = new SHA1PRNG_SecureRandomImpl();
103: this .algorithm = "SHA1PRNG"; //$NON-NLS-1$
104: } else {
105: try {
106: this .provider = service.getProvider();
107: this .secureRandomSpi = (SecureRandomSpi) service
108: .newInstance(null);
109: this .algorithm = service.getAlgorithm();
110: } catch (Exception e) {
111: throw new RuntimeException(e);
112: }
113: }
114: }
115:
116: /**
117: * Constructs a new instance of this class. Users are encouraged to use
118: * <code>getInstance()</code> instead.
119: *
120: * An implementation for the highest-priority provider is returned. The
121: * instance returned will be seeded with the parameter.
122: *
123: * @param seed
124: * bytes forming the seed for this generator.
125: */
126: public SecureRandom(byte[] seed) {
127: this ();
128: setSeed(seed);
129: }
130:
131: //Find SecureRandom service.
132: private Provider.Service findService() {
133: Set s;
134: Provider.Service service;
135: for (Iterator it1 = Services.getProvidersList().iterator(); it1
136: .hasNext();) {
137: service = ((Provider) it1.next())
138: .getService("SecureRandom"); //$NON-NLS-1$
139: if (service != null) {
140: return service;
141: }
142: }
143: return null;
144: }
145:
146: /**
147: * @com.intel.drl.spec_ref
148: *
149: */
150: protected SecureRandom(SecureRandomSpi secureRandomSpi,
151: Provider provider) {
152: this (secureRandomSpi, provider, "unknown"); //$NON-NLS-1$
153: }
154:
155: // Constructor
156: private SecureRandom(SecureRandomSpi secureRandomSpi,
157: Provider provider, String algorithm) {
158: super (0);
159: this .provider = provider;
160: this .algorithm = algorithm;
161: this .secureRandomSpi = secureRandomSpi;
162: }
163:
164: /**
165: * @com.intel.drl.spec_ref
166: *
167: */
168: public static SecureRandom getInstance(String algorithm)
169: throws NoSuchAlgorithmException {
170: if (algorithm == null) {
171: throw new NullPointerException(Messages
172: .getString("security.01")); //$NON-NLS-1$
173: }
174: synchronized (engine) {
175: engine.getInstance(algorithm, null);
176: return new SecureRandom((SecureRandomSpi) engine.spi,
177: engine.provider, algorithm);
178: }
179: }
180:
181: /**
182: * Answers a new SecureRandom which is capable of running the algorithm
183: * described by the argument. The result will be an instance of a subclass
184: * of SecureRandomSpi which implements that algorithm.
185: *
186: * @param algorithm
187: * java.lang.String Name of the algorithm desired
188: * @param provider
189: * java.security.Provider Provider which has to implement the
190: * algorithm
191: * @return SecureRandom a concrete implementation for the algorithm desired.
192: *
193: * @exception NoSuchAlgorithmException
194: * If the algorithm cannot be found
195: */
196: public static SecureRandom getInstance(String algorithm,
197: String provider) throws NoSuchAlgorithmException,
198: NoSuchProviderException {
199: if ((provider == null) || (provider.length() == 0)) {
200: throw new IllegalArgumentException(Messages
201: .getString("security.02")); //$NON-NLS-1$
202: }
203: Provider p = Security.getProvider(provider);
204: if (p == null) {
205: throw new NoSuchProviderException(Messages.getString(
206: "security.03", provider)); //$NON-NLS-1$
207: }
208: return getInstance(algorithm, p);
209: }
210:
211: /**
212: * @com.intel.drl.spec_ref
213: *
214: */
215: public static SecureRandom getInstance(String algorithm,
216: Provider provider) throws NoSuchAlgorithmException {
217: if (provider == null) {
218: throw new IllegalArgumentException(Messages
219: .getString("security.04")); //$NON-NLS-1$
220: }
221: if (algorithm == null) {
222: throw new NullPointerException(Messages
223: .getString("security.01")); //$NON-NLS-1$
224: }
225: synchronized (engine) {
226: engine.getInstance(algorithm, provider, null);
227: return new SecureRandom((SecureRandomSpi) engine.spi,
228: provider, algorithm);
229: }
230: }
231:
232: /**
233: * Returns the Provider of the secure random represented by the receiver.
234: *
235: * @return Provider an instance of a subclass of java.security.Provider
236: */
237: public final Provider getProvider() {
238: return provider;
239: }
240:
241: /**
242: * @com.intel.drl.spec_ref
243: *
244: */
245: public String getAlgorithm() {
246: return algorithm;
247: }
248:
249: /**
250: * @com.intel.drl.spec_ref
251: *
252: */
253: public synchronized void setSeed(byte[] seed) {
254: secureRandomSpi.engineSetSeed(seed);
255: }
256:
257: /**
258: * Reseeds this random object with the eight bytes described by the
259: * representation of the long provided.
260: *
261: *
262: * @param seed
263: * long Number whose representation to use to reseed the
264: * receiver.
265: */
266: public void setSeed(long seed) {
267: if (seed == 0) { // skip call from Random
268: return;
269: }
270: byte[] byteSeed = { (byte) ((seed >> 56) & 0xFF),
271: (byte) ((seed >> 48) & 0xFF),
272: (byte) ((seed >> 40) & 0xFF),
273: (byte) ((seed >> 32) & 0xFF),
274: (byte) ((seed >> 24) & 0xFF),
275: (byte) ((seed >> 16) & 0xFF),
276: (byte) ((seed >> 8) & 0xFF), (byte) ((seed) & 0xFF) };
277: setSeed(byteSeed);
278: }
279:
280: /**
281: * @com.intel.drl.spec_ref
282: *
283: */
284: public synchronized void nextBytes(byte[] bytes) {
285: secureRandomSpi.engineNextBytes(bytes);
286: }
287:
288: /**
289: * @com.intel.drl.spec_ref
290: *
291: */
292: protected final int next(int numBits) {
293: if (numBits < 0) {
294: numBits = 0;
295: } else {
296: if (numBits > 32) {
297: numBits = 32;
298: }
299: }
300: int bytes = (numBits + 7) / 8;
301: byte[] next = new byte[bytes];
302: int ret = 0;
303:
304: nextBytes(next);
305: for (int i = 0; i < bytes; i++) {
306: ret = (next[i] & 0xFF) | (ret << 8);
307: }
308: ret = ret >>> (bytes * 8 - numBits);
309: return ret;
310: }
311:
312: /**
313: * Returns the given number of seed bytes, computed using the seed
314: * generation algorithm used by this class.
315: *
316: * @param numBytes
317: * int the given number of seed bytes
318: * @return byte[] The seed bytes generated
319: */
320: public static byte[] getSeed(int numBytes) {
321: if (internalSecureRandom == null) {
322: internalSecureRandom = new SecureRandom();
323: }
324: return internalSecureRandom.generateSeed(numBytes);
325: }
326:
327: /**
328: * Generates a certain number of seed bytes
329: *
330: *
331: * @param numBytes
332: * int Number of seed bytes to generate
333: * @return byte[] The seed bytes generated
334: */
335: public byte[] generateSeed(int numBytes) {
336: return secureRandomSpi.engineGenerateSeed(numBytes);
337: }
338:
339: }
|