1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application.viewstate;
20
21 import java.security.NoSuchAlgorithmException;
22 import java.security.NoSuchProviderException;
23 import java.security.SecureRandom;
24 import java.util.Queue;
25 import java.util.concurrent.ConcurrentLinkedQueue;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29
30
31
32
33
34 class SessionIdGenerator
35 {
36
37 private static Logger log = Logger.getLogger(SessionIdGenerator.class.getName());
38
39
40
41
42
43
44
45
46 private Queue<SecureRandom> randoms =
47 new ConcurrentLinkedQueue<SecureRandom>();
48
49
50
51
52
53
54 private String secureRandomClass = null;
55
56
57
58
59
60
61
62
63
64 private String secureRandomAlgorithm = "SHA1PRNG";
65
66
67
68
69
70
71
72
73 private String secureRandomProvider = null;
74
75
76
77 private String jvmRoute = "";
78
79
80
81 private int sessionIdLength = 16;
82
83
84
85
86
87
88 public void setSecureRandomClass(String secureRandomClass)
89 {
90 this.secureRandomClass = secureRandomClass;
91 }
92
93
94
95
96
97
98 public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
99 {
100 this.secureRandomAlgorithm = secureRandomAlgorithm;
101 }
102
103
104
105
106
107
108 public void setSecureRandomProvider(String secureRandomProvider)
109 {
110 this.secureRandomProvider = secureRandomProvider;
111 }
112
113
114
115
116
117
118
119 public void setJvmRoute(String jvmRoute)
120 {
121 this.jvmRoute = jvmRoute;
122 }
123
124
125
126
127
128
129 public void setSessionIdLength(int sessionIdLength)
130 {
131 this.sessionIdLength = sessionIdLength;
132 }
133
134
135
136
137 public String generateSessionId()
138 {
139
140 byte random[] = new byte[16];
141
142
143 StringBuilder buffer = new StringBuilder();
144
145 int resultLenBytes = 0;
146
147 while (resultLenBytes < sessionIdLength)
148 {
149 getRandomBytes(random);
150 for (int j = 0;
151 j < random.length && resultLenBytes < sessionIdLength;
152 j++)
153 {
154 byte b1 = (byte) ((random[j] & 0xf0) >> 4);
155 byte b2 = (byte) (random[j] & 0x0f);
156 if (b1 < 10)
157 {
158 buffer.append((char) ('0' + b1));
159 }
160 else
161 {
162 buffer.append((char) ('A' + (b1 - 10)));
163 }
164 if (b2 < 10)
165 {
166 buffer.append((char) ('0' + b2));
167 }
168 else
169 {
170 buffer.append((char) ('A' + (b2 - 10)));
171 }
172 resultLenBytes++;
173 }
174 }
175
176 if (jvmRoute != null && jvmRoute.length() > 0)
177 {
178 buffer.append('.').append(jvmRoute);
179 }
180
181 return buffer.toString();
182 }
183
184 public void getRandomBytes(byte bytes[])
185 {
186 SecureRandom random = randoms.poll();
187 if (random == null)
188 {
189 random = createSecureRandom();
190 }
191 random.nextBytes(bytes);
192 randoms.add(random);
193 }
194
195
196
197
198
199 private SecureRandom createSecureRandom()
200 {
201
202 SecureRandom result = null;
203
204 long t1 = System.currentTimeMillis();
205 if (secureRandomClass != null)
206 {
207 try
208 {
209
210 Class<?> clazz = Class.forName(secureRandomClass);
211 result = (SecureRandom) clazz.newInstance();
212 }
213 catch (Exception e)
214 {
215 log.log(Level.SEVERE, "Exception initializing random number generator of class "+
216 secureRandomClass + ". Falling back to java.secure.SecureRandom", e);
217 }
218 }
219
220 if (result == null)
221 {
222
223 try
224 {
225 if (secureRandomProvider != null
226 && secureRandomProvider.length() > 0)
227 {
228 result = SecureRandom.getInstance(secureRandomAlgorithm,
229 secureRandomProvider);
230 }
231 else
232 {
233 if (secureRandomAlgorithm != null
234 && secureRandomAlgorithm.length() > 0)
235 {
236 result = SecureRandom.getInstance(secureRandomAlgorithm);
237 }
238 }
239 }
240 catch (NoSuchAlgorithmException e)
241 {
242 log.log(Level.SEVERE, "Exception initializing random number generator using algorithm: "+
243 secureRandomAlgorithm, e);
244 }
245 catch (NoSuchProviderException e)
246 {
247 log.log(Level.SEVERE, "Exception initializing random number generator using provider: " +
248 secureRandomProvider, e);
249 }
250 }
251
252 if (result == null)
253 {
254
255 try
256 {
257 result = SecureRandom.getInstance("SHA1PRNG");
258 }
259 catch (NoSuchAlgorithmException e)
260 {
261 log.log(Level.SEVERE, "Invalid provider / algoritm SHA1PRNG for generate secure random token", e);
262 }
263 }
264
265 if (result == null)
266 {
267
268 result = new SecureRandom();
269 }
270
271
272 result.nextInt();
273
274 long t2 = System.currentTimeMillis();
275 if ((t2 - t1) > 100)
276 {
277 if (log.isLoggable(Level.FINEST))
278 {
279 log.info("Creation of SecureRandom instance for session ID generation using ["
280 +result.getAlgorithm()+"] took ["+Long.valueOf(t2 - t1)+"] milliseconds.");
281 }
282 }
283 return result;
284 }
285 }