1 | /******************************************************************************
|
---|
2 | *
|
---|
3 | * Copyright (C) 1998 Logi Ragnarsson
|
---|
4 | *
|
---|
5 | * Adapted 1999 for use in MindTerm by Mats Andersson ([email protected])
|
---|
6 | * This class is the RandomSpinner class of the Cryptonite library found at:
|
---|
7 | * <http://www.hi.is/~logir/cryptonite/>
|
---|
8 | *
|
---|
9 | * This program is free software; you can redistribute it and/or modify
|
---|
10 | * it under the terms of the GNU General Public License as published by
|
---|
11 | * the Free Software Foundation; either version 2 of the License, or
|
---|
12 | * (at your option) any later version.
|
---|
13 | *
|
---|
14 | * This program is distributed in the hope that it will be useful,
|
---|
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
17 | * GNU General Public License for more details.
|
---|
18 | *
|
---|
19 | *****************************************************************************
|
---|
20 | * $Author: mats $
|
---|
21 | * $Date: 2000/06/29 16:29:22 $
|
---|
22 | * $Name: rel1-2-1 $
|
---|
23 | *****************************************************************************/
|
---|
24 | package mindbright.security;
|
---|
25 |
|
---|
26 | import java.util.Random;
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * This class uses the scheduler to generate random numbers. It counts the
|
---|
30 | * number of times a loop is repeated before a thread has slept for a specified
|
---|
31 | * number of milliseconds. These numbers are then fed to a hash function to mask
|
---|
32 | * any possible correlations.<p>
|
---|
33 | */
|
---|
34 | public class SecureRandom extends Random {
|
---|
35 |
|
---|
36 | MD5 md5 = new MD5();
|
---|
37 | private int t;
|
---|
38 | public Thread updater;
|
---|
39 |
|
---|
40 | public static int secureLevel = 0;
|
---|
41 |
|
---|
42 | public SecureRandom() {
|
---|
43 | t=Spinner.guessTime(1024);
|
---|
44 |
|
---|
45 | int paranoia = ((secureLevel > 0) ? 2 : 1);
|
---|
46 |
|
---|
47 | for(int i=0; i<paranoia; i++) {
|
---|
48 | // Estimate about 4 bits of entropy per call to spinner
|
---|
49 | for(int j=md5.buffer.length-1; j>=0; j--) {
|
---|
50 | // Fill the buffer with spin-counts from the Spinner class.
|
---|
51 | md5.buffer[j] = (byte)Spinner.spin(t);
|
---|
52 | if(secureLevel < 2)
|
---|
53 | md5.buffer[--j] = (byte)System.currentTimeMillis();
|
---|
54 | }
|
---|
55 | md5.transform(md5.buffer, 0);
|
---|
56 | }
|
---|
57 | unused = new byte[16];
|
---|
58 | unusedPos = 16;
|
---|
59 | unusedLock = new Object();
|
---|
60 | }
|
---|
61 |
|
---|
62 | public SecureRandom(byte[] seed) {
|
---|
63 | try {
|
---|
64 | MD5 md5 = new MD5();
|
---|
65 | md5.update(seed);
|
---|
66 | this.md5 = md5;
|
---|
67 | } catch (Exception e) {
|
---|
68 | // !!!
|
---|
69 | System.out.println("Can't operate, MD5 not available...");
|
---|
70 | }
|
---|
71 | t = Spinner.guessTime(1024);
|
---|
72 | unused = new byte[16];
|
---|
73 | unusedPos = 16;
|
---|
74 | unusedLock = new Object();
|
---|
75 | }
|
---|
76 |
|
---|
77 | /** unused[unusedPos..15] is unused pseudo-random numbers. */
|
---|
78 | byte[] unused;
|
---|
79 | int unusedPos;
|
---|
80 | Object unusedLock;
|
---|
81 |
|
---|
82 | int poolSweep=0;
|
---|
83 |
|
---|
84 | /** Get new unused bytes. */
|
---|
85 | protected synchronized void update() {
|
---|
86 | // Inject entropy into the pool
|
---|
87 | //
|
---|
88 | if(secureLevel > 1) {
|
---|
89 | md5.buffer[poolSweep++] += Spinner.spin(t) + 1;
|
---|
90 | md5.buffer[poolSweep++] += Spinner.spin(t) + 1;
|
---|
91 | } else {
|
---|
92 | md5.buffer[poolSweep++] += Spinner.bogusSpin();
|
---|
93 | md5.buffer[poolSweep] += md5.buffer[poolSweep - 1];
|
---|
94 | poolSweep++;
|
---|
95 | }
|
---|
96 |
|
---|
97 | poolSweep %= 64;
|
---|
98 |
|
---|
99 | byte[] newUnused = new byte[16];
|
---|
100 | md5.transform(md5.buffer,0);
|
---|
101 | writeBytes(md5.hash[0], newUnused, 0,4);
|
---|
102 | writeBytes(md5.hash[1], newUnused, 4,4);
|
---|
103 | writeBytes(md5.hash[2], newUnused, 8,4);
|
---|
104 | writeBytes(md5.hash[3], newUnused,12,4);
|
---|
105 |
|
---|
106 | synchronized(unusedLock) {
|
---|
107 | unused = newUnused;
|
---|
108 | unusedPos = 0;
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | /** Generates the next random number. */
|
---|
113 | protected synchronized int next(int bits) {
|
---|
114 | //System.out.println(bits);
|
---|
115 | int r=0;
|
---|
116 | synchronized(unusedLock) {
|
---|
117 | for(int b=0; b<bits; b+=8) {
|
---|
118 | if(unusedPos==16)
|
---|
119 | update();
|
---|
120 | r = (r<<8) + unused[unusedPos++];
|
---|
121 | }
|
---|
122 | }
|
---|
123 | return r;
|
---|
124 | }
|
---|
125 |
|
---|
126 | public synchronized void startUpdater() {
|
---|
127 | if(updater != null)
|
---|
128 | return;
|
---|
129 | updater = (new Thread(new Runnable() {
|
---|
130 | public void run() {
|
---|
131 | SecureRandom.this.updater.setPriority(SecureRandom.this.updater.getPriority() - 1);
|
---|
132 | while(true) {
|
---|
133 | try {
|
---|
134 | Thread.sleep(10000);
|
---|
135 | } catch (InterruptedException e) {
|
---|
136 | // !!!
|
---|
137 | }
|
---|
138 | SecureRandom.this.update();
|
---|
139 | }
|
---|
140 | }
|
---|
141 | }));
|
---|
142 | updater.start();
|
---|
143 | }
|
---|
144 |
|
---|
145 | public void nextPadBytes(byte[] bytes, int len) {
|
---|
146 | nextPadBytes(bytes, 0, len);
|
---|
147 | }
|
---|
148 |
|
---|
149 | public void nextPadBytes(byte[] bytes, int off, int len) {
|
---|
150 | byte[] ub;
|
---|
151 | int ui;
|
---|
152 | synchronized(unusedLock) {
|
---|
153 | for(int i = 0; i < len; i++) {
|
---|
154 | unusedPos %= 16;
|
---|
155 | bytes[off + i] = unused[unusedPos++];
|
---|
156 | }
|
---|
157 | }
|
---|
158 | }
|
---|
159 |
|
---|
160 | public static final void writeBytes(long a, byte[] dest, int i, int length) {
|
---|
161 | for (int j=i+length-1; j>=i; j--){
|
---|
162 | dest[j]=(byte)a;
|
---|
163 | a = a >>> 8;
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 | }
|
---|