本文介绍了C#-AESCng为什么不正确地加密/解密大于127的字节数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过AES加密和解密byte [128] {1,2,...,126,127}时,一切都很好:

when I encrypt and decrypt byte[128] { 1, 2, ..., 126, 127 } by AES, everything is fine:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array 0-127
byte[] raw = new byte[128];
for (byte i = 0; i < 128; i++)
{
    raw[i] = i;
}

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

解密后的

将输出字节[128] {1,2,...,126,127}.但是当我将raw更改为byte [127] {128,129,...,253,254}更改为相同的加密/解密逻辑时,结果变为byte [381],内部是[239,191,189]循环:

decrypted will output byte[128] { 1, 2, ..., 126, 127 }.but when I change raw to byte[127] { 128, 129, ..., 253, 254 } to the same encrypt/decrypt logic, result becomes to byte[381], inside is loops of [239, 191, 189]:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array 128-254    
byte[] raw = new byte[127];
for (byte i = 128; i <= 254; i++)
{
    raw[i-128] = i;
}

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

现在解密后将输出字节[381] {239,191,189,...,239,191,189}

now decrypted will output byte[381] { 239, 191, 189, ..., 239, 191, 189 }

起初,我认为超过127种是不同的,直到我发现以下字节数组也有效:

at start I thought that over 127 is different, until I've found the following byte array also work:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array from Poruguese ÇÃ
string rawPortuguese = "ÇÃ";
byte[] raw = Encoding.UTF8.GetBytes(rawPortuguese);

现在原始数据是字节[4] {195,135,195,131},每个数字都大于127.

now the raw is byte[4] { 195, 135, 195, 131 }, every digit is greater than 127.

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

但也可以正确解密,解密后为byte [4] {195,135,195,131}现在我完全感到困惑,为什么原始数据字节[127] {128,129,...,253,254}无法正确解密?

but also can decrypt correctly, decrypted is byte[4] { 195, 135, 195, 131 }now I totally confused, why raw data byte[127] { 128, 129, ..., 253, 254 } cannot decrypt correctlly?

密钥/IV/加密/解密代码:

Key/IV/Encrypt/Decrypt code:

static byte[] GenerateKey()
{
    using (AesCng cng = new AesCng())
    {
        cng.GenerateKey();
        return cng.Key;
    }
}

static byte[] GenerateIV()
{
    using (AesCng cng = new AesCng())
    {
        cng.GenerateIV();
        return cng.IV;
    }
}

static byte[] Encrypt(byte[] raw, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    byte[] encrypted;

    using (AesCng cng = new AesCng())
    {
        cng.Mode = mode;
        cng.Padding = padding;

        cng.Key = key;
        cng.IV = iv;

        using (ICryptoTransform encryptor = cng.CreateEncryptor())
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(raw, 0, raw.Length);
            }

            encrypted = msEncrypt.ToArray();
        }
    }

    return encrypted;
}

static byte[] Decrypt(byte[] encrypted, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    byte[] decryptedData;
    string plaintext = null;
    byte[] plainData = null;

    using (AesCng cng = new AesCng())
    {
        cng.Mode = mode;
        cng.Padding = padding;

        cng.Key = key;
        decryptedData = encrypted;
        cng.IV = iv;

        using (ICryptoTransform decryptor = cng.CreateDecryptor())
        {
            using (MemoryStream msDecrypt = new MemoryStream(decryptedData))
            {
               using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
               {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        plaintext = srDecrypt.ReadToEnd();
                    }
                    plainData = Encoding.UTF8.GetBytes(plaintext);
                }
            }
        }
    }

    return plainData;
}

推荐答案

这是问题所在

using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
    plaintext = srDecrypt.ReadToEnd();
}
plainData = Encoding.UTF8.GetBytes(plaintext);

您正在将纯文本数据视为UTF-8,将其转换为字符串,然后将其转换回字节(再次使用UTF-8).如果纯文本数据确实是 UTF-8编码的文本(如您的葡萄牙语示例),那很好,但是对于任意字节数组则不是这种情况.字节序列0x80、0x81、0x82、0x83 ... 0xff无效的UTF-8.

You're treating the plain-text data as if it's UTF-8, converting it to a string, then converting it back to bytes (using UTF-8 again). That's fine if the plain-text data really is UTF-8-encoded text (as it is in your Portuguese example), but that's not the case for an arbitrary byte array. The byte sequence 0x80, 0x81, 0x82, 0x83...0xff isn't valid UTF-8.

除非您知道数据是有效的文本,否则不应将其视为文本-总是会导致此类问题.在这种情况下,纯文本"这个名称实际上并不表示 text -这是一个不幸的术语.它只是表示未加密的数据".

Unless you know that data is valid text, you shouldn't treat it as text - that always leads to problems like this. The name "plain text" in this case doesn't really mean text - it's an unfortunate bit of terminology. It just means "not-encrypted data".

如果只想有效地读取任意流并从中创建一个数组,请使用另一个MemoryStream,将数据复制到该流,然后使用MemoryStream.ToArray将其转换为byte[]:

If you just want to effectively read from an arbitrary stream and create an array from it, use another MemoryStream, copy the data to that, then use MemoryStream.ToArray to convert it to a byte[]:

using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
    using (var plainData = new MemoryStream())
    {
        csDescrypt.CopyTo(plainData);
        return plainData.ToArray();
    }
}

这篇关于C#-AESCng为什么不正确地加密/解密大于127的字节数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 16:32