View Javadoc

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.SecureRandom;
24  
25  import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
26  import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
27  import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
28  
29  
30  /**
31   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
32   * @version $Rev: 540371 $, $Date: 2007-05-22 02:00:43 +0200 (Di, 22 Mai 2007) $
33   */
34  public abstract class EncryptionEngine
35  {
36      private static final SecureRandom random = new SecureRandom();
37  
38  
39      protected abstract byte[] getDecryptedData( EncryptionKey key, EncryptedData data, KeyUsage usage )
40          throws KerberosException;
41  
42  
43      protected abstract EncryptedData getEncryptedData( EncryptionKey key, byte[] plainText, KeyUsage usage );
44  
45  
46      protected abstract EncryptionType getEncryptionType();
47  
48  
49      protected abstract int getConfounderLength();
50  
51  
52      protected abstract int getChecksumLength();
53  
54  
55      protected abstract byte[] encrypt( byte[] plainText, byte[] key );
56  
57  
58      protected abstract byte[] decrypt( byte[] cipherText, byte[] key );
59  
60  
61      protected abstract byte[] calculateIntegrity( byte[] plainText, byte[] key, KeyUsage usage );
62  
63  
64      protected byte[] deriveRandom( byte[] key, byte[] usage, int n, int k )
65      {
66          byte[] nFoldedUsage = NFold.nFold( n, usage );
67  
68          int kBytes = k / 8;
69          byte[] result = new byte[kBytes];
70  
71          byte[] fillingKey = encrypt( nFoldedUsage, key );
72  
73          int pos = 0;
74  
75          for ( int i = 0; i < kBytes; i++ )
76          {
77              if ( pos < fillingKey.length )
78              {
79                  result[i] = fillingKey[pos];
80                  pos++;
81              }
82              else
83              {
84                  fillingKey = encrypt( fillingKey, key );
85                  pos = 0;
86                  result[i] = fillingKey[pos];
87                  pos++;
88              }
89          }
90  
91          return result;
92      }
93  
94  
95      // Encryption
96      protected byte[] getRandomBytes( int size )
97      {
98          byte[] bytes = new byte[size];
99  
100         // SecureRandom.nextBytes is already synchronized
101         random.nextBytes( bytes );
102 
103         return bytes;
104     }
105 
106 
107     // Encryption
108     protected byte[] padString( byte encodedString[] )
109     {
110         int x;
111         if ( encodedString.length < 8 )
112         {
113             x = encodedString.length;
114         }
115         else
116         {
117             x = encodedString.length % 8;
118         }
119 
120         if ( x == 0 )
121         {
122             return encodedString;
123         }
124 
125         byte paddedByteArray[] = new byte[( 8 - x ) + encodedString.length];
126 
127         for ( int y = paddedByteArray.length - 1; y > encodedString.length - 1; y-- )
128         {
129             paddedByteArray[y] = 0;
130         }
131 
132         System.arraycopy( encodedString, 0, paddedByteArray, 0, encodedString.length );
133 
134         return paddedByteArray;
135     }
136 
137 
138     // Encryption
139     protected byte[] concatenateBytes( byte[] array1, byte[] array2 )
140     {
141         byte concatenatedBytes[] = new byte[array1.length + array2.length];
142 
143         for ( int i = 0; i < array1.length; i++ )
144         {
145             concatenatedBytes[i] = array1[i];
146         }
147 
148         for ( int j = array1.length; j < concatenatedBytes.length; j++ )
149         {
150             concatenatedBytes[j] = array2[j - array1.length];
151         }
152 
153         return concatenatedBytes;
154     }
155 
156 
157     // Decryption
158     protected byte[] removeLeadingBytes( byte[] array, int confounder, int checksum )
159     {
160         byte lessBytes[] = new byte[array.length - confounder - checksum];
161 
162         int j = 0;
163         for ( int i = confounder + checksum; i < array.length; i++ )
164         {
165             lessBytes[j] = array[i];
166             j++;
167         }
168 
169         return lessBytes;
170     }
171 
172 
173     protected byte[] removeTrailingBytes( byte[] array, int confounder, int checksum )
174     {
175         byte lessBytes[] = new byte[array.length - confounder - checksum];
176 
177         int j = 0;
178         for ( int i = 0; i < array.length - confounder - checksum; i++ )
179         {
180             lessBytes[j] = array[i];
181             j++;
182         }
183 
184         return lessBytes;
185     }
186 
187 
188     protected int getBit( byte[] data, int pos )
189     {
190         int posByte = pos / 8;
191         int posBit = pos % 8;
192 
193         byte valByte = data[posByte];
194         int valInt = valByte >> ( 8 - ( posBit + 1 ) ) & 0x0001;
195         return valInt;
196     }
197 
198 
199     protected void setBit( byte[] data, int pos, int val )
200     {
201         int posByte = pos / 8;
202         int posBit = pos % 8;
203         byte oldByte = data[posByte];
204         oldByte = ( byte ) ( ( ( 0xFF7F >> posBit ) & oldByte ) & 0x00FF );
205         byte newByte = ( byte ) ( ( val << ( 8 - ( posBit + 1 ) ) ) | oldByte );
206         data[posByte] = newByte;
207     }
208 
209 
210     /**
211      * The "well-known constant" used for the DK function is the key
212      * usage number, expressed as four octets in big-endian order,
213      * followed by one octet indicated below.
214      * 
215      *  Kc = DK(base-key, usage | 0x99);
216      */
217     protected byte[] getUsageKc( KeyUsage usage )
218     {
219         return getUsage( usage.getOrdinal(), ( byte ) 0x99 );
220     }
221 
222 
223     /**
224      * The "well-known constant" used for the DK function is the key
225      * usage number, expressed as four octets in big-endian order,
226      * followed by one octet indicated below.
227      * 
228      *  Ke = DK(base-key, usage | 0xAA);
229      */
230     protected byte[] getUsageKe( KeyUsage usage )
231     {
232         return getUsage( usage.getOrdinal(), ( byte ) 0xAA );
233     }
234 
235 
236     /**
237      * The "well-known constant" used for the DK function is the key
238      * usage number, expressed as four octets in big-endian order,
239      * followed by one octet indicated below.
240      * 
241      *  Ki = DK(base-key, usage | 0x55);
242      */
243     protected byte[] getUsageKi( KeyUsage usage )
244     {
245         return getUsage( usage.getOrdinal(), ( byte ) 0x55 );
246     }
247 
248 
249     private byte[] getUsage( int usage, byte constant )
250     {
251         byte[] bytes = new byte[5];
252         bytes[0] = ( byte ) ( ( usage >>> 24 ) & 0x000000FF );
253         bytes[1] = ( byte ) ( ( usage >> 16 ) & 0x000000FF );
254         bytes[2] = ( byte ) ( ( usage >> 8 ) & 0x000000FF );
255         bytes[3] = ( byte ) ( usage & 0x00FF );
256         bytes[4] = constant;
257 
258         return bytes;
259     }
260 }