| /* |
| * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.security.provider; |
| |
| import java.io.IOException; |
| import java.security.MessageDigest; |
| import java.security.SecureRandomSpi; |
| import java.security.NoSuchAlgorithmException; |
| |
| /** |
| * <p>This class provides a crytpographically strong pseudo-random number |
| * generator based on the SHA-1 hash algorithm. |
| * |
| * <p>Note that if a seed is not provided, we attempt to provide sufficient |
| * seed bytes to completely randomize the internal state of the generator |
| * (20 bytes). However, our seed generation algorithm has not been thoroughly |
| * studied or widely deployed. |
| * |
| * <p>Also note that when a random object is deserialized, |
| * <a href="#engineNextBytes(byte[])">engineNextBytes</a> invoked on the |
| * restored random object will yield the exact same (random) bytes as the |
| * original object. If this behaviour is not desired, the restored random |
| * object should be seeded, using |
| * <a href="#engineSetSeed(byte[])">engineSetSeed</a>. |
| * |
| * @author Benjamin Renaud |
| * @author Josh Bloch |
| * @author Gadi Guy |
| */ |
| |
| public final class SecureRandom extends SecureRandomSpi |
| implements java.io.Serializable { |
| |
| private static final long serialVersionUID = 3581829991155417889L; |
| |
| private static final int DIGEST_SIZE = 20; |
| private transient MessageDigest digest; |
| private byte[] state; |
| private byte[] remainder; |
| private int remCount; |
| |
| /** |
| * This empty constructor automatically seeds the generator. We attempt |
| * to provide sufficient seed bytes to completely randomize the internal |
| * state of the generator (20 bytes). Note, however, that our seed |
| * generation algorithm has not been thoroughly studied or widely deployed. |
| * |
| * <p>The first time this constructor is called in a given Virtual Machine, |
| * it may take several seconds of CPU time to seed the generator, depending |
| * on the underlying hardware. Successive calls run quickly because they |
| * rely on the same (internal) pseudo-random number generator for their |
| * seed bits. |
| */ |
| public SecureRandom() { |
| init(null); |
| } |
| |
| /** |
| * This constructor is used to instatiate the private seeder object |
| * with a given seed from the SeedGenerator. |
| * |
| * @param seed the seed. |
| */ |
| private SecureRandom(byte seed[]) { |
| init(seed); |
| } |
| |
| /** |
| * This call, used by the constructors, instantiates the SHA digest |
| * and sets the seed, if given. |
| */ |
| private void init(byte[] seed) { |
| try { |
| digest = MessageDigest.getInstance ("SHA"); |
| } catch (NoSuchAlgorithmException e) { |
| throw new InternalError("internal error: SHA-1 not available."); |
| } |
| |
| if (seed != null) { |
| engineSetSeed(seed); |
| } |
| } |
| |
| /** |
| * Returns the given number of seed bytes, computed using the seed |
| * generation algorithm that this class uses to seed itself. This |
| * call may be used to seed other random number generators. While |
| * we attempt to return a "truly random" sequence of bytes, we do not |
| * know exactly how random the bytes returned by this call are. (See |
| * the empty constructor <a href = "#SecureRandom">SecureRandom</a> |
| * for a brief description of the underlying algorithm.) |
| * The prudent user will err on the side of caution and get extra |
| * seed bytes, although it should be noted that seed generation is |
| * somewhat costly. |
| * |
| * @param numBytes the number of seed bytes to generate. |
| * |
| * @return the seed bytes. |
| */ |
| public byte[] engineGenerateSeed(int numBytes) { |
| byte[] b = new byte[numBytes]; |
| SeedGenerator.generateSeed(b); |
| return b; |
| } |
| |
| /** |
| * Reseeds this random object. The given seed supplements, rather than |
| * replaces, the existing seed. Thus, repeated calls are guaranteed |
| * never to reduce randomness. |
| * |
| * @param seed the seed. |
| */ |
| synchronized public void engineSetSeed(byte[] seed) { |
| if (state != null) { |
| digest.update(state); |
| for (int i = 0; i < state.length; i++) |
| state[i] = 0; |
| } |
| state = digest.digest(seed); |
| } |
| |
| private static void updateState(byte[] state, byte[] output) { |
| int last = 1; |
| int v = 0; |
| byte t = 0; |
| boolean zf = false; |
| |
| // state(n + 1) = (state(n) + output(n) + 1) % 2^160; |
| for (int i = 0; i < state.length; i++) { |
| // Add two bytes |
| v = (int)state[i] + (int)output[i] + last; |
| // Result is lower 8 bits |
| t = (byte)v; |
| // Store result. Check for state collision. |
| zf = zf | (state[i] != t); |
| state[i] = t; |
| // High 8 bits are carry. Store for next iteration. |
| last = v >> 8; |
| } |
| |
| // Make sure at least one bit changes! |
| if (!zf) |
| state[0]++; |
| } |
| |
| /** |
| * This static object will be seeded by SeedGenerator, and used |
| * to seed future instances of SHA1PRNG SecureRandoms. |
| * |
| * Bloch, Effective Java Second Edition: Item 71 |
| */ |
| private static class SeederHolder { |
| |
| private static final SecureRandom seeder; |
| |
| static { |
| /* |
| * Call to SeedGenerator.generateSeed() to add additional |
| * seed material (likely from the Native implementation). |
| */ |
| seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); |
| byte [] b = new byte[DIGEST_SIZE]; |
| SeedGenerator.generateSeed(b); |
| seeder.engineSetSeed(b); |
| } |
| } |
| |
| /** |
| * Generates a user-specified number of random bytes. |
| * |
| * @param bytes the array to be filled in with random bytes. |
| */ |
| public synchronized void engineNextBytes(byte[] result) { |
| int index = 0; |
| int todo; |
| byte[] output = remainder; |
| |
| if (state == null) { |
| byte[] seed = new byte[DIGEST_SIZE]; |
| SeederHolder.seeder.engineNextBytes(seed); |
| state = digest.digest(seed); |
| } |
| |
| // Use remainder from last time |
| int r = remCount; |
| if (r > 0) { |
| // How many bytes? |
| todo = (result.length - index) < (DIGEST_SIZE - r) ? |
| (result.length - index) : (DIGEST_SIZE - r); |
| // Copy the bytes, zero the buffer |
| for (int i = 0; i < todo; i++) { |
| result[i] = output[r]; |
| output[r++] = 0; |
| } |
| remCount += todo; |
| index += todo; |
| } |
| |
| // If we need more bytes, make them. |
| while (index < result.length) { |
| // Step the state |
| digest.update(state); |
| output = digest.digest(); |
| updateState(state, output); |
| |
| // How many bytes? |
| todo = (result.length - index) > DIGEST_SIZE ? |
| DIGEST_SIZE : result.length - index; |
| // Copy the bytes, zero the buffer |
| for (int i = 0; i < todo; i++) { |
| result[index++] = output[i]; |
| output[i] = 0; |
| } |
| remCount += todo; |
| } |
| |
| // Store remainder for next time |
| remainder = output; |
| remCount %= DIGEST_SIZE; |
| } |
| |
| /* |
| * readObject is called to restore the state of the random object from |
| * a stream. We have to create a new instance of MessageDigest, because |
| * it is not included in the stream (it is marked "transient"). |
| * |
| * Note that the engineNextBytes() method invoked on the restored random |
| * object will yield the exact same (random) bytes as the original. |
| * If you do not want this behaviour, you should re-seed the restored |
| * random object, using engineSetSeed(). |
| */ |
| private void readObject(java.io.ObjectInputStream s) |
| throws IOException, ClassNotFoundException { |
| |
| s.defaultReadObject (); |
| |
| try { |
| digest = MessageDigest.getInstance ("SHA"); |
| } catch (NoSuchAlgorithmException e) { |
| throw new InternalError("internal error: SHA-1 not available."); |
| } |
| } |
| } |