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