KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > juddi > uuidgen > SecureUUIDGen


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.juddi.uuidgen;
17
18 import java.math.BigInteger JavaDoc;
19 import java.security.SecureRandom JavaDoc;
20 import java.util.Random JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /**
26  * Used to create new universally unique identifiers or UUID's (sometimes called
27  * GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
28  *
29  * @author Maarten Coene
30  * @author Steve Viens (sviens@apache.org)
31  */

32 public class SecureUUIDGen implements UUIDGen
33 {
34   // private reference to the jUDDI logger
35
private static Log log = LogFactory.getLog(SecureUUIDGen.class);
36
37   private static final BigInteger JavaDoc COUNT_START = new BigInteger JavaDoc("-12219292800000"); // 15 October 1582
38
private static final int CLOCK_SEQUENCE = (new Random JavaDoc()).nextInt(16384);
39
40   /**
41    *
42    */

43   public String JavaDoc uuidgen()
44   {
45     return nextUUID();
46   }
47
48   /**
49    *
50    */

51   public String JavaDoc[] uuidgen(int nmbr)
52   {
53     String JavaDoc[] uuids = new String JavaDoc[nmbr];
54
55     for (int i=0; i<uuids.length; i++)
56       uuids[i] = nextUUID();
57
58     return uuids;
59   }
60
61   /**
62    * Creates a new UUID. The algorithm used is described by The Open Group.
63    * See <a HREF="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
64    * Universal Unique Identifier</a> for more details.
65    * <p>
66    * Due to a lack of functionality in Java, a part of the UUID is a secure
67    * random. This results in a long processing time when this method is called
68    * for the first time.
69    */

70   protected String JavaDoc nextUUID()
71   {
72       // the count of 100-nanosecond intervals since 00:00:00.00 15 October 1582
73
BigInteger JavaDoc count;
74
75       // the number of milliseconds since 1 January 1970
76
BigInteger JavaDoc current = BigInteger.valueOf(System.currentTimeMillis());
77
78       // the number of milliseconds since 15 October 1582
79
BigInteger JavaDoc countMillis = current.subtract(COUNT_START);
80
81       // the result
82
count = countMillis.multiply(BigInteger.valueOf(10000));
83
84       String JavaDoc bitString = count.toString(2);
85       if (bitString.length() < 60) {
86           int nbExtraZeros = 60 - bitString.length();
87           String JavaDoc extraZeros = new String JavaDoc();
88           for (int i = 0; i < nbExtraZeros; i++)
89               extraZeros = extraZeros.concat("0");
90
91           bitString = extraZeros.concat(bitString);
92       }
93
94       byte[] bits = bitString.getBytes();
95
96       // the time_low field
97
byte[] time_low = new byte[32];
98       for (int i = 0; i < 32; i++)
99           time_low[i] = bits[bits.length - i - 1];
100
101       // the time_mid field
102
byte[] time_mid = new byte[16];
103       for (int i = 0; i < 16; i++)
104           time_mid[i] = bits[bits.length - 32 - i - 1];
105
106       // the time_hi_and_version field
107
byte[] time_hi_and_version = new byte[16];
108       for (int i = 0; i < 12; i++)
109           time_hi_and_version[i] = bits[bits.length - 48 - i - 1];
110
111       time_hi_and_version[12] = ((new String JavaDoc("1")).getBytes())[0];
112       time_hi_and_version[13] = ((new String JavaDoc("0")).getBytes())[0];
113       time_hi_and_version[14] = ((new String JavaDoc("0")).getBytes())[0];
114       time_hi_and_version[15] = ((new String JavaDoc("0")).getBytes())[0];
115
116       // the clock_seq_low field
117
BigInteger JavaDoc clockSequence = BigInteger.valueOf(CLOCK_SEQUENCE);
118       String JavaDoc clockString = clockSequence.toString(2);
119       if (clockString.length() < 14) {
120           int nbExtraZeros = 14 - bitString.length();
121           String JavaDoc extraZeros = new String JavaDoc();
122           for (int i = 0; i < nbExtraZeros; i++)
123               extraZeros = extraZeros.concat("0");
124
125           clockString = extraZeros.concat(bitString);
126       }
127
128       byte[] clock_bits = clockString.getBytes();
129       byte[] clock_seq_low = new byte[8];
130       for (int i = 0; i < 8; i++)
131           clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
132
133       // the clock_seq_hi_and_reserved
134
byte[] clock_seq_hi_and_reserved = new byte[8];
135       for (int i = 0; i < 6; i++)
136           clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];
137
138       clock_seq_hi_and_reserved[6] = ((new String JavaDoc("0")).getBytes())[0];
139       clock_seq_hi_and_reserved[7] = ((new String JavaDoc("1")).getBytes())[0];
140
141       String JavaDoc timeLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_low)), 2)).longValue());
142       if (timeLow.length() < 8) {
143           int nbExtraZeros = 8 - timeLow.length();
144           String JavaDoc extraZeros = new String JavaDoc();
145           for (int i = 0; i < nbExtraZeros; i++)
146               extraZeros = extraZeros.concat("0");
147
148           timeLow = extraZeros.concat(timeLow);
149       }
150
151       String JavaDoc timeMid = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_mid)), 2)).longValue());
152       if (timeMid.length() < 4) {
153           int nbExtraZeros = 4 - timeMid.length();
154           String JavaDoc extraZeros = new String JavaDoc();
155           for (int i = 0; i < nbExtraZeros; i++)
156               extraZeros = extraZeros.concat("0");
157           timeMid = extraZeros.concat(timeMid);
158       }
159
160       String JavaDoc timeHiAndVersion = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(time_hi_and_version)), 2)).longValue());
161       if (timeHiAndVersion.length() < 4) {
162           int nbExtraZeros = 4 - timeHiAndVersion.length();
163           String JavaDoc extraZeros = new String JavaDoc();
164           for (int i = 0; i < nbExtraZeros; i++)
165               extraZeros = extraZeros.concat("0");
166
167           timeHiAndVersion = extraZeros.concat(timeHiAndVersion);
168       }
169
170       String JavaDoc clockSeqHiAndReserved = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
171       if (clockSeqHiAndReserved.length() < 2) {
172           int nbExtraZeros = 2 - clockSeqHiAndReserved.length();
173           String JavaDoc extraZeros = new String JavaDoc();
174           for (int i = 0; i < nbExtraZeros; i++)
175               extraZeros = extraZeros.concat("0");
176
177           clockSeqHiAndReserved = extraZeros.concat(clockSeqHiAndReserved);
178       }
179
180       String JavaDoc clockSeqLow = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(clock_seq_low)), 2)).longValue());
181       if (clockSeqLow.length() < 2) {
182           int nbExtraZeros = 2 - clockSeqLow.length();
183           String JavaDoc extraZeros = new String JavaDoc();
184           for (int i = 0; i < nbExtraZeros; i++)
185               extraZeros = extraZeros.concat("0");
186
187           clockSeqLow = extraZeros.concat(clockSeqLow);
188       }
189
190       // problem: the node should be the IEEE 802 ethernet address, but can not
191
// be retrieved in Java yet.
192
// see bug ID 4173528
193
// workaround (also suggested in bug ID 4173528)
194
// If a system wants to generate UUIDs but has no IEE 802 compliant
195
// network card or other source of IEEE 802 addresses, then this section
196
// describes how to generate one.
197
// The ideal solution is to obtain a 47 bit cryptographic quality random
198
// number, and use it as the low 47 bits of the node ID, with the most
199
// significant bit of the first octet of the node ID set to 1. This bit
200
// is the unicast/multicast bit, which will never be set in IEEE 802
201
// addresses obtained from network cards; hence, there can never be a
202
// conflict between UUIDs generated by machines with and without network
203
// cards.
204
Random JavaDoc secureRandom = null;
205       try {
206           secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
207       } catch (Exception JavaDoc e) {
208           secureRandom = new Random JavaDoc();
209       }
210
211       long nodeValue = secureRandom.nextLong();
212       nodeValue = Math.abs(nodeValue);
213       while (nodeValue > 140737488355328L) {
214           nodeValue = secureRandom.nextLong();
215           nodeValue = Math.abs(nodeValue);
216       }
217
218       BigInteger JavaDoc nodeInt = BigInteger.valueOf(nodeValue);
219       String JavaDoc nodeString = nodeInt.toString(2);
220       if (nodeString.length() < 47) {
221           int nbExtraZeros = 47 - nodeString.length();
222           String JavaDoc extraZeros = new String JavaDoc();
223           for (int i = 0; i < nbExtraZeros; i++)
224               extraZeros = extraZeros.concat("0");
225
226           nodeString = extraZeros.concat(nodeString);
227       }
228
229       byte[] node_bits = nodeString.getBytes();
230       byte[] node = new byte[48];
231       for (int i = 0; i < 47; i++)
232           node[i] = node_bits[node_bits.length - i - 1];
233
234       node[47] = ((new String JavaDoc("1")).getBytes())[0];
235       String JavaDoc theNode = Long.toHexString((new BigInteger JavaDoc(new String JavaDoc(reverseArray(node)), 2)).longValue());
236       if (theNode.length() < 12) {
237           int nbExtraZeros = 12 - theNode.length();
238           String JavaDoc extraZeros = new String JavaDoc();
239           for (int i = 0; i < nbExtraZeros; i++)
240               extraZeros = extraZeros.concat("0");
241           theNode = extraZeros.concat(theNode);
242       }
243
244       String JavaDoc result = timeLow + "-" + timeMid + "-" + timeHiAndVersion + "-" + clockSeqHiAndReserved + clockSeqLow + "-" + theNode;
245
246       return result.toUpperCase();
247   }
248
249   private static byte[] reverseArray(byte[] bits)
250   {
251     byte[] result = new byte[bits.length];
252     for (int i = 0; i < result.length; i++)
253       result[i] = bits[result.length - 1 - i];
254
255     return result;
256   }
257
258
259   /***************************************************************************/
260   /***************************** TEST DRIVER *********************************/
261   /***************************************************************************/
262
263
264   public static void main(String JavaDoc args[])
265   {
266     SecureUUIDGen generator = new SecureUUIDGen();
267
268     long start = System.currentTimeMillis();
269
270     for (int i = 1; i <= 100; ++i)
271       generator.uuidgen();
272
273     long end = System.currentTimeMillis();
274
275     System.out.println("SecureUUIDGen: Generation of 100 UUID's took "+(end-start)+" milliseconds.");
276   }
277 }
278
Popular Tags