KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > Acme > Crypto > AesCipher


1 // AesCipher - the AES encryption method
2
//
3
// Before being selected as the Advanced Encryption Standard this was
4
// known as Rijndael, and was designed by Joan Daemen and Vincent Rijmen.
5
// Most of the algorithm code is copyright by them. A few modifications
6
// to the algorithm, and the surrounding glue, are:
7
//
8
// Copyright (C) 1996,2000 by Jef Poskanzer <jef@acme.com>.
9
// All rights reserved.
10
//
11
// Redistribution and use in source and binary forms, with or without
12
// modification, are permitted provided that the following conditions
13
// are met:
14
// 1. Redistributions of source code must retain the above copyright
15
// notice, this list of conditions and the following disclaimer.
16
// 2. Redistributions in binary form must reproduce the above copyright
17
// notice, this list of conditions and the following disclaimer in the
18
// documentation and/or other materials provided with the distribution.
19
//
20
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
// SUCH DAMAGE.
31
//
32
// Visit the ACME Labs Java page for up-to-date versions of this and other
33
// fine Java utilities: http://www.acme.com/java/
34

35 package Acme.Crypto;
36
37 import java.io.*;
38
39 /// The AES encryption method.
40
// <P>
41
// Before being selected as the Advanced Encryption Standard this was
42
// known as Rijndael, and was designed by Joan Daemen and Vincent Rijmen.
43
// <P>
44
// <A HREF="../../../resources/classes/Acme/Crypto/AesCipher.java">Fetch the software.</A><BR>
45
// <A HREF="../../../resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
46
// <P>
47
// @see EncryptedOutputStream
48
// @see EncryptedInputStream
49

50 public class AesCipher extends BlockCipher
51     {
52
53     // Constants, variables, and auxillary routines.
54

55     // Key size in bytes. Valid values are 16, 24, and 32.
56
public static final int KEY_SIZE = 16;
57
58     // Block size in bytes. Valid values are 16, 24, and 32.
59
public static final int BLOCK_SIZE = 16;
60
61     private static final int[] alog = new int[256];
62     private static final int[] log = new int[256];
63
64     private static final byte[] S = new byte[256];
65     private static final byte[] Si = new byte[256];
66     private static final int[] T1 = new int[256];
67     private static final int[] T2 = new int[256];
68     private static final int[] T3 = new int[256];
69     private static final int[] T4 = new int[256];
70     private static final int[] T5 = new int[256];
71     private static final int[] T6 = new int[256];
72     private static final int[] T7 = new int[256];
73     private static final int[] T8 = new int[256];
74     private static final int[] U1 = new int[256];
75     private static final int[] U2 = new int[256];
76     private static final int[] U3 = new int[256];
77     private static final int[] U4 = new int[256];
78     private static final byte[] rcon = new byte[30];
79
80     static private final int[][][] shifts = new int[][][] {
81         { { 0, 0 }, { 1, 3 }, { 2, 2 }, { 3, 1 } },
82         { { 0, 0 }, { 1, 5 }, { 2, 4 }, { 3, 3 } },
83         { { 0, 0 }, { 1, 7 }, { 3, 5 }, { 4, 4 } }
84     };
85
86     private static final char[] HEX_DIGITS = {
87         '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
88     };
89
90     // Static initializer - to intialise S-boxes and T-boxes
91
static
92     {
93         int ROOT = 0x11B;
94         int i, j = 0;
95
96         // Produce log and alog tables, needed for multiplying in the
97
// field GF(2^m) (generator = 3).
98
alog[0] = 1;
99         for ( i = 1; i < 256; ++i )
100         {
101             j = ( alog[i - 1] << 1 ) ^ alog[i - 1];
102             if ( ( j & 0x100 ) != 0 )
103         j ^= ROOT;
104             alog[i] = j;
105         }
106         for ( i = 1; i < 255; ++i )
107         log[alog[i]] = i;
108         byte[][] A = new byte[][] {
109             { 1, 1, 1, 1, 1, 0, 0, 0 },
110             { 0, 1, 1, 1, 1, 1, 0, 0 },
111         { 0, 0, 1, 1, 1, 1, 1, 0 },
112         { 0, 0, 0, 1, 1, 1, 1, 1 },
113         { 1, 0, 0, 0, 1, 1, 1, 1 },
114         { 1, 1, 0, 0, 0, 1, 1, 1 },
115         { 1, 1, 1, 0, 0, 0, 1, 1 },
116         { 1, 1, 1, 1, 0, 0, 0, 1 }
117         };
118         byte[] B = new byte[] { 0, 1, 1, 0, 0, 0, 1, 1 };
119
120         // Substitution box based on F^{-1}(x).
121
int t;
122         byte[][] box = new byte[256][8];
123         box[1][7] = 1;
124         for ( i = 2; i < 256; ++i )
125         {
126             j = alog[255 - log[i]];
127             for ( t = 0; t < 8; ++t )
128                 box[i][t] = (byte) ( ( j >>> ( 7 - t ) ) & 0x01 );
129         }
130         // Affine transform: box[i] <- B + A*box[i].
131
byte[][] cox = new byte[256][8];
132         for ( i = 0; i < 256; ++i )
133             for ( t = 0; t < 8; ++t )
134         {
135                 cox[i][t] = B[t];
136                 for ( j = 0; j < 8; ++j )
137                     cox[i][t] ^= A[t][j] * box[i][j];
138         }
139         // S-boxes and inverse S-boxes.
140
for ( i = 0; i < 256; ++i )
141         {
142             S[i] = (byte) ( cox[i][0] << 7 );
143             for ( t = 1; t < 8; ++t )
144                 S[i] ^= cox[i][t] << ( 7 - t );
145             Si[S[i] & 0xFF] = (byte) i;
146         }
147         // T-boxes.
148
byte[][] G = new byte[][] {
149             { 2, 1, 1, 3 },
150             { 3, 2, 1, 1 },
151             { 1, 3, 2, 1 },
152             { 1, 1, 3, 2 }
153         };
154         byte[][] AA = new byte[4][8];
155         for ( i = 0; i < 4; ++i )
156         {
157             for ( j = 0; j < 4; ++j )
158         AA[i][j] = G[i][j];
159             AA[i][i + 4] = 1;
160         }
161         byte pivot, tmp;
162         byte[][] iG = new byte[4][4];
163         for ( i = 0; i < 4; ++i )
164         {
165             pivot = AA[i][i];
166             if ( pivot == 0 )
167         {
168                 t = i + 1;
169                 while ( ( AA[t][i] == 0 ) && ( t < 4 ) )
170                     ++t;
171                 if ( t == 4 )
172                     throw new RuntimeException JavaDoc("G matrix is not invertible");
173                 else
174             {
175                     for ( j = 0; j < 8; ++j )
176             {
177                         tmp = AA[i][j];
178                         AA[i][j] = AA[t][j];
179                         AA[t][j] = (byte) tmp;
180             }
181                     pivot = AA[i][i];
182             }
183         }
184             for ( j = 0; j < 8; ++j )
185                 if (AA[i][j] != 0)
186                     AA[i][j] = (byte)
187             alog[( 255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF] ) % 255];
188             for ( t = 0; t < 4; ++t )
189                 if ( i != t )
190             {
191                     for ( j = i+1; j < 8; ++j )
192                         AA[t][j] ^= mul( AA[i][j], AA[t][i] );
193                     AA[t][i] = 0;
194             }
195         }
196         for ( i = 0; i < 4; ++i )
197             for ( j = 0; j < 4; ++j )
198         iG[i][j] = AA[i][j + 4];
199
200         int s;
201         for ( t = 0; t < 256; ++t )
202         {
203             s = S[t];
204             T1[t] = mul4( s, G[0]) ;
205             T2[t] = mul4( s, G[1]) ;
206             T3[t] = mul4( s, G[2]) ;
207             T4[t] = mul4( s, G[3]) ;
208
209             s = Si[t];
210             T5[t] = mul4( s, iG[0] );
211             T6[t] = mul4( s, iG[1] );
212             T7[t] = mul4( s, iG[2] );
213             T8[t] = mul4( s, iG[3] );
214
215             U1[t] = mul4( t, iG[0] );
216             U2[t] = mul4( t, iG[1] );
217             U3[t] = mul4( t, iG[2] );
218             U4[t] = mul4( t, iG[3] );
219         }
220         // Round constants.
221
rcon[0] = 1;
222         int r = 1;
223         for ( t = 1; t < 30; )
224         rcon[t++] = (byte)( r = mul( 2, r ) );
225     }
226
227     /// Multiply two elements of GF(2^m).
228
static final int mul( int a, int b )
229     {
230         return ( a != 0 && b != 0 ) ?
231             alog[( log[a & 0xFF] + log[b & 0xFF] ) % 255] :
232             0;
233     }
234
235     /// Convenience method used in generating Transposition boxes.
236
static final int mul4( int a, byte[] b )
237     {
238         if ( a == 0 )
239         return 0;
240         a = log[a & 0xFF];
241         int a0 = ( b[0] != 0 ) ?
242         alog[( a + log[b[0] & 0xFF] ) % 255] & 0xFF : 0;
243         int a1 = ( b[1] != 0 ) ?
244         alog[( a + log[b[1] & 0xFF] ) % 255] & 0xFF : 0;
245         int a2 = ( b[2] != 0 ) ?
246         alog[( a + log[b[2] & 0xFF] ) % 255] & 0xFF : 0;
247         int a3 = ( b[3] != 0 ) ?
248         alog[( a + log[b[3] & 0xFF] ) % 255] & 0xFF : 0;
249         return a0 << 24 | a1 << 16 | a2 << 8 | a3;
250     }
251
252     /// Return the number of rounds for a given Rijndael's key and block sizes.
253
// @param keySize The size of the user key material in bytes.
254
// @param blockSize The desired block size in bytes.
255
// @return The number of rounds for a given Rijndael's key and block sizes.
256
public static int getRounds( int keySize, int blockSize )
257     {
258         switch ( keySize )
259         {
260         case 16:
261             return blockSize == 16 ? 10 : ( blockSize == 24 ? 12 : 14 );
262         case 24:
263             return blockSize != 32 ? 12 : 14;
264         default: // 32 bytes = 256 bits
265
return 14;
266         }
267     }
268
269
270     // Constructors.
271

272     // Constructor, string key.
273
public AesCipher( String JavaDoc keyStr )
274     {
275     super( KEY_SIZE, BLOCK_SIZE );
276     setKey( keyStr );
277     }
278
279     // Constructor, byte-array key.
280
public AesCipher( byte[] key )
281     {
282     super( KEY_SIZE, BLOCK_SIZE );
283     setKey( key );
284     }
285
286
287     // Key routines.
288

289     private int ROUNDS = getRounds( KEY_SIZE, BLOCK_SIZE );
290     private int BC = BLOCK_SIZE / 4;
291     private int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys
292
private int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys
293

294     /// Set the key.
295
public void setKey( byte[] key )
296     {
297         if ( key.length != KEY_SIZE )
298         throw new RuntimeException JavaDoc("Incorrect key length");
299         int ROUND_KEY_COUNT = ( ROUNDS + 1 ) * BC;
300         int KC = KEY_SIZE / 4;
301         int[] tk = new int[KC];
302         int i, j;
303
304         // Copy user material bytes into temporary ints.
305
for ( i = 0, j = 0; i < KC; )
306             tk[i++] = ( key[j++] & 0xFF ) << 24 |
307                       ( key[j++] & 0xFF ) << 16 |
308                       ( key[j++] & 0xFF ) << 8 |
309                       ( key[j++] & 0xFF );
310         // Copy values into round key arrays.
311
int t = 0;
312         for ( j = 0; ( j < KC ) && ( t < ROUND_KEY_COUNT ); ++j, ++t )
313         {
314             Ke[t / BC][t % BC] = tk[j];
315             Kd[ROUNDS - ( t / BC )][t % BC] = tk[j];
316         }
317         int tt, rconpointer = 0;
318         while ( t < ROUND_KEY_COUNT )
319         {
320             // Extrapolate using phi (the round key evolution function).
321
tt = tk[KC - 1];
322             tk[0] ^= ( S[( tt >>> 16 ) & 0xFF] & 0xFF ) << 24 ^
323                      ( S[( tt >>> 8 ) & 0xFF] & 0xFF ) << 16 ^
324                      ( S[ tt & 0xFF] & 0xFF ) << 8 ^
325                      ( S[( tt >>> 24 ) & 0xFF] & 0xFF ) ^
326                      ( rcon[rconpointer++] & 0xFF ) << 24;
327             if ( KC != 8 )
328                 for ( i = 1, j = 0; i < KC; )
329             tk[i++] ^= tk[j++];
330             else
331         {
332                 for ( i = 1, j = 0; i < KC / 2; )
333             tk[i++] ^= tk[j++];
334                 tt = tk[KC / 2 - 1];
335                 tk[KC / 2] ^= ( S[ tt & 0xFF] & 0xFF ) ^
336                               ( S[( tt >>> 8 ) & 0xFF] & 0xFF ) << 8 ^
337                               ( S[( tt >>> 16 ) & 0xFF] & 0xFF ) << 16 ^
338                               ( S[( tt >>> 24 ) & 0xFF] & 0xFF ) << 24;
339                 for ( j = KC / 2, i = j + 1; i < KC; )
340             tk[i++] ^= tk[j++];
341         }
342             // Copy values into round key arrays.
343
for ( j = 0; ( j < KC ) && ( t < ROUND_KEY_COUNT ); ++j, ++t )
344         {
345                 Ke[t / BC][t % BC] = tk[j];
346                 Kd[ROUNDS - ( t / BC )][t % BC] = tk[j];
347         }
348         }
349         for ( int r = 1; r < ROUNDS; ++r ) // inverse MixColumn where needed
350
for ( j = 0; j < BC; ++j )
351         {
352                 tt = Kd[r][j];
353                 Kd[r][j] = U1[( tt >>> 24 ) & 0xFF] ^
354                            U2[( tt >>> 16 ) & 0xFF] ^
355                            U3[( tt >>> 8 ) & 0xFF] ^
356                            U4[ tt & 0xFF];
357         }
358     }
359
360
361     // Block encryption routines.
362

363     private int[] tempInts = new int[8];
364
365
366     /// Encrypt a block.
367
public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
368     {
369         int SC = ( BC == 4 ? 0 : ( BC == 6 ? 1 : 2 ) );
370         int s1 = shifts[SC][1][0];
371         int s2 = shifts[SC][2][0];
372         int s3 = shifts[SC][3][0];
373         int[] a = new int[BC];
374         int[] t = new int[BC]; // temporary work array
375
int i;
376         int tt;
377
378         for ( i = 0; i < BC; ++i ) // plaintext to ints + key
379
t[i] = ( ( clearText[clearOff++] & 0xFF ) << 24 |
380                      ( clearText[clearOff++] & 0xFF ) << 16 |
381                      ( clearText[clearOff++] & 0xFF ) << 8 |
382                      ( clearText[clearOff++] & 0xFF ) ) ^ Ke[0][i];
383     // Apply round transforms.
384
for ( int r = 1; r < ROUNDS; ++r )
385         {
386             for ( i = 0; i < BC; ++i )
387                 a[i] = ( T1[( t[ i ] >>> 24 ) & 0xFF] ^
388                          T2[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
389                          T3[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
390                          T4[ t[( i + s3 ) % BC] & 0xFF] ) ^ Ke[r][i];
391             System.arraycopy( a, 0, t, 0, BC );
392         }
393     // Last round is special.
394
for ( i = 0; i < BC; ++i )
395         {
396             tt = Ke[ROUNDS][i];
397             cipherText[cipherOff++] =
398         (byte) ( S[( t[ i ] >>> 24 ) & 0xFF] ^
399              ( tt >>> 24 ) );
400             cipherText[cipherOff++] =
401         (byte) ( S[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
402              ( tt >>> 16 ) );
403             cipherText[cipherOff++] =
404         (byte) ( S[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
405              ( tt >>> 8 ) );
406             cipherText[cipherOff++] =
407         (byte) ( S[ t[( i + s3 ) % BC] & 0xFF] ^
408                tt );
409         }
410     }
411
412
413     /// Decrypt a block.
414
public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
415     {
416         int SC = ( BC == 4 ? 0 : ( BC == 6 ? 1 : 2 ) );
417         int s1 = shifts[SC][1][1];
418         int s2 = shifts[SC][2][1];
419         int s3 = shifts[SC][3][1];
420         int[] a = new int[BC];
421         int[] t = new int[BC]; // temporary work array
422
int i;
423         int tt;
424
425         for ( i = 0; i < BC; ++i ) // ciphertext to ints + key
426
t[i] = ( ( cipherText[cipherOff++] & 0xFF ) << 24 |
427                      ( cipherText[cipherOff++] & 0xFF ) << 16 |
428                      ( cipherText[cipherOff++] & 0xFF ) << 8 |
429                      ( cipherText[cipherOff++] & 0xFF ) ) ^ Kd[0][i];
430     // Apply round transforms.
431
for ( int r = 1; r < ROUNDS; ++r )
432         {
433             for ( i = 0; i < BC; ++i )
434                 a[i] = ( T5[( t[ i ] >>> 24 ) & 0xFF] ^
435                          T6[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
436                          T7[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
437                          T8[ t[( i + s3 ) % BC] & 0xFF] ) ^ Kd[r][i];
438             System.arraycopy( a, 0, t, 0, BC );
439         }
440     // Last round is special.
441
for ( i = 0; i < BC; ++i )
442         {
443             tt = Kd[ROUNDS][i];
444             clearText[clearOff++] =
445         (byte) ( Si[( t[ i ] >>> 24 ) & 0xFF] ^
446              ( tt >>> 24 ) );
447             clearText[clearOff++] =
448         (byte) ( Si[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
449              ( tt >>> 16 ) );
450             clearText[clearOff++] =
451         (byte) ( Si[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
452              ( tt >>> 8 ) );
453             clearText[clearOff++] =
454         (byte) ( Si[ t[( i + s3 ) % BC] & 0xFF] ^
455                tt );
456         }
457     }
458
459
460     /// Test routine.
461
public static void main( String JavaDoc[] args )
462     {
463     byte[] cipherText = new byte[16];
464     byte[] decipherText = new byte[16];
465
466     BlockCipher aesa = new AesCipher( "0123456789" );
467     byte[] clearText1 = {
468         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
469         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
470         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
471         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
472     System.out.println( "cleartext: " + toStringBlock( clearText1 ) );
473     aesa.encrypt( clearText1, cipherText );
474     System.out.println( "encrypted: " + toStringBlock( cipherText ) );
475     aesa.decrypt( cipherText, decipherText );
476     System.out.println( "decrypted: " + toStringBlock( decipherText ) );
477
478     System.out.println();
479
480     BlockCipher aesb = new AesCipher( "abcdefghijklmnopqrstuvwxyz" );
481     byte[] clearText2 = {
482         (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
483         (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
484         (byte) 0x08, (byte) 0x09, (byte) 0x0a, (byte) 0x0b,
485         (byte) 0x0c, (byte) 0x0d, (byte) 0x0e, (byte) 0x0f };
486     System.out.println( "cleartext: " + toStringBlock( clearText2 ) );
487     aesb.encrypt( clearText2, cipherText );
488     System.out.println( "encrypted: " + toStringBlock( cipherText ) );
489     aesb.decrypt( cipherText, decipherText );
490     System.out.println( "decrypted: " + toStringBlock( decipherText ) );
491     }
492
493     }
494
Popular Tags