1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.juddi.uuidgen;
17
18 import java.math.BigInteger;
19 import java.security.SecureRandom;
20 import java.util.Random;
21
22 /***
23 * Used to create new universally unique identifiers or UUID's (sometimes called
24 * GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
25 *
26 * @author Maarten Coene
27 * @author Steve Viens (sviens@apache.org)
28 */
29 public class SecureUUIDGen implements UUIDGen
30 {
31 private static final BigInteger COUNT_START = new BigInteger("-12219292800000");
32 private static final int CLOCK_SEQUENCE = (new Random()).nextInt(16384);
33
34 /***
35 *
36 */
37 public String uuidgen()
38 {
39 return nextUUID();
40 }
41
42 /***
43 *
44 */
45 public String[] uuidgen(int nmbr)
46 {
47 String[] uuids = new String[nmbr];
48
49 for (int i=0; i<uuids.length; i++)
50 uuids[i] = nextUUID();
51
52 return uuids;
53 }
54
55 /***
56 * Creates a new UUID. The algorithm used is described by The Open Group.
57 * See <a href="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
58 * Universal Unique Identifier</a> for more details.
59 * <p>
60 * Due to a lack of functionality in Java, a part of the UUID is a secure
61 * random. This results in a long processing time when this method is called
62 * for the first time.
63 */
64 protected String nextUUID()
65 {
66
67 BigInteger count;
68
69
70 BigInteger current = BigInteger.valueOf(System.currentTimeMillis());
71
72
73 BigInteger countMillis = current.subtract(COUNT_START);
74
75
76 count = countMillis.multiply(BigInteger.valueOf(10000));
77
78 String bitString = count.toString(2);
79 if (bitString.length() < 60) {
80 int nbExtraZeros = 60 - bitString.length();
81 String extraZeros = new String();
82 for (int i = 0; i < nbExtraZeros; i++)
83 extraZeros = extraZeros.concat("0");
84
85 bitString = extraZeros.concat(bitString);
86 }
87
88 byte[] bits = bitString.getBytes();
89
90
91 byte[] time_low = new byte[32];
92 for (int i = 0; i < 32; i++)
93 time_low[i] = bits[bits.length - i - 1];
94
95
96 byte[] time_mid = new byte[16];
97 for (int i = 0; i < 16; i++)
98 time_mid[i] = bits[bits.length - 32 - i - 1];
99
100
101 byte[] time_hi_and_version = new byte[16];
102 for (int i = 0; i < 12; i++)
103 time_hi_and_version[i] = bits[bits.length - 48 - i - 1];
104
105 time_hi_and_version[12] = ((new String("1")).getBytes())[0];
106 time_hi_and_version[13] = ((new String("0")).getBytes())[0];
107 time_hi_and_version[14] = ((new String("0")).getBytes())[0];
108 time_hi_and_version[15] = ((new String("0")).getBytes())[0];
109
110
111 BigInteger clockSequence = BigInteger.valueOf(CLOCK_SEQUENCE);
112 String clockString = clockSequence.toString(2);
113 if (clockString.length() < 14) {
114 int nbExtraZeros = 14 - bitString.length();
115 String extraZeros = new String();
116 for (int i = 0; i < nbExtraZeros; i++)
117 extraZeros = extraZeros.concat("0");
118
119 clockString = extraZeros.concat(bitString);
120 }
121
122 byte[] clock_bits = clockString.getBytes();
123 byte[] clock_seq_low = new byte[8];
124 for (int i = 0; i < 8; i++)
125 clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
126
127
128 byte[] clock_seq_hi_and_reserved = new byte[8];
129 for (int i = 0; i < 6; i++)
130 clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];
131
132 clock_seq_hi_and_reserved[6] = ((new String("0")).getBytes())[0];
133 clock_seq_hi_and_reserved[7] = ((new String("1")).getBytes())[0];
134
135 String timeLow = Long.toHexString((new BigInteger(new String(reverseArray(time_low)), 2)).longValue());
136 if (timeLow.length() < 8) {
137 int nbExtraZeros = 8 - timeLow.length();
138 String extraZeros = new String();
139 for (int i = 0; i < nbExtraZeros; i++)
140 extraZeros = extraZeros.concat("0");
141
142 timeLow = extraZeros.concat(timeLow);
143 }
144
145 String timeMid = Long.toHexString((new BigInteger(new String(reverseArray(time_mid)), 2)).longValue());
146 if (timeMid.length() < 4) {
147 int nbExtraZeros = 4 - timeMid.length();
148 String extraZeros = new String();
149 for (int i = 0; i < nbExtraZeros; i++)
150 extraZeros = extraZeros.concat("0");
151 timeMid = extraZeros.concat(timeMid);
152 }
153
154 String timeHiAndVersion = Long.toHexString((new BigInteger(new String(reverseArray(time_hi_and_version)), 2)).longValue());
155 if (timeHiAndVersion.length() < 4) {
156 int nbExtraZeros = 4 - timeHiAndVersion.length();
157 String extraZeros = new String();
158 for (int i = 0; i < nbExtraZeros; i++)
159 extraZeros = extraZeros.concat("0");
160
161 timeHiAndVersion = extraZeros.concat(timeHiAndVersion);
162 }
163
164 String clockSeqHiAndReserved = Long.toHexString((new BigInteger(new String(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
165 if (clockSeqHiAndReserved.length() < 2) {
166 int nbExtraZeros = 2 - clockSeqHiAndReserved.length();
167 String extraZeros = new String();
168 for (int i = 0; i < nbExtraZeros; i++)
169 extraZeros = extraZeros.concat("0");
170
171 clockSeqHiAndReserved = extraZeros.concat(clockSeqHiAndReserved);
172 }
173
174 String clockSeqLow = Long.toHexString((new BigInteger(new String(reverseArray(clock_seq_low)), 2)).longValue());
175 if (clockSeqLow.length() < 2) {
176 int nbExtraZeros = 2 - clockSeqLow.length();
177 String extraZeros = new String();
178 for (int i = 0; i < nbExtraZeros; i++)
179 extraZeros = extraZeros.concat("0");
180
181 clockSeqLow = extraZeros.concat(clockSeqLow);
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 Random secureRandom = null;
199 try {
200 secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
201 } catch (Exception e) {
202 secureRandom = new Random();
203 }
204
205 long nodeValue = secureRandom.nextLong();
206 nodeValue = Math.abs(nodeValue);
207 while (nodeValue > 140737488355328L) {
208 nodeValue = secureRandom.nextLong();
209 nodeValue = Math.abs(nodeValue);
210 }
211
212 BigInteger nodeInt = BigInteger.valueOf(nodeValue);
213 String nodeString = nodeInt.toString(2);
214 if (nodeString.length() < 47) {
215 int nbExtraZeros = 47 - nodeString.length();
216 String extraZeros = new String();
217 for (int i = 0; i < nbExtraZeros; i++)
218 extraZeros = extraZeros.concat("0");
219
220 nodeString = extraZeros.concat(nodeString);
221 }
222
223 byte[] node_bits = nodeString.getBytes();
224 byte[] node = new byte[48];
225 for (int i = 0; i < 47; i++)
226 node[i] = node_bits[node_bits.length - i - 1];
227
228 node[47] = ((new String("1")).getBytes())[0];
229 String theNode = Long.toHexString((new BigInteger(new String(reverseArray(node)), 2)).longValue());
230 if (theNode.length() < 12) {
231 int nbExtraZeros = 12 - theNode.length();
232 String extraZeros = new String();
233 for (int i = 0; i < nbExtraZeros; i++)
234 extraZeros = extraZeros.concat("0");
235 theNode = extraZeros.concat(theNode);
236 }
237
238 String result = timeLow + "-" + timeMid + "-" + timeHiAndVersion + "-" + clockSeqHiAndReserved + clockSeqLow + "-" + theNode;
239
240 return result.toUpperCase();
241 }
242
243 private static byte[] reverseArray(byte[] bits)
244 {
245 byte[] result = new byte[bits.length];
246 for (int i = 0; i < result.length; i++)
247 result[i] = bits[result.length - 1 - i];
248
249 return result;
250 }
251
252
253 /****************************************************************************/
254 /****************************** TEST DRIVER *********************************/
255 /****************************************************************************/
256
257
258 public static void main(String args[])
259 {
260 SecureUUIDGen generator = new SecureUUIDGen();
261
262 long start = System.currentTimeMillis();
263
264 for (int i = 1; i <= 100; ++i)
265 generator.uuidgen();
266
267 long end = System.currentTimeMillis();
268
269 System.out.println("SecureUUIDGen: Generation of 100 UUID's took "+(end-start)+" milliseconds.");
270 }
271 }