comparison dcrypt/crypto/ciphers/AES.d @ 27:8b5eaf3c2979

Fixed error in hash message padding reported by Glenn Haecker.
author Thomas Dixon <reikon@reikon.us>
date Sat, 09 May 2009 23:29:20 -0400
parents 176c933827a8
children ad687db713a4
comparison
equal deleted inserted replaced
26:176c933827a8 27:8b5eaf3c2979
17 * Vincent Rijmen and Joan Daemen. 17 * Vincent Rijmen and Joan Daemen.
18 * 18 *
19 * Conforms: FIPS-197 19 * Conforms: FIPS-197
20 * References: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf 20 * References: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
21 */ 21 */
22 class AES : BlockCipher { 22 class AES : BlockCipher
23 private { 23 {
24 private
25 {
24 // Round constants 26 // Round constants
25 static const uint[10] RCON = [ 27 static const uint[10] RCON = [
26 0x01000000u, 0x02000000u, 0x04000000u, 0x08000000u, 0x10000000u, 28 0x01000000u, 0x02000000u, 0x04000000u, 0x08000000u, 0x10000000u,
27 0x20000000u, 0x40000000u, 0x80000000u, 0x1B000000u, 0x36000000u 29 0x20000000u, 0x40000000u, 0x80000000u, 0x1B000000u, 0x36000000u
28 ]; 30 ];
642 uint[] w; // Expanded key 644 uint[] w; // Expanded key
643 ubyte[] workingKey; 645 ubyte[] workingKey;
644 646
645 } // end private 647 } // end private
646 648
647 char[] name() { 649 char[] name()
650 {
648 return "AES"; 651 return "AES";
649 } 652 }
650 653
651 uint rounds() { 654 uint rounds()
655 {
652 if (!_initialized) 656 if (!_initialized)
653 throw new NotInitializedError(name()~": Cipher not initialized."); 657 throw new NotInitializedError(name()~": Cipher not initialized.");
654 return ROUNDS; 658 return ROUNDS;
655 } 659 }
656 660
657 uint blockSize() { 661 uint blockSize()
662 {
658 return BLOCK_SIZE; 663 return BLOCK_SIZE;
659 } 664 }
660 665
661 void init(bool encrypt, CipherParameters params) { 666 void init(bool encrypt, CipherParameters params)
667 {
662 SymmetricKey keyParams = cast(SymmetricKey)params; 668 SymmetricKey keyParams = cast(SymmetricKey)params;
663 if (!keyParams) 669 if (!keyParams)
664 throw new InvalidParameterError( 670 throw new InvalidParameterError(
665 name()~": Invalid parameter passed to init"); 671 name()~": Invalid parameter passed to init");
672
666 _encrypt = encrypt; 673 _encrypt = encrypt;
667 674
668 uint len = keyParams.key.length; 675 uint len = keyParams.key.length;
669 if (len != 16 && len != 24 && len != 32) 676 if (len != 16 && len != 24 && len != 32)
670 throw new InvalidKeyError( 677 throw new InvalidKeyError(
671 name()~": Invalid key length (requires 16, 24 or 32 bytes)"); 678 name()~": Invalid key length (requires 16, 24 or 32 bytes)");
679
672 workingKey = keyParams.key; 680 workingKey = keyParams.key;
673 681
674 setup(workingKey); 682 setup(workingKey);
675 683
676 _initialized = true; 684 _initialized = true;
677 } 685 }
678 686
679 private void encryptBlock() { 687 private void encryptBlock()
688 {
680 uint i = 4, 689 uint i = 4,
681 r = ROUNDS >> 1, 690 r = ROUNDS >> 1,
682 t0, t1, t2, t3; 691 t0, t1, t2, t3;
683 while (--r >= 0) { 692
693 while (--r >= 0)
694 {
684 t0 = w[i++] ^ TE0[s0 >> 24] ^ 695 t0 = w[i++] ^ TE0[s0 >> 24] ^
685 TE1[cast(ubyte)(s1 >> 16)] ^ 696 TE1[cast(ubyte)(s1 >> 16)] ^
686 TE2[cast(ubyte)(s2 >> 8)] ^ 697 TE2[cast(ubyte)(s2 >> 8)] ^
687 TE3[cast(ubyte) s3]; 698 TE3[cast(ubyte) s3];
688 t1 = w[i++] ^ TE0[s1 >> 24] ^ 699 t1 = w[i++] ^ TE0[s1 >> 24] ^
736 (S[cast(ubyte)(t0 >> 16)] << 16) ^ 747 (S[cast(ubyte)(t0 >> 16)] << 16) ^
737 (S[cast(ubyte)(t1 >> 8)] << 8) ^ 748 (S[cast(ubyte)(t1 >> 8)] << 8) ^
738 S[cast(ubyte) t2]; 749 S[cast(ubyte) t2];
739 } 750 }
740 751
741 private void decryptBlock() { 752 private void decryptBlock()
753 {
742 uint i = 4, 754 uint i = 4,
743 r = ROUNDS >> 1, 755 r = ROUNDS >> 1,
744 t0, t1, t2, t3; 756 t0, t1, t2, t3;
745 while (--r >= 0) { 757
758 while (--r >= 0)
759 {
746 t0 = w[i++] ^ TD0[s0 >> 24] ^ 760 t0 = w[i++] ^ TD0[s0 >> 24] ^
747 TD1[cast(ubyte)(s3 >> 16)] ^ 761 TD1[cast(ubyte)(s3 >> 16)] ^
748 TD2[cast(ubyte)(s2 >> 8)] ^ 762 TD2[cast(ubyte)(s2 >> 8)] ^
749 TD3[cast(ubyte) s1]; 763 TD3[cast(ubyte) s1];
750 t1 = w[i++] ^ TD0[s1 >> 24] ^ 764 t1 = w[i++] ^ TD0[s1 >> 24] ^
797 (RS[cast(ubyte)(t2 >> 16)] << 16) ^ 811 (RS[cast(ubyte)(t2 >> 16)] << 16) ^
798 (RS[cast(ubyte)(t1 >> 8)] << 8) ^ 812 (RS[cast(ubyte)(t1 >> 8)] << 8) ^
799 RS[cast(ubyte) t0]; 813 RS[cast(ubyte) t0];
800 } 814 }
801 815
802 uint update(void[] input_, void[] output_) { 816 uint update(void[] input_, void[] output_)
817 {
803 if (!_initialized) 818 if (!_initialized)
804 throw new NotInitializedError(name()~": Cipher not initialized."); 819 throw new NotInitializedError(name()~": Cipher not initialized.");
805 820
806 ubyte[] input = cast(ubyte[]) input_, 821 ubyte[] input = cast(ubyte[]) input_,
807 output = cast(ubyte[]) output_; 822 output = cast(ubyte[]) output_;
827 return BLOCK_SIZE; 842 return BLOCK_SIZE;
828 } 843 }
829 844
830 void reset() {} 845 void reset() {}
831 846
832 private uint subWord(uint x) { 847 private uint subWord(uint x)
848 {
833 return ((S[x>>24] << 24) | 849 return ((S[x>>24] << 24) |
834 (S[cast(ubyte)(x>>8)] << 8) | 850 (S[cast(ubyte)(x>>8)] << 8) |
835 (S[cast(ubyte)(x>>16)] << 16)| 851 (S[cast(ubyte)(x>>16)] << 16)|
836 (S[cast(ubyte)x])); 852 (S[cast(ubyte)x]));
837 } 853 }
838 854
839 private void setup(ubyte[] key) { 855 private void setup(ubyte[] key)
856 {
840 uint nk = key.length / 4; 857 uint nk = key.length / 4;
841 ROUNDS = nk + 6; 858 ROUNDS = nk + 6;
842 w = new uint[4*(ROUNDS+1)]; 859 w = new uint[4*(ROUNDS+1)];
843 860
844 for (uint i = 0, j = 0; i < nk; i++, j+=4) 861 for (uint i = 0, j = 0; i < nk; i++, j+=4)
845 w[i] = ByteConverter.BigEndian.to!(uint)(key[j..j+int.sizeof]); 862 w[i] = ByteConverter.BigEndian.to!(uint)(key[j..j+int.sizeof]);
846 863
847 for (uint i = nk; i < w.length; i++) { 864 for (uint i = nk; i < w.length; i++)
865 {
848 uint t = w[i-1]; 866 uint t = w[i-1];
849 867
850 if (i % nk == 0) 868 if (i % nk == 0)
851 t = subWord(Bitwise.rotateLeft(t, 8)) ^ RCON[(i/nk)-1]; 869 t = subWord(Bitwise.rotateLeft(t, 8)) ^ RCON[(i/nk)-1];
852 else if (nk > 6 && (i % nk == 4)) 870 else if (nk > 6 && (i % nk == 4))
853 t = subWord(t); 871 t = subWord(t);
854 872
855 w[i] = w[i-nk] ^ t; 873 w[i] = w[i-nk] ^ t;
856 } 874 }
857 875
858 if (!_encrypt) { 876 if (!_encrypt)
877 {
859 for (uint i = 0; i <= 4*ROUNDS; i+=4) 878 for (uint i = 0; i <= 4*ROUNDS; i+=4)
860 w[i..i+4].reverse; 879 w[i..i+4].reverse;
861 w.reverse; 880 w.reverse;
862 881
863 for (uint i = 4; i < w.length-4; i++) { 882 for (uint i = 4; i < w.length-4; i++)
864 w[i] = (TD0[S[w[i]>>24]] ^ 883 {
884 w[i] = (TD0[S[w[i]>>24]] ^
865 TD1[S[cast(ubyte)(w[i]>>16)]] ^ 885 TD1[S[cast(ubyte)(w[i]>>16)]] ^
866 TD2[S[cast(ubyte)(w[i]>>8)]] ^ 886 TD2[S[cast(ubyte)(w[i]>>8)]] ^
867 TD3[S[cast(ubyte)w[i]]]); 887 TD3[S[cast(ubyte)w[i]]]);
868 } 888 }
869 } 889 }
870 } 890 }
871 891
872 /** Some AES test vectors from the FIPS-197 paper and BC. */ 892 /** Some AES test vectors from the FIPS-197 paper and BC. */
873 debug (UnitTest) { 893 debug (UnitTest)
874 unittest { 894 {
895 unittest
896 {
875 static const char[][] test_keys = [ 897 static const char[][] test_keys = [
876 "000102030405060708090a0b0c0d0e0f", 898 "000102030405060708090a0b0c0d0e0f",
877 "000102030405060708090a0b0c0d0e0f1011121314151617", 899 "000102030405060708090a0b0c0d0e0f1011121314151617",
878 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 900 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
879 "80000000000000000000000000000000", 901 "80000000000000000000000000000000",
899 "ddc6bf790c15760d8d9aeb6f9a75fd4e" 921 "ddc6bf790c15760d8d9aeb6f9a75fd4e"
900 922
901 ]; 923 ];
902 924
903 AES t = new AES(); 925 AES t = new AES();
904 foreach (uint i, char[] test_key; test_keys) { 926 foreach (uint i, char[] test_key; test_keys)
927 {
905 ubyte[] buffer = new ubyte[t.blockSize]; 928 ubyte[] buffer = new ubyte[t.blockSize];
906 char[] result; 929 char[] result;
907 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); 930 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key));
908 931
909 // Encryption 932 // Encryption