C# AES解密非文本文件最终导致数据损坏

C# AES解密非文本文件最终导致数据损坏,c#,encryption,utf-8,aes,rncryptor,C#,Encryption,Utf 8,Aes,Rncryptor,我正在用C#编写一个Windows应用程序,它必须与Mac应用程序(用Cocoa编写)交互。此应用程序使用CBC(IV,密钥,salt,HMAC)加密AES中的文件。我对加密知之甚少,但我认为它就是这样做的。我们使用的可可库是。它们有一个字符串,这就是我在Windows端使用的(经过一些修改,主要是使用byte[]而不是字符串) 现在文本文件已正确解密,但其他文件(例如PNG文件)最终已损坏(正确的文件在右侧,而损坏的文件在左侧,使用UTF8编码,您可以看到有许多带?s的菱形): 我相信这是由

我正在用C#编写一个Windows应用程序,它必须与Mac应用程序(用Cocoa编写)交互。此应用程序使用CBC(IV,密钥,salt,HMAC)加密AES中的文件。我对加密知之甚少,但我认为它就是这样做的。我们使用的可可库是。它们有一个字符串,这就是我在Windows端使用的(经过一些修改,主要是使用
byte[]
而不是字符串)

现在文本文件已正确解密,但其他文件(例如PNG文件)最终已损坏(正确的文件在右侧,而损坏的文件在左侧,使用UTF8编码,您可以看到有许多带?s的菱形):

我相信这是由于文件的编码,但我尝试了UTF8、默认值、Unicode、ASCII。。。输出文件总是被不同大小的文件损坏,ASCII和默认编码(我相信UTF16)是最接近的大小

这是我使用的RNCryptor修改代码:

public byte[] Decrypt (byte[] encryptedBase64, string password)
    {
        PayloadComponents components = this.unpackEncryptedBase64Data (encryptedBase64);

        if (!this.hmacIsValid (components, password)) {
            return null;
        }

        byte[] key = this.generateKey (components.salt, password);

        byte[] plaintextBytes = new byte[0];

        switch (this.aesMode) {
            case AesMode.CTR:
                // Yes, we are "encrypting" here.  CTR uses the same code in both directions.
                plaintextBytes = this.encryptAesCtrLittleEndianNoPadding(components.ciphertext, key, components.iv);
                break;

            case AesMode.CBC:
                plaintextBytes = this.decryptAesCbcPkcs7(components.ciphertext, key, components.iv);
                break;
        }

        return plaintextBytes;
    }

    private byte[] decryptAesCbcPkcs7 (byte[] encrypted, byte[] key, byte[] iv)
    {
        var aes = Aes.Create();
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        var decryptor = aes.CreateDecryptor(key, iv);

        string plaintext;
        using (MemoryStream msDecrypt = new MemoryStream(encrypted))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }

        return Encoding.UTF8.GetBytes(plaintext);
    }

    private PayloadComponents unpackEncryptedBase64Data (byte[] encryptedBase64)
    {
        List<byte> binaryBytes = new List<byte>();
        binaryBytes.AddRange (encryptedBase64);

        PayloadComponents components;
        int offset = 0;

        components.schema = binaryBytes.GetRange(0, 1).ToArray();
        offset++;

        this.configureSettings ((Schema)binaryBytes [0]);

        components.options = binaryBytes.GetRange (1, 1).ToArray();
        offset++;

        components.salt = binaryBytes.GetRange (offset, Cryptor.saltLength).ToArray();
        offset += components.salt.Length;

        components.hmacSalt = binaryBytes.GetRange(offset, Cryptor.saltLength).ToArray();
        offset += components.hmacSalt.Length;

        components.iv = binaryBytes.GetRange(offset, Cryptor.ivLength).ToArray();
        offset += components.iv.Length;

        components.headerLength = offset;

        components.ciphertext = binaryBytes.GetRange (offset, binaryBytes.Count - Cryptor.hmac_length - components.headerLength).ToArray();
        offset += components.ciphertext.Length;

        components.hmac = binaryBytes.GetRange (offset, Cryptor.hmac_length).ToArray();

        return components;

    }

    private bool hmacIsValid (PayloadComponents components, string password)
    {
        byte[] generatedHmac = this.generateHmac (components, password);

        if (generatedHmac.Length != components.hmac.Length) {
            return false;
        }

        for (int i = 0; i < components.hmac.Length; i++) {
            if (generatedHmac[i] != components.hmac[i]) {
                return false;
            }
        }
        return true;
    }

这里有什么问题?提前感谢。

问题在于解密时使用
StreamReader
<代码>StreamReader读取文本(此处为UTF-8),而不是任意二进制数据。一种解决方案是将数据读入
内存流
,并使用其
ToArray()
方法获取结果
字节[]

嘿,谢谢你的回复。不幸的是,除非我做错了什么,否则它不会起作用。这是已修改的方法:。该文件的结尾类似于许多汉字。@pmerino看起来您是从包含加密字节的
msDecrypt
而不是从将被解密的
csDecrypt
中读取的
Read()
错误。谢谢!我试着按照你说的重写代码,现在它成功了!
 byte[] decryptedFile = this.decryptor.Decrypt(File.ReadAllBytes(filePath), password);
 File.WriteAllBytes(filePath, decryptedFile);