SecureRandom.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.security.provider; 27 28import java.io.IOException; 29import java.security.MessageDigest; 30import java.security.SecureRandomSpi; 31import java.security.NoSuchAlgorithmException; 32import java.security.NoSuchProviderException; 33 34/** 35 * <p>This class provides a crytpographically strong pseudo-random number 36 * generator based on the SHA-1 hash algorithm. 37 * 38 * <p>Note that if a seed is not provided, we attempt to provide sufficient 39 * seed bytes to completely randomize the internal state of the generator 40 * (20 bytes). However, our seed generation algorithm has not been thoroughly 41 * studied or widely deployed. 42 * 43 * <p>Also note that when a random object is deserialized, 44 * <a href="#engineNextBytes(byte[])">engineNextBytes</a> invoked on the 45 * restored random object will yield the exact same (random) bytes as the 46 * original object. If this behaviour is not desired, the restored random 47 * object should be seeded, using 48 * <a href="#engineSetSeed(byte[])">engineSetSeed</a>. 49 * 50 * @author Benjamin Renaud 51 * @author Josh Bloch 52 * @author Gadi Guy 53 */ 54 55public final class SecureRandom extends SecureRandomSpi 56implements java.io.Serializable { 57 58 private static final long serialVersionUID = 3581829991155417889L; 59 60 private static final int DIGEST_SIZE = 20; 61 private transient MessageDigest digest; 62 private byte[] state; 63 private byte[] remainder; 64 private int remCount; 65 66 /** 67 * This empty constructor automatically seeds the generator. We attempt 68 * to provide sufficient seed bytes to completely randomize the internal 69 * state of the generator (20 bytes). Note, however, that our seed 70 * generation algorithm has not been thoroughly studied or widely deployed. 71 * 72 * <p>The first time this constructor is called in a given Virtual Machine, 73 * it may take several seconds of CPU time to seed the generator, depending 74 * on the underlying hardware. Successive calls run quickly because they 75 * rely on the same (internal) pseudo-random number generator for their 76 * seed bits. 77 */ 78 public SecureRandom() { 79 init(null); 80 } 81 82 /** 83 * This constructor is used to instantiate the private seeder object 84 * with a given seed from the SeedGenerator. 85 * 86 * @param seed the seed. 87 */ 88 private SecureRandom(byte[] seed) { 89 init(seed); 90 } 91 92 /** 93 * This call, used by the constructors, instantiates the SHA digest 94 * and sets the seed, if given. 95 */ 96 private void init(byte[] seed) { 97 try { 98 /* 99 * Use the local SUN implementation to avoid native 100 * performance overhead. 101 */ 102 digest = MessageDigest.getInstance("SHA", "SUN"); 103 } catch (NoSuchProviderException | NoSuchAlgorithmException e) { 104 // Fallback to any available. 105 try { 106 digest = MessageDigest.getInstance("SHA"); 107 } catch (NoSuchAlgorithmException exc) { 108 throw new InternalError( 109 "internal error: SHA-1 not available.", exc); 110 } 111 } 112 113 if (seed != null) { 114 engineSetSeed(seed); 115 } 116 } 117 118 /** 119 * Returns the given number of seed bytes, computed using the seed 120 * generation algorithm that this class uses to seed itself. This 121 * call may be used to seed other random number generators. While 122 * we attempt to return a "truly random" sequence of bytes, we do not 123 * know exactly how random the bytes returned by this call are. (See 124 * the empty constructor <a href = "#SecureRandom">SecureRandom</a> 125 * for a brief description of the underlying algorithm.) 126 * The prudent user will err on the side of caution and get extra 127 * seed bytes, although it should be noted that seed generation is 128 * somewhat costly. 129 * 130 * @param numBytes the number of seed bytes to generate. 131 * 132 * @return the seed bytes. 133 */ 134 @Override 135 public byte[] engineGenerateSeed(int numBytes) { 136 // Neither of the SeedGenerator implementations require 137 // locking, so no sync needed here. 138 byte[] b = new byte[numBytes]; 139 SeedGenerator.generateSeed(b); 140 return b; 141 } 142 143 /** 144 * Reseeds this random object. The given seed supplements, rather than 145 * replaces, the existing seed. Thus, repeated calls are guaranteed 146 * never to reduce randomness. 147 * 148 * @param seed the seed. 149 */ 150 @Override 151 public synchronized void engineSetSeed(byte[] seed) { 152 if (state != null) { 153 digest.update(state); 154 for (int i = 0; i < state.length; i++) { 155 state[i] = 0; 156 } 157 } 158 state = digest.digest(seed); 159 } 160 161 private static void updateState(byte[] state, byte[] output) { 162 int last = 1; 163 int v; 164 byte t; 165 boolean zf = false; 166 167 // state(n + 1) = (state(n) + output(n) + 1) % 2^160; 168 for (int i = 0; i < state.length; i++) { 169 // Add two bytes 170 v = (int)state[i] + (int)output[i] + last; 171 // Result is lower 8 bits 172 t = (byte)v; 173 // Store result. Check for state collision. 174 zf = zf | (state[i] != t); 175 state[i] = t; 176 // High 8 bits are carry. Store for next iteration. 177 last = v >> 8; 178 } 179 180 // Make sure at least one bit changes! 181 if (!zf) { 182 state[0]++; 183 } 184 } 185 186 /** 187 * This static object will be seeded by SeedGenerator, and used 188 * to seed future instances of SHA1PRNG SecureRandoms. 189 * 190 * Bloch, Effective Java Second Edition: Item 71 191 */ 192 private static class SeederHolder { 193 194 private static final SecureRandom seeder; 195 196 static { 197 /* 198 * Call to SeedGenerator.generateSeed() to add additional 199 * seed material (likely from the Native implementation). 200 */ 201 seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); 202 byte [] b = new byte[DIGEST_SIZE]; 203 SeedGenerator.generateSeed(b); 204 seeder.engineSetSeed(b); 205 } 206 } 207 208 /** 209 * Generates a user-specified number of random bytes. 210 * 211 * @param result the array to be filled in with random bytes. 212 */ 213 @Override 214 public synchronized void engineNextBytes(byte[] result) { 215 int index = 0; 216 int todo; 217 byte[] output = remainder; 218 219 if (state == null) { 220 byte[] seed = new byte[DIGEST_SIZE]; 221 SeederHolder.seeder.engineNextBytes(seed); 222 state = digest.digest(seed); 223 } 224 225 // Use remainder from last time 226 int r = remCount; 227 if (r > 0) { 228 // How many bytes? 229 todo = (result.length - index) < (DIGEST_SIZE - r) ? 230 (result.length - index) : (DIGEST_SIZE - r); 231 // Copy the bytes, zero the buffer 232 for (int i = 0; i < todo; i++) { 233 result[i] = output[r]; 234 output[r++] = 0; 235 } 236 remCount += todo; 237 index += todo; 238 } 239 240 // If we need more bytes, make them. 241 while (index < result.length) { 242 // Step the state 243 digest.update(state); 244 output = digest.digest(); 245 updateState(state, output); 246 247 // How many bytes? 248 todo = (result.length - index) > DIGEST_SIZE ? 249 DIGEST_SIZE : result.length - index; 250 // Copy the bytes, zero the buffer 251 for (int i = 0; i < todo; i++) { 252 result[index++] = output[i]; 253 output[i] = 0; 254 } 255 remCount += todo; 256 } 257 258 // Store remainder for next time 259 remainder = output; 260 remCount %= DIGEST_SIZE; 261 } 262 263 /* 264 * readObject is called to restore the state of the random object from 265 * a stream. We have to create a new instance of MessageDigest, because 266 * it is not included in the stream (it is marked "transient"). 267 * 268 * Note that the engineNextBytes() method invoked on the restored random 269 * object will yield the exact same (random) bytes as the original. 270 * If you do not want this behaviour, you should re-seed the restored 271 * random object, using engineSetSeed(). 272 */ 273 private void readObject(java.io.ObjectInputStream s) 274 throws IOException, ClassNotFoundException { 275 276 s.defaultReadObject (); 277 278 try { 279 /* 280 * Use the local SUN implementation to avoid native 281 * performance overhead. 282 */ 283 digest = MessageDigest.getInstance("SHA", "SUN"); 284 } catch (NoSuchProviderException | NoSuchAlgorithmException e) { 285 // Fallback to any available. 286 try { 287 digest = MessageDigest.getInstance("SHA"); 288 } catch (NoSuchAlgorithmException exc) { 289 throw new InternalError( 290 "internal error: SHA-1 not available.", exc); 291 } 292 } 293 } 294} 295