1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.kerberos.shared.crypto.encryption;
21
22
23 import java.io.UnsupportedEncodingException;
24 import java.security.GeneralSecurityException;
25 import java.security.InvalidKeyException;
26 import java.security.spec.AlgorithmParameterSpec;
27
28 import javax.crypto.Cipher;
29 import javax.crypto.SecretKey;
30 import javax.crypto.spec.DESKeySpec;
31 import javax.crypto.spec.IvParameterSpec;
32 import javax.crypto.spec.SecretKeySpec;
33
34
35
36
37
38
39
40
41
42
43 public class DesStringToKey
44 {
45
46
47
48
49
50
51 public byte[] getKey( String passPhrase )
52 {
53 return generateKey( passPhrase );
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67 public byte[] getKey( String password, String realmName, String userName )
68 {
69 return generateKey( password + realmName + userName );
70 }
71
72
73
74
75
76
77
78
79
80 protected byte[] generateKey( String passPhrase )
81 {
82 byte encodedByteArray[] = characterEncodeString( passPhrase );
83
84 byte paddedByteArray[] = padString( encodedByteArray );
85
86 byte[] secretKey = fanFold( paddedByteArray );
87
88 secretKey = setParity( secretKey );
89 secretKey = getStrongKey( secretKey );
90 secretKey = calculateChecksum( paddedByteArray, secretKey );
91 secretKey = setParity( secretKey );
92 secretKey = getStrongKey( secretKey );
93
94 return secretKey;
95 }
96
97
98
99
100
101
102
103
104 protected byte[] setParity( byte[] in )
105 {
106 byte[] out = new byte[8];
107
108 int bitCount = 0;
109 int index = 0;
110
111 for ( int i = 0; i < 64; i++ )
112 {
113 if ( ( i + 1 ) % 8 == 0 )
114 {
115 if ( bitCount % 2 == 0 )
116 {
117 setBit( out, i, 1 );
118 }
119
120 index++;
121 bitCount = 0;
122 }
123 else
124 {
125 int val = getBit( in, index );
126 boolean bit = val > 0;
127
128 if ( bit )
129 {
130 setBit( out, i, val );
131 bitCount++;
132 }
133
134 index++;
135 }
136 }
137
138 return out;
139 }
140
141
142
143
144
145
146
147
148
149 protected int getBit( byte[] data, int pos )
150 {
151 int posByte = pos / 8;
152 int posBit = pos % 8;
153
154 byte valByte = data[posByte];
155 int valInt = valByte >> ( 8 - ( posBit + 1 ) ) & 0x0001;
156 return valInt;
157 }
158
159
160
161
162
163
164
165
166
167 protected void setBit( byte[] data, int pos, int val )
168 {
169 int posByte = pos / 8;
170 int posBit = pos % 8;
171 byte oldByte = data[posByte];
172 oldByte = ( byte ) ( ( ( 0xFF7F >> posBit ) & oldByte ) & 0x00FF );
173 byte newByte = ( byte ) ( ( val << ( 8 - ( posBit + 1 ) ) ) | oldByte );
174 data[posByte] = newByte;
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190 protected byte[] fanFold( byte[] paddedByteArray )
191 {
192 byte secretKey[] = new byte[8];
193
194 int div = paddedByteArray.length / 8;
195
196 for ( int ii = 0; ii < div; ii++ )
197 {
198 byte blockValue1[] = new byte[8];
199 System.arraycopy( paddedByteArray, ii * 8, blockValue1, 0, 8 );
200
201 if ( ii % 2 == 1 )
202 {
203 byte tempbyte1 = 0;
204 byte tempbyte2 = 0;
205 byte blockValue2[] = new byte[8];
206
207 for ( int jj = 0; jj < 8; jj++ )
208 {
209 tempbyte2 = 0;
210
211 for ( int kk = 0; kk < 4; kk++ )
212 {
213 tempbyte2 = ( byte ) ( ( 1 << ( 7 - kk ) ) & 0xff );
214 tempbyte1 |= ( blockValue1[jj] & tempbyte2 ) >>> ( 7 - 2 * kk );
215 tempbyte2 = 0;
216 }
217
218 for ( int kk = 4; kk < 8; kk++ )
219 {
220 tempbyte2 = ( byte ) ( ( 1 << ( 7 - kk ) ) & 0xff );
221 tempbyte1 |= ( blockValue1[jj] & tempbyte2 ) << ( 2 * kk - 7 );
222 tempbyte2 = 0;
223 }
224
225 blockValue2[7 - jj] = tempbyte1;
226 tempbyte1 = 0;
227 }
228
229 for ( int jj = 0; jj < 8; jj++ )
230 {
231 blockValue2[jj] = ( byte ) ( ( ( blockValue2[jj] & 0xff ) >>> 1 ) & 0xff );
232 }
233
234 System.arraycopy( blockValue2, 0, blockValue1, 0, blockValue2.length );
235 }
236
237 for ( int jj = 0; jj < 8; jj++ )
238 {
239 blockValue1[jj] = ( byte ) ( ( ( blockValue1[jj] & 0xff ) << 1 ) & 0xff );
240 }
241
242
243 for ( int jj = 0; jj < 8; jj++ )
244 {
245 secretKey[jj] ^= blockValue1[jj];
246 }
247 }
248
249 return secretKey;
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263 protected byte[] calculateChecksum( byte[] data, byte[] keyBytes )
264 {
265 try
266 {
267 Cipher cipher = Cipher.getInstance( "DES/CBC/NoPadding" );
268 SecretKey key = new SecretKeySpec( keyBytes, "DES" );
269
270 AlgorithmParameterSpec paramSpec = new IvParameterSpec( keyBytes );
271
272 cipher.init( Cipher.ENCRYPT_MODE, key, paramSpec );
273
274 byte[] result = cipher.doFinal( data );
275
276 byte[] checksum = new byte[8];
277 System.arraycopy( result, result.length - 8, checksum, 0, 8 );
278
279 return checksum;
280 }
281 catch ( GeneralSecurityException nsae )
282 {
283 nsae.printStackTrace();
284 return null;
285 }
286 }
287
288
289
290
291
292
293
294
295
296 protected byte[] getStrongKey( byte[] secretKey )
297 {
298 try
299 {
300 if ( DESKeySpec.isWeak( secretKey, 0 ) )
301 {
302 secretKey[7] ^= 0xf0;
303 }
304 }
305 catch ( InvalidKeyException ike )
306 {
307 return new byte[8];
308 }
309
310 return secretKey;
311 }
312
313
314
315
316
317
318
319
320 protected byte[] characterEncodeString( String string )
321 {
322 byte encodedByteArray[] = new byte[string.length()];
323
324 try
325 {
326 encodedByteArray = string.getBytes( "UTF-8" );
327 }
328 catch ( UnsupportedEncodingException ue )
329 {
330
331 }
332
333 return encodedByteArray;
334 }
335
336
337
338
339
340
341
342
343 protected byte[] padString( byte encodedString[] )
344 {
345 int length;
346
347 if ( encodedString.length < 8 )
348 {
349 length = encodedString.length;
350 }
351 else
352 {
353 length = encodedString.length % 8;
354 }
355
356 if ( length == 0 )
357 {
358 return encodedString;
359 }
360
361 byte paddedByteArray[] = new byte[( 8 - length ) + encodedString.length];
362
363 for ( int ii = paddedByteArray.length - 1; ii > encodedString.length - 1; ii-- )
364 {
365 paddedByteArray[ii] = 0;
366 }
367
368 System.arraycopy( encodedString, 0, paddedByteArray, 0, encodedString.length );
369
370 return paddedByteArray;
371 }
372 }