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 remCount = 0; 160 } 161 162 private static void updateState(byte[] state, byte[] output) { 163 int last = 1; 164 int v; 165 byte t; 166 boolean zf = false; 167 168 // state(n + 1) = (state(n) + output(n) + 1) % 2^160; 169 for (int i = 0; i < state.length; i++) { 170 // Add two bytes 171 v = (int)state[i] + (int)output[i] + last; 172 // Result is lower 8 bits 173 t = (byte)v; 174 // Store result. Check for state collision. 175 zf = zf | (state[i] != t); 176 state[i] = t; 177 // High 8 bits are carry. Store for next iteration. 178 last = v >> 8; 179 } 180 181 // Make sure at least one bit changes! 182 if (!zf) { 183 state[0]++; 184 } 185 } 186 187 /** 188 * This static object will be seeded by SeedGenerator, and used 189 * to seed future instances of SHA1PRNG SecureRandoms. 190 * 191 * Bloch, Effective Java Second Edition: Item 71 192 */ 193 private static class SeederHolder { 194 195 private static final SecureRandom seeder; 196 197 static { 198 /* 199 * Call to SeedGenerator.generateSeed() to add additional 200 * seed material (likely from the Native implementation). 201 */ 202 seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); 203 byte [] b = new byte[DIGEST_SIZE]; 204 SeedGenerator.generateSeed(b); 205 seeder.engineSetSeed(b); 206 } 207 } 208 209 /** 210 * Generates a user-specified number of random bytes. 211 * 212 * @param result the array to be filled in with random bytes. 213 */ 214 @Override 215 public synchronized void engineNextBytes(byte[] result) { 216 int index = 0; 217 int todo; 218 byte[] output = remainder; 219 220 if (state == null) { 221 byte[] seed = new byte[DIGEST_SIZE]; 222 SeederHolder.seeder.engineNextBytes(seed); 223 state = digest.digest(seed); 224 } 225 226 // Use remainder from last time 227 int r = remCount; 228 if (r > 0) { 229 // How many bytes? 230 todo = (result.length - index) < (DIGEST_SIZE - r) ? 231 (result.length - index) : (DIGEST_SIZE - r); 232 // Copy the bytes, zero the buffer 233 for (int i = 0; i < todo; i++) { 234 result[i] = output[r]; 235 output[r++] = 0; 236 } 237 remCount += todo; 238 index += todo; 239 } 240 241 // If we need more bytes, make them. 242 while (index < result.length) { 243 // Step the state 244 digest.update(state); 245 output = digest.digest(); 246 updateState(state, output); 247 248 // How many bytes? 249 todo = (result.length - index) > DIGEST_SIZE ? 250 DIGEST_SIZE : result.length - index; 251 // Copy the bytes, zero the buffer 252 for (int i = 0; i < todo; i++) { 253 result[index++] = output[i]; 254 output[i] = 0; 255 } 256 remCount += todo; 257 } 258 259 // Store remainder for next time 260 remainder = output; 261 remCount %= DIGEST_SIZE; 262 } 263 264 /* 265 * readObject is called to restore the state of the random object from 266 * a stream. We have to create a new instance of MessageDigest, because 267 * it is not included in the stream (it is marked "transient"). 268 * 269 * Note that the engineNextBytes() method invoked on the restored random 270 * object will yield the exact same (random) bytes as the original. 271 * If you do not want this behaviour, you should re-seed the restored 272 * random object, using engineSetSeed(). 273 */ 274 private void readObject(java.io.ObjectInputStream s) 275 throws IOException, ClassNotFoundException { 276 277 s.defaultReadObject (); 278 279 try { 280 /* 281 * Use the local SUN implementation to avoid native 282 * performance overhead. 283 */ 284 digest = MessageDigest.getInstance("SHA", "SUN"); 285 } catch (NoSuchProviderException | NoSuchAlgorithmException e) { 286 // Fallback to any available. 287 try { 288 digest = MessageDigest.getInstance("SHA"); 289 } catch (NoSuchAlgorithmException exc) { 290 throw new InternalError( 291 "internal error: SHA-1 not available.", exc); 292 } 293 } 294 } 295} 296