1 35 package Acme.Crypto; 36 37 import java.io.*; 38 39 50 public class AesCipher extends BlockCipher 51 { 52 53 55 public static final int KEY_SIZE = 16; 57 58 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 92 { 93 int ROOT = 0x11B; 94 int i, j = 0; 95 96 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 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 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 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 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 ("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 rcon[0] = 1; 222 int r = 1; 223 for ( t = 1; t < 30; ) 224 rcon[t++] = (byte)( r = mul( 2, r ) ); 225 } 226 227 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 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 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: return 14; 266 } 267 } 268 269 270 272 public AesCipher( String keyStr ) 274 { 275 super( KEY_SIZE, BLOCK_SIZE ); 276 setKey( keyStr ); 277 } 278 279 public AesCipher( byte[] key ) 281 { 282 super( KEY_SIZE, BLOCK_SIZE ); 283 setKey( key ); 284 } 285 286 287 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]; private int[][] Kd = new int[ROUNDS + 1][BC]; 294 public void setKey( byte[] key ) 296 { 297 if ( key.length != KEY_SIZE ) 298 throw new RuntimeException ("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 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 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 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 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 ) 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 363 private int[] tempInts = new int[8]; 364 365 366 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]; int i; 376 int tt; 377 378 for ( i = 0; i < BC; ++i ) t[i] = ( ( clearText[clearOff++] & 0xFF ) << 24 | 380 ( clearText[clearOff++] & 0xFF ) << 16 | 381 ( clearText[clearOff++] & 0xFF ) << 8 | 382 ( clearText[clearOff++] & 0xFF ) ) ^ Ke[0][i]; 383 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 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 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]; int i; 423 int tt; 424 425 for ( i = 0; i < BC; ++i ) t[i] = ( ( cipherText[cipherOff++] & 0xFF ) << 24 | 427 ( cipherText[cipherOff++] & 0xFF ) << 16 | 428 ( cipherText[cipherOff++] & 0xFF ) << 8 | 429 ( cipherText[cipherOff++] & 0xFF ) ) ^ Kd[0][i]; 430 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 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 public static void main( String [] 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 |