source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/security/SecureRandom.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 4.6 KB
Line 
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 *****************************************************************************/
24package mindbright.security;
25
26import 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 */
34public 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}
Note: See TracBrowser for help on using the repository browser.