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.text.ParseException;
24 import java.text.SimpleDateFormat;
25 import java.util.Date;
26 import java.util.TimeZone;
27
28 import javax.security.auth.kerberos.KerberosKey;
29 import javax.security.auth.kerberos.KerberosPrincipal;
30
31 import junit.framework.TestCase;
32
33 import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
34 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
35 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedTimeStamp;
36 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
37 import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
38
39
40
41
42
43
44
45
46 public class CipherTextHandlerTest extends TestCase
47 {
48 private byte[] desEncryptedTimeStamp =
49 { ( byte ) 0x97, ( byte ) 0x21, ( byte ) 0x58, ( byte ) 0x5f, ( byte ) 0x81, ( byte ) 0x46, ( byte ) 0x17,
50 ( byte ) 0xa6, ( byte ) 0x4e, ( byte ) 0x8a, ( byte ) 0x5d, ( byte ) 0xe2, ( byte ) 0xf3, ( byte ) 0xd1,
51 ( byte ) 0x40, ( byte ) 0x30, ( byte ) 0x38, ( byte ) 0x5e, ( byte ) 0xb8, ( byte ) 0xf6, ( byte ) 0xad,
52 ( byte ) 0xd8, ( byte ) 0x7c, ( byte ) 0x30, ( byte ) 0xb0, ( byte ) 0x0d, ( byte ) 0x69, ( byte ) 0x71,
53 ( byte ) 0x08, ( byte ) 0xd5, ( byte ) 0x6a, ( byte ) 0x61, ( byte ) 0x1f, ( byte ) 0xee, ( byte ) 0x38,
54 ( byte ) 0xad, ( byte ) 0x43, ( byte ) 0x99, ( byte ) 0xae, ( byte ) 0xc2, ( byte ) 0xd2, ( byte ) 0xf5,
55 ( byte ) 0xb2, ( byte ) 0xb7, ( byte ) 0x95, ( byte ) 0x22, ( byte ) 0x93, ( byte ) 0x12, ( byte ) 0x63,
56 ( byte ) 0xd5, ( byte ) 0xf4, ( byte ) 0x39, ( byte ) 0xfa, ( byte ) 0x27, ( byte ) 0x6e, ( byte ) 0x8e };
57
58 private byte[] tripleDesEncryptedTimeStamp =
59 { ( byte ) 0x96, ( byte ) 0xcb, ( byte ) 0x38, ( byte ) 0xb3, ( byte ) 0xc9, ( byte ) 0xb5, ( byte ) 0x78,
60 ( byte ) 0x17, ( byte ) 0xba, ( byte ) 0x0a, ( byte ) 0x64, ( byte ) 0x49, ( byte ) 0x18, ( byte ) 0x39,
61 ( byte ) 0x57, ( byte ) 0x1e, ( byte ) 0xcf, ( byte ) 0xfc, ( byte ) 0x6e, ( byte ) 0x0f, ( byte ) 0x53,
62 ( byte ) 0xe2, ( byte ) 0x9c, ( byte ) 0x96, ( byte ) 0xfd, ( byte ) 0xbc, ( byte ) 0xc6, ( byte ) 0x1e,
63 ( byte ) 0x10, ( byte ) 0x35, ( byte ) 0xe0, ( byte ) 0x8f, ( byte ) 0xc1, ( byte ) 0x7f, ( byte ) 0xbd,
64 ( byte ) 0x86, ( byte ) 0x55, ( byte ) 0xf2, ( byte ) 0x22, ( byte ) 0x48, ( byte ) 0x86, ( byte ) 0xfb,
65 ( byte ) 0x92, ( byte ) 0x22, ( byte ) 0xe7, ( byte ) 0xbe, ( byte ) 0xd1, ( byte ) 0xec, ( byte ) 0x2e,
66 ( byte ) 0x37, ( byte ) 0xd8, ( byte ) 0x47, ( byte ) 0x1e, ( byte ) 0xa0, ( byte ) 0x16, ( byte ) 0x70,
67 ( byte ) 0x5f, ( byte ) 0x6b, ( byte ) 0x18, ( byte ) 0xf3 };
68
69 private byte[] aes128EncryptedTimeStamp =
70 { ( byte ) 0x4f, ( byte ) 0x1e, ( byte ) 0x52, ( byte ) 0xf5, ( byte ) 0xe0, ( byte ) 0xee, ( byte ) 0xe5,
71 ( byte ) 0xe2, ( byte ) 0x2c, ( byte ) 0x9b, ( byte ) 0xf4, ( byte ) 0xdc, ( byte ) 0x58, ( byte ) 0x5f,
72 ( byte ) 0x00, ( byte ) 0x96, ( byte ) 0x31, ( byte ) 0xfe, ( byte ) 0xc7, ( byte ) 0xf7, ( byte ) 0x89,
73 ( byte ) 0x38, ( byte ) 0x88, ( byte ) 0xf5, ( byte ) 0x25, ( byte ) 0xaf, ( byte ) 0x09, ( byte ) 0x9f,
74 ( byte ) 0xfd, ( byte ) 0x78, ( byte ) 0x68, ( byte ) 0x3b, ( byte ) 0xb4, ( byte ) 0x1e, ( byte ) 0xc2,
75 ( byte ) 0xfc, ( byte ) 0x2d, ( byte ) 0xf3, ( byte ) 0x41, ( byte ) 0x88, ( byte ) 0x92, ( byte ) 0x7e,
76 ( byte ) 0xd7, ( byte ) 0xed, ( byte ) 0xe1, ( byte ) 0xe0, ( byte ) 0x0c, ( byte ) 0xad, ( byte ) 0xe5,
77 ( byte ) 0x06, ( byte ) 0xbf, ( byte ) 0x30, ( byte ) 0x1e, ( byte ) 0xbf, ( byte ) 0xf2, ( byte ) 0xec };
78
79 private byte[] aes256EncryptedTimeStamp =
80 { ( byte ) 0xa8, ( byte ) 0x40, ( byte ) 0x73, ( byte ) 0xfc, ( byte ) 0xe5, ( byte ) 0x45, ( byte ) 0x66,
81 ( byte ) 0xd6, ( byte ) 0x83, ( byte ) 0xb4, ( byte ) 0xed, ( byte ) 0xb6, ( byte ) 0x18, ( byte ) 0x5a,
82 ( byte ) 0xd2, ( byte ) 0x24, ( byte ) 0xd6, ( byte ) 0xef, ( byte ) 0x38, ( byte ) 0xac, ( byte ) 0xdf,
83 ( byte ) 0xcd, ( byte ) 0xed, ( byte ) 0x6d, ( byte ) 0x32, ( byte ) 0xf6, ( byte ) 0x00, ( byte ) 0xd1,
84 ( byte ) 0xc0, ( byte ) 0xb0, ( byte ) 0x1e, ( byte ) 0x70, ( byte ) 0x13, ( byte ) 0x48, ( byte ) 0x0a,
85 ( byte ) 0x5a, ( byte ) 0xbb, ( byte ) 0xd2, ( byte ) 0x2a, ( byte ) 0x6b, ( byte ) 0x16, ( byte ) 0x29,
86 ( byte ) 0x63, ( byte ) 0xba, ( byte ) 0xea, ( byte ) 0xb7, ( byte ) 0x1a, ( byte ) 0x90, ( byte ) 0x7b,
87 ( byte ) 0xf4, ( byte ) 0x89, ( byte ) 0x94, ( byte ) 0x7a, ( byte ) 0x2d, ( byte ) 0x6a, ( byte ) 0xf1 };
88
89 private byte[] arcfourEncryptedTimeStamp =
90 { ( byte ) 0xa2, ( byte ) 0x4f, ( byte ) 0x04, ( byte ) 0x6d, ( byte ) 0x93, ( byte ) 0x31, ( byte ) 0x19,
91 ( byte ) 0x77, ( byte ) 0x3f, ( byte ) 0x9d, ( byte ) 0xf9, ( byte ) 0x6f, ( byte ) 0x7e, ( byte ) 0x86,
92 ( byte ) 0x2c, ( byte ) 0x99, ( byte ) 0x63, ( byte ) 0xc5, ( byte ) 0xcf, ( byte ) 0xe2, ( byte ) 0xf1,
93 ( byte ) 0x54, ( byte ) 0x05, ( byte ) 0x6a, ( byte ) 0xea, ( byte ) 0x20, ( byte ) 0x37, ( byte ) 0x31,
94 ( byte ) 0xa2, ( byte ) 0xdc, ( byte ) 0xe8, ( byte ) 0x79, ( byte ) 0xaa, ( byte ) 0xae, ( byte ) 0x1c,
95 ( byte ) 0xfa, ( byte ) 0x93, ( byte ) 0x02, ( byte ) 0xbe, ( byte ) 0x11, ( byte ) 0x14, ( byte ) 0x22,
96 ( byte ) 0x65, ( byte ) 0x92, ( byte ) 0xbd, ( byte ) 0xf5, ( byte ) 0x52, ( byte ) 0x9f, ( byte ) 0x94,
97 ( byte ) 0x67, ( byte ) 0x10, ( byte ) 0xd2 };
98
99 private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
100
101 private static final SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMddHHmmss'Z'" );
102
103 static
104 {
105 dateFormat.setTimeZone( UTC_TIME_ZONE );
106 }
107
108
109
110
111
112
113
114 public void testTestVectorLengths()
115 {
116 assertEquals( "DES length", 56, desEncryptedTimeStamp.length );
117 assertEquals( "DES3 length", 60, tripleDesEncryptedTimeStamp.length );
118 assertEquals( "AES128 length", 56, aes128EncryptedTimeStamp.length );
119 assertEquals( "AES256 length", 56, aes256EncryptedTimeStamp.length );
120 assertEquals( "RC4-HMAC length", 52, arcfourEncryptedTimeStamp.length );
121 }
122
123
124
125
126
127
128
129 public void testDesGoodPasswordDecrypt()
130 {
131 CipherTextHandler lockBox = new CipherTextHandler();
132 Class hint = EncryptedTimeStamp.class;
133 KerberosPrincipal principal = new KerberosPrincipal( "erodriguez@EXAMPLE.COM" );
134 KerberosKey kerberosKey = new KerberosKey( principal, "kerby".toCharArray(), "DES" );
135 EncryptionKey key = new EncryptionKey( EncryptionType.DES_CBC_MD5, kerberosKey.getEncoded() );
136 EncryptedData data = new EncryptedData( EncryptionType.DES_CBC_MD5, 0, desEncryptedTimeStamp );
137
138 try
139 {
140 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, data, KeyUsage.NUMBER1 );
141 assertEquals( "TimeStamp", "20070322233107Z", object.getTimeStamp().toString() );
142 assertEquals( "MicroSeconds", 291067, object.getMicroSeconds() );
143 }
144 catch ( KerberosException ke )
145 {
146 fail( "Should not have caught exception." );
147 }
148 }
149
150
151
152
153
154
155 public void testDesBadPasswordDecrypt()
156 {
157 CipherTextHandler lockBox = new CipherTextHandler();
158 Class hint = EncryptedTimeStamp.class;
159 KerberosPrincipal principal = new KerberosPrincipal( "erodriguez@EXAMPLE.COM" );
160 KerberosKey kerberosKey = new KerberosKey( principal, "badpassword".toCharArray(), "DES" );
161 EncryptionKey key = new EncryptionKey( EncryptionType.DES_CBC_MD5, kerberosKey.getEncoded() );
162 EncryptedData data = new EncryptedData( EncryptionType.DES_CBC_MD5, 0, desEncryptedTimeStamp );
163
164 try
165 {
166 lockBox.unseal( hint, key, data, KeyUsage.NUMBER1 );
167 fail( "Should have thrown exception." );
168 }
169 catch ( KerberosException ke )
170 {
171 assertEquals( "ErrorCode", 31, ke.getErrorCode() );
172 }
173 }
174
175
176
177
178
179
180
181 public void testTripleDesGoodPasswordDecrypt()
182 {
183 CipherTextHandler lockBox = new CipherTextHandler();
184 Class hint = EncryptedTimeStamp.class;
185 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
186 String algorithm = VendorHelper.getTripleDesAlgorithm();
187 KerberosKey kerberosKey = new KerberosKey( principal, "secret".toCharArray(), algorithm );
188 EncryptionKey key = new EncryptionKey( EncryptionType.DES3_CBC_SHA1_KD, kerberosKey.getEncoded() );
189 EncryptedData data = new EncryptedData( EncryptionType.DES3_CBC_SHA1_KD, 0, tripleDesEncryptedTimeStamp );
190
191 try
192 {
193 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, data, KeyUsage.NUMBER1 );
194 assertEquals( "TimeStamp", "20070410190400Z", object.getTimeStamp().toString() );
195 assertEquals( "MicroSeconds", 460450, object.getMicroSeconds() );
196 }
197 catch ( KerberosException ke )
198 {
199 fail( "Should not have caught exception." );
200 }
201 }
202
203
204
205
206
207
208
209
210
211 public void testTripleDesGoodPasswordEncrypt() throws ParseException
212 {
213 CipherTextHandler lockBox = new CipherTextHandler();
214 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
215 String algorithm = VendorHelper.getTripleDesAlgorithm();
216 KerberosKey kerberosKey = new KerberosKey( principal, "secret".toCharArray(), algorithm );
217 EncryptionKey key = new EncryptionKey( EncryptionType.DES3_CBC_SHA1_KD, kerberosKey.getEncoded() );
218
219 String zuluTime = "20070410190400Z";
220 int microSeconds = 460450;
221 EncryptedTimeStamp encryptedTimeStamp = getEncryptedTimeStamp( zuluTime, microSeconds );
222
223 EncryptedData encryptedData = null;
224
225 try
226 {
227 encryptedData = lockBox.seal( key, encryptedTimeStamp, KeyUsage.NUMBER1 );
228 }
229 catch ( KerberosException ke )
230 {
231 fail( "Should not have caught exception." );
232 }
233
234 Class hint = EncryptedTimeStamp.class;
235
236 try
237 {
238 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, encryptedData,
239 KeyUsage.NUMBER1 );
240 assertEquals( "TimeStamp", zuluTime, object.getTimeStamp().toString() );
241 assertEquals( "MicroSeconds", microSeconds, object.getMicroSeconds() );
242 }
243 catch ( KerberosException ke )
244 {
245 fail( "Should not have caught exception." );
246 }
247 }
248
249
250
251
252
253
254
255 public void testAes128GoodPasswordDecrypt()
256 {
257 if ( !VendorHelper.isCtsSupported() )
258 {
259 return;
260 }
261
262 CipherTextHandler lockBox = new CipherTextHandler();
263 Class hint = EncryptedTimeStamp.class;
264 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
265 KerberosKey kerberosKey = new KerberosKey( principal, "secret".toCharArray(), "AES128" );
266 EncryptionKey key = new EncryptionKey( EncryptionType.AES128_CTS_HMAC_SHA1_96, kerberosKey.getEncoded() );
267 EncryptedData data = new EncryptedData( EncryptionType.AES128_CTS_HMAC_SHA1_96, 0, aes128EncryptedTimeStamp );
268
269 try
270 {
271 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, data, KeyUsage.NUMBER1 );
272 assertEquals( "TimeStamp", "20070410212557Z", object.getTimeStamp().toString() );
273 assertEquals( "MicroSeconds", 379386, object.getMicroSeconds() );
274 }
275 catch ( KerberosException ke )
276 {
277 fail( "Should not have caught exception." );
278 }
279 }
280
281
282
283
284
285
286
287
288
289 public void testAes128GoodPasswordEncrypt() throws ParseException
290 {
291 if ( !VendorHelper.isCtsSupported() )
292 {
293 return;
294 }
295
296 CipherTextHandler lockBox = new CipherTextHandler();
297 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
298 KerberosKey kerberosKey = new KerberosKey( principal, "secret".toCharArray(), "AES128" );
299 EncryptionKey key = new EncryptionKey( EncryptionType.AES128_CTS_HMAC_SHA1_96, kerberosKey.getEncoded() );
300
301 String zuluTime = "20070410190400Z";
302 int microSeconds = 460450;
303 EncryptedTimeStamp encryptedTimeStamp = getEncryptedTimeStamp( zuluTime, microSeconds );
304
305 EncryptedData encryptedData = null;
306
307 try
308 {
309 encryptedData = lockBox.seal( key, encryptedTimeStamp, KeyUsage.NUMBER1 );
310 }
311 catch ( KerberosException ke )
312 {
313 fail( "Should not have caught exception." );
314 }
315
316 Class hint = EncryptedTimeStamp.class;
317
318 try
319 {
320 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, encryptedData,
321 KeyUsage.NUMBER1 );
322 assertEquals( "TimeStamp", "20070410190400Z", object.getTimeStamp().toString() );
323 assertEquals( "MicroSeconds", 460450, object.getMicroSeconds() );
324 }
325 catch ( KerberosException ke )
326 {
327 fail( "Should not have caught exception." );
328 }
329 }
330
331
332
333
334
335
336
337 public void testAes256GoodPasswordDecrypt()
338 {
339 if ( !VendorHelper.isCtsSupported() )
340 {
341 return;
342 }
343
344 CipherTextHandler lockBox = new CipherTextHandler();
345 Class hint = EncryptedTimeStamp.class;
346
347 KerberosKey kerberosKey;
348
349 try
350 {
351 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
352 kerberosKey = new KerberosKey( principal, "secret".toCharArray(), "AES256" );
353 }
354 catch ( IllegalArgumentException iae )
355 {
356
357 return;
358 }
359
360 EncryptionKey key = new EncryptionKey( EncryptionType.AES256_CTS_HMAC_SHA1_96, kerberosKey.getEncoded() );
361 EncryptedData data = new EncryptedData( EncryptionType.AES256_CTS_HMAC_SHA1_96, 0, aes256EncryptedTimeStamp );
362
363 try
364 {
365 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, data, KeyUsage.NUMBER1 );
366 assertEquals( "TimeStamp", "20070410212809Z", object.getTimeStamp().toString() );
367 assertEquals( "MicroSeconds", 298294, object.getMicroSeconds() );
368 }
369 catch ( KerberosException ke )
370 {
371 fail( "Should not have caught exception." );
372 }
373 }
374
375
376
377
378
379
380
381
382
383 public void testAes256GoodPasswordEncrypt() throws ParseException
384 {
385 if ( !VendorHelper.isCtsSupported() )
386 {
387 return;
388 }
389
390 CipherTextHandler lockBox = new CipherTextHandler();
391
392 KerberosKey kerberosKey;
393
394 try
395 {
396 KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
397 kerberosKey = new KerberosKey( principal, "secret".toCharArray(), "AES256" );
398 }
399 catch ( IllegalArgumentException iae )
400 {
401
402 return;
403 }
404
405 EncryptionKey key = new EncryptionKey( EncryptionType.AES256_CTS_HMAC_SHA1_96, kerberosKey.getEncoded() );
406
407 String zuluTime = "20070410190400Z";
408 int microSeconds = 460450;
409 EncryptedTimeStamp encryptedTimeStamp = getEncryptedTimeStamp( zuluTime, microSeconds );
410
411 EncryptedData encryptedData = null;
412
413 try
414 {
415 encryptedData = lockBox.seal( key, encryptedTimeStamp, KeyUsage.NUMBER1 );
416 }
417 catch ( KerberosException ke )
418 {
419 fail( "Should not have caught exception." );
420 }
421
422 Class hint = EncryptedTimeStamp.class;
423
424 try
425 {
426 EncryptedTimeStamp object = ( EncryptedTimeStamp ) lockBox.unseal( hint, key, encryptedData,
427 KeyUsage.NUMBER1 );
428 assertEquals( "TimeStamp", "20070410190400Z", object.getTimeStamp().toString() );
429 assertEquals( "MicroSeconds", 460450, object.getMicroSeconds() );
430 }
431 catch ( KerberosException ke )
432 {
433 fail( "Should not have caught exception." );
434 }
435 }
436
437
438 protected EncryptedTimeStamp getEncryptedTimeStamp( String zuluTime, int microSeconds ) throws ParseException
439 {
440 Date date = null;
441 synchronized ( dateFormat )
442 {
443 date = dateFormat.parse( zuluTime );
444 }
445
446 KerberosTime timeStamp = new KerberosTime( date );
447
448 return new EncryptedTimeStamp( timeStamp, microSeconds );
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 }