c# - AES 256 加密与结果不匹配

标签 c# .net encryption

我有一份文件说要使用 AES256 加密字符串 。根据我的文档中的两个值 10002:1486703720424 AND HashKey: hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF 它将生成结果 1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc= 但是当我尝试生成它从我的代码生成 6SKbqJAxbBrg4eU7r/B8gJoJEPg+KjMvGL5L7bfykUU= 的结果。你能告诉我我在做什么错误吗?这是我第一次进行加密,所以我有点困惑地发现我的错误。

string getHashKey1 = EncryptText("10002:1486703720424", "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");

public string EncryptText(string input, string password)
{
    string result = "";
    try
    {
        // Get the bytes of the string
        byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

        // Hash the password with SHA256
        passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

        byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

        result = Convert.ToBase64String(bytesEncrypted);
    }
    catch (Exception ex)
    {
        ErrorLog errLog = new ErrorLog();
        errLog.LogsWrite(ex, Path.GetDirectoryName(Application.ExecutablePath));

    }

    return result;
}

public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
    byte[] encryptedBytes = null;
    try
    {
        // Set your salt here, change it to meet your flavor:
        // The salt bytes must be at least 8 bytes.
        byte[] saltBytes = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };

        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;

                var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);  
                AES.Mode = CipherMode.CBC;

                using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                    cs.Close();
                }
                encryptedBytes = ms.ToArray();
            }
        }
    }
    catch (Exception ex)
    {
        ErrorLog errLog = new ErrorLog();
        errLog.LogsWrite(ex, Path.GetDirectoryName(Application.ExecutablePath));
    }    

    return encryptedBytes;
}

最佳答案

发现...他们使用 ECB 作为密码模式,所以没有 IV。我不会评论这个的“安全性”。填充似乎是 PKCS7(AES 的默认值)。密码“按原样”使用,简单地以 UTF8(或者甚至 ASCII)编码(因此它必须是 32 字节长)。

public static string EncryptText(string input, string password)
{
    // Get the bytes of the string
    byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
    byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

    byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

    string result = Convert.ToBase64String(bytesEncrypted);
    return result;
}

public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = passwordBytes;
            aes.Mode = CipherMode.ECB;

            // "zero" IV
            aes.IV = new byte[16];

            using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                cs.Close();
            }
        }

        byte[] encryptedBytes = ms.ToArray();
        return encryptedBytes;
    }
}

@LukePark 正确地对这个答案进行了长篇大论,该答案对 OP 有用,但在更大的世界中毫无用处。我会将正确 字样加粗。出于这个原因,我将解释给 A. Goutam 的规范中的“错误”以及“正确”规范必须始终包含的内容。

加密规范应始终包含:使用的算法(例如 AES)、 key 大小(如果您说 AES256,那么显然它是 256 位)、 block 模式(CBC、ECB 等)。许多 block 模式(例如 CBC)需要 IV 向量。 ECB 的安全性低于其他 block 模式(参见示例 https://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher )。如果 IV 是必要的,那么规范必须包含它(或解释它应该如何生成)。规范必须包含应该使用的填充。 Padding.None 仅当要加密的数据可以精确分割为加密 block 时才应使用(例如,对于 AES,PaddingMode.None 仅在以下情况下才有效数据为 16、32、64、96、... 字节)。 PaddingMode.Zeros 仅适用于文本(我不会使用它,因为它会在文本末尾添加 '\0')。其他padding模式都不错。

key 通常不会“按原样”使用,因为例如它是一个字符串。规范应包含必须如何从字符串 key 派生出加密 key 。 key 上的 SHA256 是一个弱解。通常一个好的解决方案是使用强大的 key 派生函数,例如 Rfc2898DeriveBytes。如果使用此函数,规范必须包含迭代次数和有关使用 Rfc2898DeriveBytes 或类似函数的其他信息。显然必须包括 key (以及要加密的数据,如果是文本)应该使用什么编码(UTF8 总是一个好主意)。

我要补充一点,一个好的规范应该包含一些测试用例。至少一个测试用例的长度应小于加密 block ,并且至少一个测试用例必须的长度大于加密 block 但小于两个加密 block (或 > 2 和 < 3. ..一些完整的 block 和一个不完整的 block )。通过这种方式,您正在测试 PaddingModeCipherMode(注意应该/必须:通过测试比加密 block 更大的东西加上不完整的 block ,您已经在测试所有内容)

关于c# - AES 256 加密与结果不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42642551/

相关文章:

c# - 使用私钥签署程序集

c# - 当我使用 .ToShortTimeString().... 只能使用模板?

c# - Crystal Reports 打印纵向而不是横向

c# - ExcelReader Factory 在最后写入行失败

c# - 何时以及如何交换 .NET 托管堆?

Java加密/解密到Ruby

android - 使用集成 Android 2.3 SIP 堆栈进行加密 VoIP 通信

java - 如何在 C# 中反序列化 JAVA 程序使用 jackson 发送的 JSON 对象?

c# - 二维码定制尺寸

.net - 通过非泛型 IDictionary 枚举时,无法将泛型字典项转换为 DictionaryEntry