History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/provider/SecureRandom.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/SecureRandom.java+255−0
@@ -0,0 +1,255 @@
1+/*
2+ * Copyright (c) 1998, 2003, 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+
33+/**
34+ * <p>This class provides a crytpographically strong pseudo-random number
35+ * generator based on the SHA-1 hash algorithm.
36+ *
37+ * <p>Note that if a seed is not provided, we attempt to provide sufficient
38+ * seed bytes to completely randomize the internal state of the generator
39+ * (20 bytes). However, our seed generation algorithm has not been thoroughly
40+ * studied or widely deployed.
41+ *
42+ * <p>Also note that when a random object is deserialized,
43+ * <a href="#engineNextBytes(byte[])">engineNextBytes</a> invoked on the
44+ * restored random object will yield the exact same (random) bytes as the
45+ * original object. If this behaviour is not desired, the restored random
46+ * object should be seeded, using
47+ * <a href="#engineSetSeed(byte[])">engineSetSeed</a>.
48+ *
49+ * @author Benjamin Renaud
50+ * @author Josh Bloch
51+ * @author Gadi Guy
52+ */
53+
54+public final class SecureRandom extends SecureRandomSpi
55+implements java.io.Serializable {
56+
57+ private static final long serialVersionUID = 3581829991155417889L;
58+
59+ /**
60+ * This static object will be seeded by SeedGenerator, and used
61+ * to seed future instances of SecureRandom
62+ */
63+ private static SecureRandom seeder;
64+
65+ private static final int DIGEST_SIZE = 20;
66+ private transient MessageDigest digest;
67+ private byte[] state;
68+ private byte[] remainder;
69+ private int remCount;
70+
71+ /**
72+ * This empty constructor automatically seeds the generator. We attempt
73+ * to provide sufficient seed bytes to completely randomize the internal
74+ * state of the generator (20 bytes). Note, however, that our seed
75+ * generation algorithm has not been thoroughly studied or widely deployed.
76+ *
77+ * <p>The first time this constructor is called in a given Virtual Machine,
78+ * it may take several seconds of CPU time to seed the generator, depending
79+ * on the underlying hardware. Successive calls run quickly because they
80+ * rely on the same (internal) pseudo-random number generator for their
81+ * seed bits.
82+ */
83+ public SecureRandom() {
84+ init(null);
85+ }
86+
87+ /**
88+ * This constructor is used to instatiate the private seeder object
89+ * with a given seed from the SeedGenerator.
90+ *
91+ * @param seed the seed.
92+ */
93+ private SecureRandom(byte seed[]) {
94+ init(seed);
95+ }
96+
97+ /**
98+ * This call, used by the constructors, instantiates the SHA digest
99+ * and sets the seed, if given.
100+ */
101+ private void init(byte[] seed) {
102+ try {
103+ digest = MessageDigest.getInstance ("SHA");
104+ } catch (NoSuchAlgorithmException e) {
105+ throw new InternalError("internal error: SHA-1 not available.");
106+ }
107+
108+ if (seed != null) {
109+ engineSetSeed(seed);
110+ }
111+ }
112+
113+ /**
114+ * Returns the given number of seed bytes, computed using the seed
115+ * generation algorithm that this class uses to seed itself. This
116+ * call may be used to seed other random number generators. While
117+ * we attempt to return a "truly random" sequence of bytes, we do not
118+ * know exactly how random the bytes returned by this call are. (See
119+ * the empty constructor <a href = "#SecureRandom">SecureRandom</a>
120+ * for a brief description of the underlying algorithm.)
121+ * The prudent user will err on the side of caution and get extra
122+ * seed bytes, although it should be noted that seed generation is
123+ * somewhat costly.
124+ *
125+ * @param numBytes the number of seed bytes to generate.
126+ *
127+ * @return the seed bytes.
128+ */
129+ public byte[] engineGenerateSeed(int numBytes) {
130+ byte[] b = new byte[numBytes];
131+ SeedGenerator.generateSeed(b);
132+ return b;
133+ }
134+
135+ /**
136+ * Reseeds this random object. The given seed supplements, rather than
137+ * replaces, the existing seed. Thus, repeated calls are guaranteed
138+ * never to reduce randomness.
139+ *
140+ * @param seed the seed.
141+ */
142+ synchronized public void engineSetSeed(byte[] seed) {
143+ if (state != null) {
144+ digest.update(state);
145+ for (int i = 0; i < state.length; i++)
146+ state[i] = 0;
147+ }
148+ state = digest.digest(seed);
149+ }
150+
151+ private static void updateState(byte[] state, byte[] output) {
152+ int last = 1;
153+ int v = 0;
154+ byte t = 0;
155+ boolean zf = false;
156+
157+ // state(n + 1) = (state(n) + output(n) + 1) % 2^160;
158+ for (int i = 0; i < state.length; i++) {
159+ // Add two bytes
160+ v = (int)state[i] + (int)output[i] + last;
161+ // Result is lower 8 bits
162+ t = (byte)v;
163+ // Store result. Check for state collision.
164+ zf = zf | (state[i] != t);
165+ state[i] = t;
166+ // High 8 bits are carry. Store for next iteration.
167+ last = v >> 8;
168+ }
169+
170+ // Make sure at least one bit changes!
171+ if (!zf)
172+ state[0]++;
173+ }
174+
175+ /**
176+ * Generates a user-specified number of random bytes.
177+ *
178+ * @param bytes the array to be filled in with random bytes.
179+ */
180+ public synchronized void engineNextBytes(byte[] result) {
181+ int index = 0;
182+ int todo;
183+ byte[] output = remainder;
184+
185+ if (state == null) {
186+ if (seeder == null) {
187+ seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
188+ seeder.engineSetSeed(engineGenerateSeed(DIGEST_SIZE));
189+ }
190+
191+ byte[] seed = new byte[DIGEST_SIZE];
192+ seeder.engineNextBytes(seed);
193+ state = digest.digest(seed);
194+ }
195+
196+ // Use remainder from last time
197+ int r = remCount;
198+ if (r > 0) {
199+ // How many bytes?
200+ todo = (result.length - index) < (DIGEST_SIZE - r) ?
201+ (result.length - index) : (DIGEST_SIZE - r);
202+ // Copy the bytes, zero the buffer
203+ for (int i = 0; i < todo; i++) {
204+ result[i] = output[r];
205+ output[r++] = 0;
206+ }
207+ remCount += todo;
208+ index += todo;
209+ }
210+
211+ // If we need more bytes, make them.
212+ while (index < result.length) {
213+ // Step the state
214+ digest.update(state);
215+ output = digest.digest();
216+ updateState(state, output);
217+
218+ // How many bytes?
219+ todo = (result.length - index) > DIGEST_SIZE ?
220+ DIGEST_SIZE : result.length - index;
221+ // Copy the bytes, zero the buffer
222+ for (int i = 0; i < todo; i++) {
223+ result[index++] = output[i];
224+ output[i] = 0;
225+ }
226+ remCount += todo;
227+ }
228+
229+ // Store remainder for next time
230+ remainder = output;
231+ remCount %= DIGEST_SIZE;
232+ }
233+
234+ /*
235+ * readObject is called to restore the state of the random object from
236+ * a stream. We have to create a new instance of MessageDigest, because
237+ * it is not included in the stream (it is marked "transient").
238+ *
239+ * Note that the engineNextBytes() method invoked on the restored random
240+ * object will yield the exact same (random) bytes as the original.
241+ * If you do not want this behaviour, you should re-seed the restored
242+ * random object, using engineSetSeed().
243+ */
244+ private void readObject(java.io.ObjectInputStream s)
245+ throws IOException, ClassNotFoundException {
246+
247+ s.defaultReadObject ();
248+
249+ try {
250+ digest = MessageDigest.getInstance ("SHA");
251+ } catch (NoSuchAlgorithmException e) {
252+ throw new InternalError("internal error: SHA-1 not available.");
253+ }
254+ }
255+}