为什么AES算法会出错

Why is the AES algorithm making errors

我编写了一个AES加解密方法,但是当我加解密一个文本时,算法出错。 我做错了什么?

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 ();
    }
}

输入:

1 起初神创造天地

2 大地war 荒凉空旷,深渊一片黑暗;上帝的灵在水面上盘旋。

3 上帝说:要有光!而且它 ward 亮。

4 神看光是好的war。然后上帝把光暗分开了

5又叫光明日和黑暗夜。从第一天晚上到早上 ward。

输出:

�1一开始sc����h��y��k��land earth.

2 大地war 荒凉空旷,深渊一片黑暗;上帝的灵在水面上盘旋。

3 上帝说:要有����=1��Ŀ����ƺ硬光。

4 上帝看到 I2>��Q��d����% war。然后上帝把光暗分开了

5并称光日��|��_q������为夜。从第一天晚上到早上 ward。

这里的主要错误是加密函数中的output.text = Encoding.Unicode.GetString (msEncrypt.ToArray());和解密函数中的Unicode.GetBytes方法。现代密文由字节而不是实际文本组成。因此,如果您将其视为字符串,那么您可能会丢失信息,因为并非所有字节都代表有效字符。或者,在这种情况下,16 位 UTF-16LE 代码单元,因为那是 Unicode 错误表示的。

如果只更改解密函数的一位输入,那么它将错误地解密整个块。代码单元或字节的丢失更糟。

备注:

  • 永远不要存储 Aes 密码对象,这些是轻量级对象。只需存储密钥即可;
  • 使用UTF-8,是不是比UTF-16效率更高,用得更多,甚至比小端形式的UTF-16还多;
  • ECB 不采用 IV,而是使用 CBC,至少它是 CPA 安全的(如果没有明文预言机)。
  • 使用 base64 或 base64url 将密文(即随机字节)转换为实际可打印字符。
  • 将IV作为密文前缀(直接使用MemoryStream是将带有密文的IV从加密函数传递到解密函数的好方法。

维尔·埃尔福格!