Mercurial > projects > dcrypt
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 |