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.security.InvalidKeyException;
24  import java.util.Arrays;
25  
26  import javax.crypto.spec.DESKeySpec;
27  
28  import junit.framework.TestCase;
29  
30  
31  /**
32   * Test cases for the DES string-to-key function as described in RFC 3961,
33   * "Encryption and Checksum Specifications for Kerberos 5."
34   * 
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   * @version $Rev$, $Date$
37   */
38  public class DesStringToKeyTest extends TestCase
39  {
40      private byte[] fanFold1 =
41          { ( byte ) 0xC0, ( byte ) 0x1E, ( byte ) 0x38, ( byte ) 0x68, ( byte ) 0x8A, ( byte ) 0xC8, ( byte ) 0x6C,
42              ( byte ) 0x2E };
43      private byte[] intermediateKey1 =
44          { ( byte ) 0xC1, ( byte ) 0x1F, ( byte ) 0x38, ( byte ) 0x68, ( byte ) 0x8A, ( byte ) 0xC8, ( byte ) 0x6D,
45              ( byte ) 0x2F };
46      private byte[] desKey1 =
47          { ( byte ) 0xCB, ( byte ) 0xC2, ( byte ) 0x2F, ( byte ) 0xAE, ( byte ) 0x23, ( byte ) 0x52, ( byte ) 0x98,
48              ( byte ) 0xE3 };
49  
50      private byte[] fanFold2 =
51          { ( byte ) 0xA0, ( byte ) 0x28, ( byte ) 0x94, ( byte ) 0x4E, ( byte ) 0xE6, ( byte ) 0x3C, ( byte ) 0x04,
52              ( byte ) 0x16 };
53      private byte[] intermediateKey2 =
54          { ( byte ) 0xA1, ( byte ) 0x29, ( byte ) 0x94, ( byte ) 0x4F, ( byte ) 0xE6, ( byte ) 0x3D, ( byte ) 0x04,
55              ( byte ) 0x16 };
56      private byte[] desKey2 =
57          { ( byte ) 0xDF, ( byte ) 0x3D, ( byte ) 0x32, ( byte ) 0xA7, ( byte ) 0x4F, ( byte ) 0xD9, ( byte ) 0x2A,
58              ( byte ) 0x01 };
59  
60      private DesStringToKey stringToKey = new DesStringToKey();
61  
62  
63      /**
64       * Tests DES StringToKey test vector 1 from RFC 3961.
65       */
66      public void testDesStringToKeyVector1()
67      {
68          byte[] key = stringToKey.getKey( "password", "ATHENA.MIT.EDU", "raeburn" );
69  
70          assertTrue( "Key match", Arrays.equals( desKey1, key ) );
71      }
72  
73  
74      /**
75       * Tests DES StringToKey test vector 2 from RFC 3961.
76       */
77      public void testDesStringToKeyVector2()
78      {
79          byte[] key = stringToKey.getKey( "potatoe", "WHITEHOUSE.GOV", "danny" );
80  
81          assertTrue( "Key match", Arrays.equals( desKey2, key ) );
82      }
83  
84  
85      /**
86       * Tests DES StringToKey test vector 1 from RFC 3961 with intermediate step checks.
87       *
88       * @throws InvalidKeyException
89       */
90      public void testIntermediateDesStringToKeyVector1() throws InvalidKeyException
91      {
92          String passPhrase = "passwordATHENA.MIT.EDUraeburn";
93  
94          byte[] encodedByteArray = stringToKey.characterEncodeString( passPhrase );
95          byte[] paddedByteArray = stringToKey.padString( encodedByteArray );
96          byte[] fanFold = stringToKey.fanFold( paddedByteArray );
97  
98          assertTrue( "Key match", Arrays.equals( fanFold1, fanFold ) );
99  
100         fanFold = stringToKey.setParity( fanFold );
101         assertTrue( "Key match", Arrays.equals( intermediateKey1, fanFold ) );
102 
103         byte[] secretKey = getDesKey( paddedByteArray, fanFold );
104         assertTrue( "Key match", Arrays.equals( desKey1, secretKey ) );
105     }
106 
107 
108     /**
109      * Tests DES StringToKey test vector 2 from RFC 3961 with intermediate step checks.
110      * 
111      * @throws InvalidKeyException
112      */
113     public void testIntermediateDesStringToKeyVector2() throws InvalidKeyException
114     {
115         String passPhrase = "potatoeWHITEHOUSE.GOVdanny";
116 
117         byte[] encodedByteArray = stringToKey.characterEncodeString( passPhrase );
118         byte[] paddedByteArray = stringToKey.padString( encodedByteArray );
119         byte[] fanFold = stringToKey.fanFold( paddedByteArray );
120 
121         assertTrue( "Key match", Arrays.equals( fanFold2, fanFold ) );
122 
123         fanFold = stringToKey.setParity( fanFold );
124         assertTrue( "Key match", Arrays.equals( intermediateKey2, fanFold ) );
125 
126         byte[] secretKey = getDesKey( paddedByteArray, fanFold );
127         assertTrue( "Key match", Arrays.equals( desKey2, secretKey ) );
128     }
129 
130 
131     /**
132      * Test harness method for checking intermediate key state, which is not
133      * exposed from {@link DesStringToKey}.
134      *
135      * @param paddedByteArray The input passphrase.
136      * @param intermediateKey The intermediate key generated by fan-folding and parity-adjustment.
137      * @return The final DES key.
138      * @throws InvalidKeyException
139      */
140     private byte[] getDesKey( byte[] paddedByteArray, byte[] intermediateKey ) throws InvalidKeyException
141     {
142         if ( DESKeySpec.isWeak( intermediateKey, 0 ) )
143         {
144             intermediateKey = stringToKey.getStrongKey( intermediateKey );
145         }
146 
147         byte[] secretKey = stringToKey.calculateChecksum( paddedByteArray, intermediateKey );
148 
149         secretKey = stringToKey.setParity( secretKey );
150 
151         if ( DESKeySpec.isWeak( secretKey, 0 ) )
152         {
153             secretKey = stringToKey.getStrongKey( secretKey );
154         }
155 
156         return secretKey;
157     }
158 }