KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > directwebremoting > util > IdGenerator


1 /*
2  * Copyright 2005 Joe Walker
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.directwebremoting.util;
17
18 import java.security.MessageDigest JavaDoc;
19 import java.security.NoSuchAlgorithmException JavaDoc;
20 import java.security.SecureRandom JavaDoc;
21 import java.util.Random JavaDoc;
22
23 /**
24  * Code to generate page ids.
25  * IdGenerators are expensive to setup so it is suggested that you share
26  * instances wherever possible. This action will also enhance security.
27  * Much of this code is adapted from org.apache.catalina.session.ManagerBase.
28  * Specifically Revision 1.37 which has been unchanged in the past 18 months.
29  * I have taken out the /dev/urandom stuff and simplified things to the point
30  * where we can audit it to work out what might be broken.
31  * @author Joe Walker [joe at getahead dot ltd dot uk]
32  */

33 public class IdGenerator
34 {
35     /**
36      * Seed the random number
37      */

38     public IdGenerator()
39     {
40         // Start with the current system time as a seed
41
long seed = System.currentTimeMillis();
42
43         // Also throw in the system identifier for 'this' from toString
44
char[] entropy = this.toString().toCharArray();
45         for (int i = 0; i < entropy.length; i++)
46         {
47             long update = ((byte) entropy[i]) << ((i % 8) * 8);
48             seed ^= update;
49         }
50
51         random.setSeed(seed);
52     }
53
54     /**
55      * Generate and return a new session identifier.
56      * @param length The number of bytes to generate
57      * @return A new page id string
58      */

59     public synchronized String JavaDoc generateId(int length)
60     {
61         byte buffer[] = new byte[16];
62
63         // Render the result as a String of hexadecimal digits
64
StringBuffer JavaDoc reply = new StringBuffer JavaDoc();
65
66         int resultLenBytes = 0;
67         while (resultLenBytes < length)
68         {
69             random.nextBytes(buffer);
70             buffer = getDigest().digest(buffer);
71
72             for (int j = 0; j < buffer.length && resultLenBytes < length; j++)
73             {
74                 byte b1 = (byte) ((buffer[j] & 0xf0) >> 4);
75                 if (b1 < 10)
76                 {
77                     reply.append((char) ('0' + b1));
78                 }
79                 else
80                 {
81                     reply.append((char) ('A' + (b1 - 10)));
82                 }
83
84                 byte b2 = (byte) (buffer[j] & 0x0f);
85                 if (b2 < 10)
86                 {
87                     reply.append((char) ('0' + b2));
88                 }
89                 else
90                 {
91                     reply.append((char) ('A' + (b2 - 10)));
92                 }
93
94                 resultLenBytes++;
95             }
96         }
97
98         return reply.toString();
99     }
100
101     /**
102      * @return the algorithm
103      */

104     public synchronized String JavaDoc getAlgorithm()
105     {
106         return algorithm;
107     }
108
109     /**
110      * @param algorithm the algorithm to set
111      */

112     public synchronized void setAlgorithm(String JavaDoc algorithm)
113     {
114         this.algorithm = algorithm;
115         digest = null;
116     }
117
118     /**
119      * Return the MessageDigest object to be used for calculating
120      * session identifiers. If none has been created yet, initialize
121      * one the first time this method is called.
122      * @return The hashing algorithm
123      */

124     private MessageDigest JavaDoc getDigest()
125     {
126         if (digest == null)
127         {
128             try
129             {
130                 digest = MessageDigest.getInstance(algorithm);
131             }
132             catch (NoSuchAlgorithmException JavaDoc ex)
133             {
134                 try
135                 {
136                     digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
137                 }
138                 catch (NoSuchAlgorithmException JavaDoc ex2)
139                 {
140                     digest = null;
141                     throw new IllegalStateException JavaDoc("No algorithms for IdGenerator");
142                 }
143             }
144
145             log.debug("Using MessageDigest: " + digest.getAlgorithm());
146         }
147
148         return digest;
149     }
150
151     /* (non-Javadoc)
152      * @see java.lang.Object#toString()
153      */

154     public String JavaDoc toString()
155     {
156         // This is to make the point that we need toString to return something
157
// that includes some sort of system identifier as does the default.
158
// Don't change this unless you really know what you are doing.
159
return super.toString();
160     }
161
162     /**
163      * The default message digest algorithm to use if we cannot use
164      * the requested one.
165      */

166     protected static final String JavaDoc DEFAULT_ALGORITHM = "MD5";
167
168     /**
169      * The message digest algorithm to be used when generating session
170      * identifiers. This must be an algorithm supported by the
171      * <code>java.security.MessageDigest</code> class on your platform.
172      */

173     protected String JavaDoc algorithm = DEFAULT_ALGORITHM;
174
175     /**
176      * A random number generator to use when generating session identifiers.
177      */

178     protected Random JavaDoc random = new SecureRandom JavaDoc();
179
180     /**
181      * Return the MessageDigest implementation to be used when creating session
182      * identifiers.
183      */

184     protected MessageDigest JavaDoc digest = null;
185
186     /**
187      * The log stream
188      */

189     private static final Logger log = Logger.getLogger(IdGenerator.class);
190 }
191
Popular Tags