1 /* 2 * Copyright (c) 1998, 2019, 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 26 package sun.security.provider; 27 28 import java.io.IOException; 29 import java.security.MessageDigest; 30 import java.security.SecureRandomSpi; 31 import java.security.NoSuchAlgorithmException; 32 import 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 55 public final class SecureRandom extends SecureRandomSpi 56 implements java.io.Serializable { 57 58 @java.io.Serial 59 private static final long serialVersionUID = 3581829991155417889L; 60 61 private static final int DIGEST_SIZE = 20; 62 private transient MessageDigest digest; 63 private byte[] state; 64 private byte[] remainder; 65 private int remCount; 66 67 /** 68 * This empty constructor automatically seeds the generator. We attempt 69 * to provide sufficient seed bytes to completely randomize the internal 70 * state of the generator (20 bytes). Note, however, that our seed 71 * generation algorithm has not been thoroughly studied or widely deployed. 72 * 73 * <p>The first time this constructor is called in a given Virtual Machine, 74 * it may take several seconds of CPU time to seed the generator, depending 75 * on the underlying hardware. Successive calls run quickly because they 76 * rely on the same (internal) pseudo-random number generator for their 77 * seed bits. 78 */ SecureRandom()79 public SecureRandom() { 80 init(null); 81 } 82 83 /** 84 * This constructor is used to instantiate the private seeder object 85 * with a given seed from the SeedGenerator. 86 * 87 * @param seed the seed. 88 */ SecureRandom(byte[] seed)89 private SecureRandom(byte[] seed) { 90 init(seed); 91 } 92 93 /** 94 * This call, used by the constructors, instantiates the SHA digest 95 * and sets the seed, if given. 96 */ init(byte[] seed)97 private void init(byte[] seed) { 98 try { 99 /* 100 * Use the local SUN implementation to avoid native 101 * performance overhead. 102 */ 103 digest = MessageDigest.getInstance("SHA", "SUN"); 104 } catch (NoSuchProviderException | NoSuchAlgorithmException e) { 105 // Fallback to any available. 106 try { 107 digest = MessageDigest.getInstance("SHA"); 108 } catch (NoSuchAlgorithmException exc) { 109 throw new InternalError( 110 "internal error: SHA-1 not available.", exc); 111 } 112 } 113 114 if (seed != null) { 115 engineSetSeed(seed); 116 } 117 } 118 119 /** 120 * Returns the given number of seed bytes, computed using the seed 121 * generation algorithm that this class uses to seed itself. This 122 * call may be used to seed other random number generators. While 123 * we attempt to return a "truly random" sequence of bytes, we do not 124 * know exactly how random the bytes returned by this call are. (See 125 * the empty constructor <a href = "#SecureRandom">SecureRandom</a> 126 * for a brief description of the underlying algorithm.) 127 * The prudent user will err on the side of caution and get extra 128 * seed bytes, although it should be noted that seed generation is 129 * somewhat costly. 130 * 131 * @param numBytes the number of seed bytes to generate. 132 * 133 * @return the seed bytes. 134 */ 135 @Override engineGenerateSeed(int numBytes)136 public byte[] engineGenerateSeed(int numBytes) { 137 // Neither of the SeedGenerator implementations require 138 // locking, so no sync needed here. 139 byte[] b = new byte[numBytes]; 140 SeedGenerator.generateSeed(b); 141 return b; 142 } 143 144 /** 145 * Reseeds this random object. The given seed supplements, rather than 146 * replaces, the existing seed. Thus, repeated calls are guaranteed 147 * never to reduce randomness. 148 * 149 * @param seed the seed. 150 */ 151 @Override engineSetSeed(byte[] seed)152 public synchronized void engineSetSeed(byte[] seed) { 153 if (state != null) { 154 digest.update(state); 155 for (int i = 0; i < state.length; i++) { 156 state[i] = 0; 157 } 158 } 159 state = digest.digest(seed); 160 remCount = 0; 161 } 162 updateState(byte[] state, byte[] output)163 private static void updateState(byte[] state, byte[] output) { 164 int last = 1; 165 int v; 166 byte t; 167 boolean zf = false; 168 169 // state(n + 1) = (state(n) + output(n) + 1) % 2^160; 170 for (int i = 0; i < state.length; i++) { 171 // Add two bytes 172 v = (int)state[i] + (int)output[i] + last; 173 // Result is lower 8 bits 174 t = (byte)v; 175 // Store result. Check for state collision. 176 zf = zf | (state[i] != t); 177 state[i] = t; 178 // High 8 bits are carry. Store for next iteration. 179 last = v >> 8; 180 } 181 182 // Make sure at least one bit changes! 183 if (!zf) { 184 state[0]++; 185 } 186 } 187 188 /** 189 * This static object will be seeded by SeedGenerator, and used 190 * to seed future instances of SHA1PRNG SecureRandoms. 191 * 192 * Bloch, Effective Java Second Edition: Item 71 193 */ 194 private static class SeederHolder { 195 196 private static final SecureRandom seeder; 197 198 static { 199 /* 200 * Call to SeedGenerator.generateSeed() to add additional 201 * seed material (likely from the Native implementation). 202 */ 203 seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); 204 byte [] b = new byte[DIGEST_SIZE]; 205 SeedGenerator.generateSeed(b); 206 seeder.engineSetSeed(b); 207 } 208 } 209 210 /** 211 * Generates a user-specified number of random bytes. 212 * 213 * @param result the array to be filled in with random bytes. 214 */ 215 @Override engineNextBytes(byte[] result)216 public synchronized void engineNextBytes(byte[] result) { 217 int index = 0; 218 int todo; 219 byte[] output = remainder; 220 221 if (state == null) { 222 byte[] seed = new byte[DIGEST_SIZE]; 223 SeederHolder.seeder.engineNextBytes(seed); 224 state = digest.digest(seed); 225 } 226 227 // Use remainder from last time 228 int r = remCount; 229 if (r > 0) { 230 // How many bytes? 231 todo = (result.length - index) < (DIGEST_SIZE - r) ? 232 (result.length - index) : (DIGEST_SIZE - r); 233 // Copy the bytes, zero the buffer 234 for (int i = 0; i < todo; i++) { 235 result[i] = output[r]; 236 output[r++] = 0; 237 } 238 remCount += todo; 239 index += todo; 240 } 241 242 // If we need more bytes, make them. 243 while (index < result.length) { 244 // Step the state 245 digest.update(state); 246 output = digest.digest(); 247 updateState(state, output); 248 249 // How many bytes? 250 todo = (result.length - index) > DIGEST_SIZE ? 251 DIGEST_SIZE : result.length - index; 252 // Copy the bytes, zero the buffer 253 for (int i = 0; i < todo; i++) { 254 result[index++] = output[i]; 255 output[i] = 0; 256 } 257 remCount += todo; 258 } 259 260 // Store remainder for next time 261 remainder = output; 262 remCount %= DIGEST_SIZE; 263 } 264 265 /* 266 * readObject is called to restore the state of the random object from 267 * a stream. We have to create a new instance of MessageDigest, because 268 * it is not included in the stream (it is marked "transient"). 269 * 270 * Note that the engineNextBytes() method invoked on the restored random 271 * object will yield the exact same (random) bytes as the original. 272 * If you do not want this behaviour, you should re-seed the restored 273 * random object, using engineSetSeed(). 274 */ 275 @java.io.Serial 276 private void readObject(java.io.ObjectInputStream s) 277 throws IOException, ClassNotFoundException { 278 279 s.defaultReadObject (); 280 281 try { 282 /* 283 * Use the local SUN implementation to avoid native 284 * performance overhead. 285 */ 286 digest = MessageDigest.getInstance("SHA", "SUN"); 287 } catch (NoSuchProviderException | NoSuchAlgorithmException e) { 288 // Fallback to any available. 289 try { 290 digest = MessageDigest.getInstance("SHA"); 291 } catch (NoSuchAlgorithmException exc) { 292 throw new InternalError( 293 "internal error: SHA-1 not available.", exc); 294 } 295 } 296 } 297 } 298