1 module dcrypt.blockcipher.rijndael; 2 3 import dcrypt.blockcipher.blockcipher; 4 5 import std.conv:text; 6 7 unittest { 8 9 // test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf 10 string[] test_keys = [ 11 // sp800-38a.pdf 12 x"2b7e151628aed2a6abf7158809cf4f3c", 13 x"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 14 x"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 15 ]; 16 17 string[] test_plaintexts = [ 18 x"6bc1bee22e409f96e93d7e117393172a", 19 x"6bc1bee22e409f96e93d7e117393172a", 20 x"6bc1bee22e409f96e93d7e117393172a", 21 ]; 22 23 string[] test_ciphertexts = [ 24 x"3ad77bb40d7a3660a89ecaf32466ef97", 25 x"bd334f1d6e45f25ff712a214571fa5cc", 26 x"f3eed1bdb5d2a03c064b5a7e3db181f8", 27 ]; 28 29 blockCipherTest(new Rijndael128Engine, test_keys, test_plaintexts, test_ciphertexts); 30 31 // test all block sizes (128, 160, 192, 244, 256) 32 33 string []keys = [ 34 x"01010101010101010101010101010101", 35 x"0101010101010101010101010101010101010101", 36 x"010101010101010101010101010101010101010101010101", 37 x"01010101010101010101010101010101010101010101010101010101", 38 x"0101010101010101010101010101010101010101010101010101010101010101", 39 ]; 40 string[] plains128 = [ 41 x"01010101010101010101010101010101", 42 x"01010101010101010101010101010101", 43 x"01010101010101010101010101010101", 44 x"01010101010101010101010101010101", 45 x"01010101010101010101010101010101", 46 ]; 47 string[] ciphers128 = [ 48 x"5e77e59f8f85943489a24149c75f4ec9", 49 x"9ff7852b6881845bbb93e90261db12de", 50 x"98b895a145ca4e0bf83e693281c1a097", 51 x"168d2318e4fc720c8ee355771574fe58", 52 x"9cac94c6b48561f8ffaaa78616ba4892", 53 ]; 54 55 blockCipherTest(new Rijndael128Engine, keys, plains128, ciphers128); 56 57 string[] plains160 = [ 58 x"0101010101010101010101010101010101010101", 59 x"0101010101010101010101010101010101010101", 60 x"0101010101010101010101010101010101010101", 61 x"0101010101010101010101010101010101010101", 62 x"0101010101010101010101010101010101010101", 63 ]; 64 string[] ciphers160 = [ 65 x"0506b1bf13143240557b6356110a7ef75429535c", 66 x"d69122f92262abfc4ccc79233635e64e4ab8d720", 67 x"88219b6c6546e2d823323206ffb280035d28e615", 68 x"8436e3478b3dbecbf789fede44c1b170e1e6442c", 69 x"fef4057ed10ee8afcbae93d99591b39ba01758bd", 70 ]; 71 72 73 blockCipherTest(new Rijndael160Engine, keys, plains160, ciphers160); 74 75 string[] plains192 = [ 76 x"010101010101010101010101010101010101010101010101", 77 x"010101010101010101010101010101010101010101010101", 78 x"010101010101010101010101010101010101010101010101", 79 x"010101010101010101010101010101010101010101010101", 80 x"010101010101010101010101010101010101010101010101", 81 ]; 82 string[] ciphers192 = [ 83 x"a64984768b532f6cec04216a3f858bb9c4a9f1469caa407f", 84 x"8700141eba45ec66d1b386a5baaea6b9f1c996788e220ebc", 85 x"c5c85078f586df206b6234a147facc9bf015f108f5da1200", 86 x"c12d1c4fa4119aa539f8f637d73b6c27319734e8cf1f499f", 87 x"18c0c2c37c137075749352ebec999f7c52d0e64cf15c3af5", 88 ]; 89 90 blockCipherTest(new Rijndael192Engine, keys, plains192, ciphers192); 91 92 string[] plains224 = [ 93 x"01010101010101010101010101010101010101010101010101010101", 94 x"01010101010101010101010101010101010101010101010101010101", 95 x"01010101010101010101010101010101010101010101010101010101", 96 x"01010101010101010101010101010101010101010101010101010101", 97 x"01010101010101010101010101010101010101010101010101010101", 98 ]; 99 string[] ciphers224 = [ 100 x"4858261dd42a3b457102796e46586aac7d0b37e037a643e76ad27d34", 101 x"4fdc0df3213efaf1fd5d44ca66fd04954d2370cd8beb596626da4d8c", 102 x"69b308803d2ceca37a7ce4832761d4f027371df7451ca7458ca64f85", 103 x"d2ab997da7cb0ccdbaa049715f8c17d3fbecd7e95b40ab814bfad96e", 104 x"e6ff389d1fd554c3cbb3f72e62d76d146a4ab2f5fa24ec9d29a543de", 105 ]; 106 107 blockCipherTest(new Rijndael224Engine, keys, plains224, ciphers224); 108 109 string[] plains256 = [ 110 x"0101010101010101010101010101010101010101010101010101010101010101", 111 x"0101010101010101010101010101010101010101010101010101010101010101", 112 x"0101010101010101010101010101010101010101010101010101010101010101", 113 x"0101010101010101010101010101010101010101010101010101010101010101", 114 x"0101010101010101010101010101010101010101010101010101010101010101", 115 ]; 116 string[] ciphers256 = [ 117 x"3ae837205c68ae9bec81d302601cc069cb0a3d712604a46b170377c981190143", 118 x"e8c91ad4babd2909a575a866229a088ac9d9fad8c9e341a8bfbf647182c4ed7f", 119 x"b4bc9135c8b8d291cd202700ce35bfa3a26b84cbdbff3817cb28b8f03283b608", 120 x"821e0022e8864d31ba140e50c5c52e6c96b8bcb8c6f1173f57e1429ec9b1b43a", 121 x"f6f97c6772f20488e3c0eec5482981b2bd00b15bbdf940069fbf5142ceb39688", 122 ]; 123 124 125 blockCipherTest(new Rijndael256Engine, keys, plains256, ciphers256); 126 } 127 128 alias BlockCipherWrapper!(Rijndael!128) Rijndael128Engine; /// Rijndael with 128 bit blocks 129 alias BlockCipherWrapper!(Rijndael!160) Rijndael160Engine; /// Rijndael with 160 bit blocks 130 alias BlockCipherWrapper!(Rijndael!192) Rijndael192Engine; /// Rijndael with 192 bit blocks 131 alias BlockCipherWrapper!(Rijndael!224) Rijndael224Engine; /// Rijndael with 192 bit blocks 132 alias BlockCipherWrapper!(Rijndael!256) Rijndael256Engine; /// Rijndael with 256 bit blocks 133 134 @safe 135 public struct Rijndael(uint blockBits) { 136 137 static assert(blockBits == 128 || blockBits == 160 || blockBits == 192 || blockBits == 224 || blockBits == 256, "unknown blocksize. Must be 128, 192, 224 or 256."); 138 139 alias ulong[4][MAXROUNDS+1] workingkey_t; 140 141 enum name = text("Rijndael", blockBits); 142 143 public { 144 145 /// Params: 146 /// forEncryption = `false`: decrypt, `true`: encrypt 147 /// userKey = Secret key. 148 /// iv = Not used. 149 void start(bool forEncryption, in ubyte[] userKey, in ubyte[] iv = null) nothrow @nogc 150 { 151 this.forEncryption = forEncryption; 152 workingKey = generateWorkingKey(userKey); 153 initialized = true; 154 } 155 156 uint processBlock(in ubyte[] input, ubyte[] output) nothrow @nogc 157 in { 158 assert(initialized, "Rijndael engine not initialized"); 159 assert(blockSize <= input.length, "input buffer too short"); 160 assert(blockSize <= output.length, "output buffer too short"); 161 } 162 body { 163 if (forEncryption) 164 { 165 unpackBlock(input); 166 encryptBlock(); 167 packBlock(output); 168 } 169 else 170 { 171 unpackBlock(input); 172 decryptBlock(); 173 packBlock(output); 174 } 175 176 return blockSize; 177 } 178 179 void reset() nothrow @nogc 180 { 181 } 182 183 } 184 185 186 // begin of private section 187 private: 188 189 190 /** 191 * multiply two elements of GF(2^m) 192 * needed for MixColumn and InvMixColumn 193 */ 194 @nogc 195 private ubyte mul0x2(int b) pure nothrow 196 { 197 if (b != 0) 198 { 199 return aLogtable[25 + logtable[b]]; 200 } 201 else 202 { 203 return 0; 204 } 205 } 206 207 @nogc 208 private ubyte mul0x3(int b) pure nothrow 209 { 210 if (b != 0) 211 { 212 return aLogtable[1 + logtable[b]]; 213 } 214 else 215 { 216 return 0; 217 } 218 } 219 220 @nogc 221 private ubyte mul0x9(int b) pure nothrow 222 { 223 if (b >= 0) 224 { 225 return aLogtable[199 + b]; 226 } 227 else 228 { 229 return 0; 230 } 231 } 232 233 @nogc 234 private ubyte mul0xb(int b) pure nothrow 235 { 236 if (b >= 0) 237 { 238 return aLogtable[104 + b]; 239 } 240 else 241 { 242 return 0; 243 } 244 } 245 246 @nogc 247 private ubyte mul0xd(int b) pure nothrow 248 { 249 if (b >= 0) 250 { 251 return aLogtable[238 + b]; 252 } 253 else 254 { 255 return 0; 256 } 257 } 258 259 @nogc 260 private ubyte mul0xe(int b) pure nothrow 261 { 262 if (b >= 0) 263 { 264 return aLogtable[223 + b]; 265 } 266 else 267 { 268 return 0; 269 } 270 } 271 272 /** 273 * xor corresponding text input and round key input bytes 274 */ 275 @nogc 276 private void KeyAddition(in ulong[] rk) pure nothrow 277 { 278 A0 ^= rk[0]; 279 A1 ^= rk[1]; 280 A2 ^= rk[2]; 281 A3 ^= rk[3]; 282 } 283 284 @nogc 285 private ulong shift(ulong r, uint shift) pure nothrow 286 { 287 return (((r >>> shift) | (r << (BC - shift)))) & BC_MASK; 288 } 289 290 /** 291 * Row 0 remains unchanged 292 * The other three rows are shifted a variable amount 293 */ 294 @nogc 295 private void ShiftRow(in ubyte[] shiftsSC) pure nothrow 296 { 297 A1 = shift(A1, shiftsSC[1]); 298 A2 = shift(A2, shiftsSC[2]); 299 A3 = shift(A3, shiftsSC[3]); 300 } 301 302 @nogc 303 private ulong applyS(ulong r, in ubyte[] box) pure nothrow 304 { 305 ulong res = 0; 306 307 for (uint j = 0; j < BC; j += 8) 308 { 309 res |= cast(ulong)(box[((r >> j) & 0xff)] & 0xff) << j; 310 } 311 312 return res; 313 } 314 315 /** 316 * Replace every byte of the input by the byte at that place 317 * in the nonlinear S-box 318 */ 319 @nogc 320 private void Substitution(in ubyte[] box) pure nothrow 321 { 322 A0 = applyS(A0, box); 323 A1 = applyS(A1, box); 324 A2 = applyS(A2, box); 325 A3 = applyS(A3, box); 326 } 327 328 /** 329 * Mix the bytes of every column in a linear way 330 */ 331 @nogc 332 private void MixColumn() pure nothrow 333 { 334 ulong r0, r1, r2, r3; 335 336 r0 = r1 = r2 = r3 = 0; 337 338 for (uint j = 0; j < BC; j += 8) 339 { 340 uint a0 = cast(uint)((A0 >> j) & 0xff); 341 uint a1 = cast(uint)((A1 >> j) & 0xff); 342 uint a2 = cast(uint)((A2 >> j) & 0xff); 343 uint a3 = cast(uint)((A3 >> j) & 0xff); 344 345 r0 |= cast(ulong)((mul0x2(a0) ^ mul0x3(a1) ^ a2 ^ a3) & 0xff) << j; 346 347 r1 |= cast(ulong)((mul0x2(a1) ^ mul0x3(a2) ^ a3 ^ a0) & 0xff) << j; 348 349 r2 |= cast(ulong)((mul0x2(a2) ^ mul0x3(a3) ^ a0 ^ a1) & 0xff) << j; 350 351 r3 |= cast(ulong)((mul0x2(a3) ^ mul0x3(a0) ^ a1 ^ a2) & 0xff) << j; 352 } 353 354 A0 = r0; 355 A1 = r1; 356 A2 = r2; 357 A3 = r3; 358 } 359 360 /** 361 * Mix the bytes of every column in a linear way 362 * This is the opposite operation of Mixcolumn 363 */ 364 @nogc 365 private void InvMixColumn() pure nothrow 366 { 367 ulong r0, r1, r2, r3; 368 369 r0 = r1 = r2 = r3 = 0; 370 for (uint j = 0; j < BC; j += 8) 371 { 372 uint a0 = cast(uint)((A0 >> j) & 0xff); 373 uint a1 = cast(uint)((A1 >> j) & 0xff); 374 uint a2 = cast(uint)((A2 >> j) & 0xff); 375 uint a3 = cast(uint)((A3 >> j) & 0xff); 376 377 // 378 // pre-lookup the log table 379 // 380 a0 = (a0 != 0) ? (logtable[a0 & 0xff]) : -1; 381 a1 = (a1 != 0) ? (logtable[a1 & 0xff]) : -1; 382 a2 = (a2 != 0) ? (logtable[a2 & 0xff]) : -1; 383 a3 = (a3 != 0) ? (logtable[a3 & 0xff]) : -1; 384 385 r0 |= cast(ulong)((mul0xe(a0) ^ mul0xb(a1) ^ mul0xd(a2) ^ mul0x9(a3)) & 0xff) << j; 386 387 r1 |= cast(ulong)((mul0xe(a1) ^ mul0xb(a2) ^ mul0xd(a3) ^ mul0x9(a0)) & 0xff) << j; 388 389 r2 |= cast(ulong)((mul0xe(a2) ^ mul0xb(a3) ^ mul0xd(a0) ^ mul0x9(a1)) & 0xff) << j; 390 391 r3 |= cast(ulong)((mul0xe(a3) ^ mul0xb(a0) ^ mul0xd(a1) ^ mul0x9(a2)) & 0xff) << j; 392 } 393 394 A0 = r0; 395 A1 = r1; 396 A2 = r2; 397 A3 = r3; 398 } 399 400 /** 401 * Calculate the necessary round keys 402 * The number of calculations depends on keyBits and blockBits 403 */ 404 private workingkey_t generateWorkingKey(in ubyte[] key) pure nothrow @nogc 405 { 406 uint KC; 407 uint t, rconpointer = 0; 408 uint keyBits = cast(uint)(key.length * 8); 409 ubyte[MAXKC][4] tk; 410 workingkey_t W; 411 412 switch (keyBits) 413 { 414 case 128: 415 KC = 4; 416 break; 417 case 160: 418 KC = 5; 419 break; 420 case 192: 421 KC = 6; 422 break; 423 case 224: 424 KC = 7; 425 break; 426 case 256: 427 KC = 8; 428 break; 429 default : 430 assert(false, "Key length not 128/160/192/224/256 bits."); 431 } 432 433 if (keyBits >= blockBits) 434 { 435 ROUNDS = KC + 6; 436 } 437 else 438 { 439 ROUNDS = (BC / 8) + 6; 440 } 441 442 // 443 // copy the key into the processing area 444 // 445 uint index = 0; 446 447 for (uint i = 0; i < key.length; i++) 448 { 449 tk[i % 4][i / 4] = key[index++]; 450 } 451 452 t = 0; 453 454 // 455 // copy values into round key array 456 // 457 for (uint j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++) 458 { 459 for (uint i = 0; i < 4; i++) 460 { 461 W[t / (BC / 8)][i] |= cast(ulong)(tk[i][j] & 0xff) << ((t * 8) % BC); 462 } 463 } 464 465 // 466 // while not enough round key material calculated 467 // calculate new values 468 // 469 while (t < (ROUNDS+1)*(BC/8)) 470 { 471 for (uint i = 0; i < 4; i++) 472 { 473 tk[i][0] ^= S[tk[(i+1)%4][KC-1] & 0xff]; 474 } 475 tk[0][0] ^= rcon[rconpointer++]; 476 477 if (KC <= 6) 478 { 479 for (uint j = 1; j < KC; j++) 480 { 481 for (uint i = 0; i < 4; i++) 482 { 483 tk[i][j] ^= tk[i][j-1]; 484 } 485 } 486 } 487 else 488 { 489 for (uint j = 1; j < 4; j++) 490 { 491 for (uint i = 0; i < 4; i++) 492 { 493 tk[i][j] ^= tk[i][j-1]; 494 } 495 } 496 for (uint i = 0; i < 4; i++) 497 { 498 tk[i][4] ^= S[tk[i][3] & 0xff]; 499 } 500 for (uint j = 5; j < KC; j++) 501 { 502 for (uint i = 0; i < 4; i++) 503 { 504 tk[i][j] ^= tk[i][j-1]; 505 } 506 } 507 } 508 509 // 510 // copy values into round key array 511 // 512 for (uint j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++) 513 { 514 for (uint i = 0; i < 4; i++) 515 { 516 W[t / (BC/8)][i] |= cast(ulong)(tk[i][j] & 0xff) << ((t * 8) % (BC)); 517 } 518 } 519 } 520 521 return W; 522 } 523 524 private: 525 526 uint ROUNDS; 527 workingkey_t workingKey; 528 ulong A0, A1, A2, A3; 529 bool forEncryption; 530 bool initialized = false; 531 532 533 // set constants according to the block size 534 static if(blockBits == 128) { 535 enum BC = 32; 536 enum BC_MASK = 0xffffffffL; 537 immutable (ubyte)[] shifts0SC = [ 0, 8, 16, 24 ]; 538 immutable (ubyte)[] shifts1SC = [ 0, 24, 16, 8 ]; 539 } else 540 static if(blockBits == 160) { 541 enum BC = 40; 542 enum BC_MASK = 0xffffffffffL; 543 immutable (ubyte)[] shifts0SC = [ 0, 8, 16, 24 ]; 544 immutable (ubyte)[] shifts1SC = [ 0, 32, 24, 16 ]; 545 } else 546 static if(blockBits == 192) { 547 enum BC = 48; 548 enum BC_MASK = 0xffffffffffffL; 549 immutable (ubyte)[] shifts0SC = [ 0, 8, 16, 24 ]; 550 immutable (ubyte)[] shifts1SC = [ 0, 40, 32, 24 ]; 551 } else 552 static if(blockBits == 224) { 553 enum BC = 56; 554 enum BC_MASK = 0xffffffffffffffL; 555 immutable (ubyte)[] shifts0SC = [ 0, 8, 16, 32 ]; 556 immutable (ubyte)[] shifts1SC = [ 0, 48, 40, 24 ]; 557 } else 558 static if(blockBits == 256) { 559 enum BC = 64; 560 enum BC_MASK = 0xffffffffffffffffL; 561 immutable (ubyte)[] shifts0SC = [ 0, 8, 24, 32 ]; 562 immutable (ubyte)[] shifts1SC = [ 0, 56, 40, 32 ]; 563 } else { 564 static assert(false, "invalid block size"); 565 } 566 public enum blockSize = BC/2; 567 568 private nothrow @nogc: 569 570 void unpackBlock(in ubyte[] bytes) 571 { 572 uint index = 0; 573 574 A0 = cast(ulong)(bytes[index++] & 0xff); 575 A1 = cast(ulong)(bytes[index++] & 0xff); 576 A2 = cast(ulong)(bytes[index++] & 0xff); 577 A3 = cast(ulong)(bytes[index++] & 0xff); 578 579 for (uint j = 8; j != BC; j += 8) 580 { 581 A0 |= cast(ulong)(bytes[index++] & 0xff) << j; 582 A1 |= cast(ulong)(bytes[index++] & 0xff) << j; 583 A2 |= cast(ulong)(bytes[index++] & 0xff) << j; 584 A3 |= cast(ulong)(bytes[index++] & 0xff) << j; 585 } 586 } 587 588 @nogc 589 void packBlock(ubyte[] bytes) 590 { 591 uint index = 0; 592 593 for (uint j = 0; j != BC; j += 8) 594 { 595 bytes[index++] = cast(ubyte)(A0 >> j); 596 bytes[index++] = cast(ubyte)(A1 >> j); 597 bytes[index++] = cast(ubyte)(A2 >> j); 598 bytes[index++] = cast(ubyte)(A3 >> j); 599 } 600 } 601 602 void encryptBlock() 603 { 604 alias workingKey rk; 605 uint r; 606 607 // 608 // begin with a key addition 609 // 610 KeyAddition(rk[0]); 611 612 // 613 // ROUNDS-1 ordinary rounds 614 // 615 for (r = 1; r < ROUNDS; r++) 616 { 617 Substitution(S); 618 ShiftRow(shifts0SC); 619 MixColumn(); 620 KeyAddition(rk[r]); 621 } 622 623 // 624 // Last round is special: there is no MixColumn 625 // 626 Substitution(S); 627 ShiftRow(shifts0SC); 628 KeyAddition(rk[ROUNDS]); 629 } 630 631 void decryptBlock() 632 { 633 alias workingKey rk; 634 uint r; 635 636 // To decrypt: apply the inverse operations of the encrypt routine, 637 // in opposite order 638 // 639 // (KeyAddition is an involution: it 's equal to its inverse) 640 // (the inverse of Substitution with table S is Substitution with the inverse table of S) 641 // (the inverse of Shiftrow is Shiftrow over a suitable distance) 642 // 643 644 // First the special round: 645 // without InvMixColumn 646 // with extra KeyAddition 647 // 648 KeyAddition(rk[ROUNDS]); 649 Substitution(Si); 650 ShiftRow(shifts1SC); 651 652 // 653 // ROUNDS-1 ordinary rounds 654 // 655 for (r = ROUNDS-1; r > 0; r--) 656 { 657 KeyAddition(rk[r]); 658 InvMixColumn(); 659 Substitution(Si); 660 ShiftRow(shifts1SC); 661 } 662 663 // 664 // End with the extra key addition 665 // 666 KeyAddition(rk[0]); 667 } 668 669 // tables & constants 670 671 static immutable: 672 673 enum MAXROUNDS = 14; 674 675 enum MAXKC = (256/4); 676 677 ubyte[256] logtable = [ 678 0, 0, 25, 1, 50, 2, 26, 198, 679 75, 199, 27, 104, 51, 238, 223, 3, 680 100, 4, 224, 14, 52, 141, 129, 239, 681 76, 113, 8, 200, 248, 105, 28, 193, 682 125, 194, 29, 181, 249, 185, 39, 106, 683 77, 228, 166, 114, 154, 201, 9, 120, 684 101, 47, 138, 5, 33, 15, 225, 36, 685 18, 240, 130, 69, 53, 147, 218, 142, 686 150, 143, 219, 189, 54, 208, 206, 148, 687 19, 92, 210, 241, 64, 70, 131, 56, 688 102, 221, 253, 48, 191, 6, 139, 98, 689 179, 37, 226, 152, 34, 136, 145, 16, 690 126, 110, 72, 195, 163, 182, 30, 66, 691 58, 107, 40, 84, 250, 133, 61, 186, 692 43, 121, 10, 21, 155, 159, 94, 202, 693 78, 212, 172, 229, 243, 115, 167, 87, 694 175, 88, 168, 80, 244, 234, 214, 116, 695 79, 174, 233, 213, 231, 230, 173, 232, 696 44, 215, 117, 122, 235, 22, 11, 245, 697 89, 203, 95, 176, 156, 169, 81, 160, 698 127, 12, 246, 111, 23, 196, 73, 236, 699 216, 67, 31, 45, 164, 118, 123, 183, 700 204, 187, 62, 90, 251, 96, 177, 134, 701 59, 82, 161, 108, 170, 85, 41, 157, 702 151, 178, 135, 144, 97, 190, 220, 252, 703 188, 149, 207, 205, 55, 63, 91, 209, 704 83, 57, 132, 60, 65, 162, 109, 71, 705 20, 42, 158, 93, 86, 242, 211, 171, 706 68, 17, 146, 217, 35, 32, 46, 137, 707 180, 124, 184, 38, 119, 153, 227, 165, 708 103, 74, 237, 222, 197, 49, 254, 24, 709 13, 99, 140, 128, 192, 247, 112, 7 710 ]; 711 712 ubyte[511] aLogtable = [ 713 0, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 714 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 715 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, 716 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, 717 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 718 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 719 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, 720 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, 721 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 722 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 723 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 724 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 725 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 726 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 727 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 728 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, 729 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 730 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 731 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, 732 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, 733 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 734 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 735 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, 736 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, 737 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 738 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 739 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 740 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 741 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 742 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 743 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 744 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, 745 ]; 746 747 ubyte[256] S = [ 748 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 749 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 750 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 751 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 752 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 753 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 754 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 755 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 756 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 757 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 758 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 759 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 760 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 761 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 762 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 763 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22, 764 ]; 765 766 ubyte[256] Si = [ 767 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 768 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 769 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 770 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 771 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 772 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 773 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 774 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 775 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 776 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 777 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 778 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 779 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 780 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 781 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 782 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, 783 ]; 784 785 ubyte[30] rcon = [ 786 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ]; 787 788 }