1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.kerberos.shared.crypto.encryption;
21  
22  
23  import java.util.Arrays;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
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.messages.value.EncryptionKey;
34  
35  
36  /**
37   * Test cases for string-to-key functions for DES-, DES3-, AES-, and RC4-based
38   * encryption types.
39   * 
40   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
41   * @version $Rev$, $Date$
42   */
43  public class KerberosKeyFactoryTest extends TestCase
44  {
45      /**
46       * Tests that key derivation can be performed for a DES key.
47       */
48      public void testDesKerberosKey()
49      {
50          KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
51          KerberosKey key = new KerberosKey( principal, "secret".toCharArray(), "DES" );
52  
53          assertEquals( "DES key length", 8, key.getEncoded().length );
54      }
55  
56  
57      /**
58       * Tests that key derivation can be performed for a Triple-DES key.
59       */
60      public void testTripleDesKerberosKey()
61      {
62          KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
63          String algorithm = VendorHelper.getTripleDesAlgorithm();
64          KerberosKey key = new KerberosKey( principal, "secret".toCharArray(), algorithm );
65  
66          assertEquals( "DESede key length", 24, key.getEncoded().length );
67      }
68  
69  
70      /**
71       * Tests that key derivation can be performed for an RC4-HMAC key.
72       */
73      public void testArcFourHmacKerberosKey()
74      {
75          if ( !VendorHelper.isArcFourHmacSupported() )
76          {
77              return;
78          }
79  
80          KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
81          KerberosKey key = new KerberosKey( principal, "secret".toCharArray(), "ArcFourHmac" );
82  
83          assertEquals( "ArcFourHmac key length", 16, key.getEncoded().length );
84      }
85  
86  
87      /**
88       * Tests that key derivation can be performed for an AES-128 key.
89       *
90       * @throws Exception
91       */
92      public void testAes128KerberosKey() throws Exception
93      {
94          KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
95          KerberosKey key = new KerberosKey( principal, "secret".toCharArray(), "AES128" );
96  
97          assertEquals( "AES128 key length", 16, key.getEncoded().length );
98      }
99  
100 
101     /**
102      * Tests that key derivation can be performed for an AES-256 key.
103      */
104     public void testAes256KerberosKey()
105     {
106         try
107         {
108             KerberosPrincipal principal = new KerberosPrincipal( "hnelson@EXAMPLE.COM" );
109             KerberosKey kerberosKey = new KerberosKey( principal, "secret".toCharArray(), "AES256" );
110             assertEquals( "AES256 key length", 32, kerberosKey.getEncoded().length );
111         }
112         catch ( IllegalArgumentException iae )
113         {
114             // Algorithm AES256 not enabled
115         }
116     }
117 
118 
119     /**
120      * Tests that key derivation can be performed by the factory for the des-cbc-md5 encryption type.
121      */
122     public void testKerberosKeyFactoryOnlyDes()
123     {
124         String principalName = "hnelson@EXAMPLE.COM";
125         String passPhrase = "secret";
126 
127         Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
128         encryptionTypes.add( EncryptionType.DES_CBC_MD5 );
129 
130         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase,
131             encryptionTypes );
132 
133         assertEquals( "List length", 1, map.values().size() );
134 
135         EncryptionKey kerberosKey = map.get( EncryptionType.DES_CBC_MD5 );
136 
137         EncryptionType keyType = kerberosKey.getKeyType();
138         int keyLength = kerberosKey.getKeyValue().length;
139         byte[] keyBytes = kerberosKey.getKeyValue();
140 
141         assertEquals( keyType, EncryptionType.DES_CBC_MD5 );
142         assertEquals( keyLength, 8 );
143         byte[] expectedBytes = new byte[]
144             { ( byte ) 0xF4, ( byte ) 0xA7, ( byte ) 0x13, ( byte ) 0x64, ( byte ) 0x8A, ( byte ) 0x61, ( byte ) 0xCE,
145                 ( byte ) 0x5B };
146         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
147     }
148 
149 
150     /**
151      * Tests that key derivation can be performed by the factory for the des3-cbc-sha1-kd encryption type.
152      */
153     public void testKerberosKeyFactoryOnlyTripleDes()
154     {
155         if ( !VendorHelper.isTripleDesSupported() )
156         {
157             return;
158         }
159 
160         String principalName = "hnelson@EXAMPLE.COM";
161         String passPhrase = "secret";
162 
163         Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
164         encryptionTypes.add( EncryptionType.DES3_CBC_SHA1_KD );
165 
166         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase,
167             encryptionTypes );
168 
169         assertEquals( "List length", 1, map.values().size() );
170 
171         EncryptionKey kerberosKey = map.get( EncryptionType.DES3_CBC_SHA1_KD );
172 
173         EncryptionType keyType = kerberosKey.getKeyType();
174         int keyLength = kerberosKey.getKeyValue().length;
175         byte[] keyBytes = kerberosKey.getKeyValue();
176 
177         assertEquals( keyType, EncryptionType.DES3_CBC_SHA1_KD );
178         assertEquals( keyLength, 24 );
179         byte[] expectedBytes = new byte[]
180             { ( byte ) 0x57, ( byte ) 0x07, ( byte ) 0xCE, ( byte ) 0x29, ( byte ) 0x52, ( byte ) 0x92, ( byte ) 0x2C,
181                 ( byte ) 0x1C, ( byte ) 0x8C, ( byte ) 0xBF, ( byte ) 0x43, ( byte ) 0xC2, ( byte ) 0x3D,
182                 ( byte ) 0x8F, ( byte ) 0x8C, ( byte ) 0x5E, ( byte ) 0x9E, ( byte ) 0x8C, ( byte ) 0xF7,
183                 ( byte ) 0x5D, ( byte ) 0x3E, ( byte ) 0x4A, ( byte ) 0x5E, ( byte ) 0x25 };
184         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
185     }
186 
187 
188     /**
189      * Tests that key derivation can be performed by the factory for the rc4-hmac encryption type.
190      */
191     public void testKerberosKeyFactoryOnlyArcFourHmac()
192     {
193         if ( !VendorHelper.isArcFourHmacSupported() )
194         {
195             return;
196         }
197 
198         String principalName = "hnelson@EXAMPLE.COM";
199         String passPhrase = "secret";
200 
201         Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
202         encryptionTypes.add( EncryptionType.RC4_HMAC );
203 
204         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase,
205             encryptionTypes );
206 
207         assertEquals( "List length", 1, map.values().size() );
208 
209         EncryptionKey kerberosKey = map.get( EncryptionType.RC4_HMAC );
210 
211         EncryptionType keyType = kerberosKey.getKeyType();
212         int keyLength = kerberosKey.getKeyValue().length;
213         byte[] keyBytes = kerberosKey.getKeyValue();
214 
215         assertEquals( keyType, EncryptionType.RC4_HMAC );
216         assertEquals( keyLength, 16 );
217         byte[] expectedBytes = new byte[]
218             { ( byte ) 0x87, ( byte ) 0x8D, ( byte ) 0x80, ( byte ) 0x14, ( byte ) 0x60, ( byte ) 0x6C, ( byte ) 0xDA,
219                 ( byte ) 0x29, ( byte ) 0x67, ( byte ) 0x7A, ( byte ) 0x44, ( byte ) 0xEF, ( byte ) 0xA1,
220                 ( byte ) 0x35, ( byte ) 0x3F, ( byte ) 0xC7 };
221         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
222     }
223 
224 
225     /**
226      * Tests that key derivation can be performed by the factory for the aes128-cts-hmac-sha1-96 encryption type.
227      */
228     public void testKerberosKeyFactoryOnlyAes128()
229     {
230         if ( VendorHelper.isIbm() )
231         {
232             return;
233         }
234 
235         String principalName = "hnelson@EXAMPLE.COM";
236         String passPhrase = "secret";
237 
238         Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
239         encryptionTypes.add( EncryptionType.AES128_CTS_HMAC_SHA1_96 );
240 
241         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase,
242             encryptionTypes );
243 
244         assertEquals( "List length", 1, map.values().size() );
245 
246         EncryptionKey kerberosKey = map.get( EncryptionType.AES128_CTS_HMAC_SHA1_96 );
247 
248         EncryptionType keyType = kerberosKey.getKeyType();
249         int keyLength = kerberosKey.getKeyValue().length;
250         byte[] keyBytes = kerberosKey.getKeyValue();
251 
252         assertEquals( keyType, EncryptionType.AES128_CTS_HMAC_SHA1_96 );
253         assertEquals( keyLength, 16 );
254         byte[] expectedBytes = new byte[]
255             { ( byte ) 0xAD, ( byte ) 0x21, ( byte ) 0x4B, ( byte ) 0x38, ( byte ) 0xB6, ( byte ) 0x9D, ( byte ) 0xFC,
256                 ( byte ) 0xCA, ( byte ) 0xAC, ( byte ) 0xF1, ( byte ) 0x5F, ( byte ) 0x34, ( byte ) 0x6D,
257                 ( byte ) 0x41, ( byte ) 0x7B, ( byte ) 0x90 };
258 
259         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
260     }
261 
262 
263     /**
264      * Tests that key derivation can be performed by the factory for the aes256-cts-hmac-sha1-96 encryption type.
265      */
266     public void testKerberosKeyFactoryOnlyAes256()
267     {
268         if ( VendorHelper.isIbm() )
269         {
270             return;
271         }
272 
273         String principalName = "hnelson@EXAMPLE.COM";
274         String passPhrase = "secret";
275 
276         Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
277         encryptionTypes.add( EncryptionType.AES256_CTS_HMAC_SHA1_96 );
278 
279         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase,
280             encryptionTypes );
281 
282         EncryptionKey kerberosKey = map.get( EncryptionType.AES256_CTS_HMAC_SHA1_96 );
283 
284         if ( kerberosKey != null )
285         {
286             assertEquals( "List length", 1, map.values().size() );
287 
288             EncryptionType keyType = kerberosKey.getKeyType();
289             int keyLength = kerberosKey.getKeyValue().length;
290             byte[] keyBytes = kerberosKey.getKeyValue();
291 
292             assertEquals( keyType, EncryptionType.AES256_CTS_HMAC_SHA1_96 );
293             assertEquals( keyLength, 32 );
294             byte[] expectedBytes = new byte[]
295                 { ( byte ) 0x3D, ( byte ) 0x33, ( byte ) 0x31, ( byte ) 0x8F, ( byte ) 0xBE, ( byte ) 0x47,
296                     ( byte ) 0xE5, ( byte ) 0x2A, ( byte ) 0x21, ( byte ) 0x50, ( byte ) 0x77, ( byte ) 0xA4,
297                     ( byte ) 0x15, ( byte ) 0x58, ( byte ) 0xCA, ( byte ) 0xE7, ( byte ) 0x36, ( byte ) 0x50,
298                     ( byte ) 0x1F, ( byte ) 0xA7, ( byte ) 0xA4, ( byte ) 0x85, ( byte ) 0x82, ( byte ) 0x05,
299                     ( byte ) 0xF6, ( byte ) 0x8F, ( byte ) 0x67, ( byte ) 0xA2, ( byte ) 0xB5, ( byte ) 0xEA,
300                     ( byte ) 0x0E, ( byte ) 0xBF };
301             assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
302         }
303     }
304 
305 
306     /**
307      * Tests that key derivation can be performed by the factory for multiple encryption types.
308      */
309     public void testKerberosKeyFactory()
310     {
311         if ( VendorHelper.isIbm() )
312         {
313             return;
314         }
315 
316         String principalName = "hnelson@EXAMPLE.COM";
317         String passPhrase = "secret";
318 
319         Map<EncryptionType, EncryptionKey> map = KerberosKeyFactory.getKerberosKeys( principalName, passPhrase );
320 
321         EncryptionKey kerberosKey = map.get( EncryptionType.DES_CBC_MD5 );
322 
323         EncryptionType keyType = kerberosKey.getKeyType();
324         int keyLength = kerberosKey.getKeyValue().length;
325         byte[] keyBytes = kerberosKey.getKeyValue();
326 
327         assertEquals( keyType, EncryptionType.DES_CBC_MD5 );
328         assertEquals( keyLength, 8 );
329         byte[] expectedBytes = new byte[]
330             { ( byte ) 0xF4, ( byte ) 0xA7, ( byte ) 0x13, ( byte ) 0x64, ( byte ) 0x8A, ( byte ) 0x61, ( byte ) 0xCE,
331                 ( byte ) 0x5B };
332         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
333 
334         kerberosKey = map.get( EncryptionType.DES3_CBC_SHA1_KD );
335         keyType = kerberosKey.getKeyType();
336         keyLength = kerberosKey.getKeyValue().length;
337         keyBytes = kerberosKey.getKeyValue();
338 
339         assertEquals( keyType, EncryptionType.DES3_CBC_SHA1_KD );
340         assertEquals( keyLength, 24 );
341         expectedBytes = new byte[]
342             { ( byte ) 0x57, ( byte ) 0x07, ( byte ) 0xCE, ( byte ) 0x29, ( byte ) 0x52, ( byte ) 0x92, ( byte ) 0x2C,
343                 ( byte ) 0x1C, ( byte ) 0x8C, ( byte ) 0xBF, ( byte ) 0x43, ( byte ) 0xC2, ( byte ) 0x3D,
344                 ( byte ) 0x8F, ( byte ) 0x8C, ( byte ) 0x5E, ( byte ) 0x9E, ( byte ) 0x8C, ( byte ) 0xF7,
345                 ( byte ) 0x5D, ( byte ) 0x3E, ( byte ) 0x4A, ( byte ) 0x5E, ( byte ) 0x25 };
346         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
347 
348         kerberosKey = map.get( EncryptionType.RC4_HMAC );
349         keyType = kerberosKey.getKeyType();
350         keyLength = kerberosKey.getKeyValue().length;
351         keyBytes = kerberosKey.getKeyValue();
352 
353         assertEquals( keyType, EncryptionType.RC4_HMAC );
354         assertEquals( keyLength, 16 );
355         expectedBytes = new byte[]
356             { ( byte ) 0x87, ( byte ) 0x8D, ( byte ) 0x80, ( byte ) 0x14, ( byte ) 0x60, ( byte ) 0x6C, ( byte ) 0xDA,
357                 ( byte ) 0x29, ( byte ) 0x67, ( byte ) 0x7A, ( byte ) 0x44, ( byte ) 0xEF, ( byte ) 0xA1,
358                 ( byte ) 0x35, ( byte ) 0x3F, ( byte ) 0xC7 };
359         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
360 
361         kerberosKey = map.get( EncryptionType.AES128_CTS_HMAC_SHA1_96 );
362         keyType = kerberosKey.getKeyType();
363         keyLength = kerberosKey.getKeyValue().length;
364         keyBytes = kerberosKey.getKeyValue();
365 
366         assertEquals( keyType, EncryptionType.AES128_CTS_HMAC_SHA1_96 );
367         assertEquals( keyLength, 16 );
368         expectedBytes = new byte[]
369             { ( byte ) 0xAD, ( byte ) 0x21, ( byte ) 0x4B, ( byte ) 0x38, ( byte ) 0xB6, ( byte ) 0x9D, ( byte ) 0xFC,
370                 ( byte ) 0xCA, ( byte ) 0xAC, ( byte ) 0xF1, ( byte ) 0x5F, ( byte ) 0x34, ( byte ) 0x6D,
371                 ( byte ) 0x41, ( byte ) 0x7B, ( byte ) 0x90 };
372         assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
373 
374         kerberosKey = map.get( EncryptionType.AES256_CTS_HMAC_SHA1_96 );
375 
376         if ( kerberosKey != null )
377         {
378             keyType = kerberosKey.getKeyType();
379             keyLength = kerberosKey.getKeyValue().length;
380             keyBytes = kerberosKey.getKeyValue();
381 
382             assertEquals( keyType, EncryptionType.AES256_CTS_HMAC_SHA1_96 );
383             assertEquals( keyLength, 32 );
384             expectedBytes = new byte[]
385                 { ( byte ) 0x3D, ( byte ) 0x33, ( byte ) 0x31, ( byte ) 0x8F, ( byte ) 0xBE, ( byte ) 0x47,
386                     ( byte ) 0xE5, ( byte ) 0x2A, ( byte ) 0x21, ( byte ) 0x50, ( byte ) 0x77, ( byte ) 0xA4,
387                     ( byte ) 0x15, ( byte ) 0x58, ( byte ) 0xCA, ( byte ) 0xE7, ( byte ) 0x36, ( byte ) 0x50,
388                     ( byte ) 0x1F, ( byte ) 0xA7, ( byte ) 0xA4, ( byte ) 0x85, ( byte ) 0x82, ( byte ) 0x05,
389                     ( byte ) 0xF6, ( byte ) 0x8F, ( byte ) 0x67, ( byte ) 0xA2, ( byte ) 0xB5, ( byte ) 0xEA,
390                     ( byte ) 0x0E, ( byte ) 0xBF };
391             assertTrue( Arrays.equals( expectedBytes, keyBytes ) );
392         }
393     }
394 }