Search code examples
c#encryptionaes

Why is the AES algorithm making errors


I have programmed a AES encryption and decryption method, but when i encrypt and decrypt a text, the algorithm makes mistakes. What did i do wrong?

public class VSVerschluesselung : MonoBehaviour {

    [SerializeField]
    private TMP_InputField input;
    [SerializeField]
    private TMP_InputField output;

    private byte[] schluessel = { 196, 67, 23, 195, 176, 89, 198, 17, 7, 248, 47, 232, 246, 107, 249, 252, 138, 21, 133, 226, 186, 82, 255, 199, 152, 0, 1, 173, 239, 18, 181, 238 };
    private byte[] iv = { 137, 224, 26, 121, 180, 59, 150, 95, 164, 216, 57, 161, 247, 251, 68, 182 };
    private Aes crypt;

    public void verschluesseln () {
        string text = input.text;
        if (text == "" || text == null) return;
        Debug.Log ("Verschlüsselung");

        using (Aes crypt = Aes.Create ()) {
            this.crypt = crypt;
            //Maximale Keygröße auswählen
            crypt.KeySize = 256;
            crypt.Key = schluessel;
            crypt.IV = iv;
            crypt.BlockSize = 128;
            crypt.Mode = CipherMode.ECB;

            // Create an encryptor to perform the stream transform.
            ICryptoTransform encryptor = crypt.CreateEncryptor (crypt.Key, crypt.IV);

            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream ()) {
                using (CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write)) {
                    using (BinaryWriter swEncrypt = new BinaryWriter (csEncrypt)) {
                        //Write all data to the stream.
                        swEncrypt.Write (text);
                    }
                    output.text = Encoding.Unicode.GetString (msEncrypt.ToArray ());
                }
            }
        }
        crypt.Clear ();
    }

    public void entschluesseln () {
        string inputText = input.text;
        if (inputText == "" || inputText == null) return;
        Debug.Log ("Entschlüsselung");

        using (Aes crypt = Aes.Create ()) {
            this.crypt = crypt;
            //Maximale Keygröße auswählen
            crypt.KeySize = 256;
            crypt.Key = schluessel;
            crypt.IV = iv;
            crypt.BlockSize = 128;
            crypt.Mode = CipherMode.ECB;

            byte[] verschlText = Encoding.Unicode.GetBytes (inputText);
            // Create a decryptor to perform the stream transform.
            ICryptoTransform decryptor = crypt.CreateDecryptor (crypt.Key, crypt.IV);

            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream (verschlText)) {
                using (CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read)) {
                    using (StreamReader srDecrypt = new StreamReader (csDecrypt)) {

                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        output.text = srDecrypt.ReadToEnd ();
                    }
                }
            }
        }
        crypt.Clear ();
    }
}

Input:

1 Am Anfang schuf Gott Himmel und Erde.

2 Und die Erde war wüst und leer, und Finsternis lag auf der Tiefe; und der Geist Gottes schwebte über dem Wasser.

3 Und Gott sprach: Es werde Licht! Und es ward Licht.

4 Und Gott sah, dass das Licht gut war. Da schied Gott das Licht von der Finsternis

5 und nannte das Licht Tag und die Finsternis Nacht. Da ward aus Abend und Morgen der erste Tag.

Output:

�1 Am Anfang sc���h��y��K�lund Erde.

2 Und die Erde war wüst und leer, und Finsternis lag auf der Tiefe; und der Geist Gottes schwebte über dem Wasser.

3 Und Gott sprach: Es werde���=1�Ŀ���ƺard Licht.

4 Und Gott sah, daI2>�Q��d���% war. Da schied Gott das Licht von der Finsternis

5 und nannte das Licht Tag ���|�_q������is Nacht. Da ward aus Abend und Morgen der erste Tag.


Solution

  • The major error here is output.text = Encoding.Unicode.GetString (msEncrypt.ToArray()); in the encryption function and the Unicode.GetBytes method in the decryption function. Modern ciphertext consists of bytes rather than actual text. So if you treat it as a string then you are likely to lose information, as not all bytes represent a valid character. Or, in this case, 16 bit UTF-16LE code units, as that is what Unicode falsely represents.

    If only one bit of input for the decryption function is changed then it will incorrectly decrypt the entire block. Loss of code units or bytes is even worse.

    Notes:

    • Never store an Aes cipher object, these are lightweight objects. Just store the key instead;
    • Use UTF-8, is it more efficient and used quite a lot more than UTF-16, and even more than UTF-16 in Little Endian form;
    • ECB doesn't take an IV, use CBC instead, at least it is CPA secure (if no plaintext oracles are present).
    • Use base64 to or base64url to convert ciphertext (i.e. randomized bytes) to actual printable characters.
    • Prefixing the IV to the ciphertext (directly using MemoryStream is a good way to transfer the IV with the ciphertext from the encryption function to the decryption function.

    Viel Erfolg!