【问题标题】:How to change padding option on an existing encrypt/decrypt code?如何更改现有加密/解密代码的填充选项?
【发布时间】:2016-11-10 19:31:46
【问题描述】:

我有以下代码,它已经工作了将近两年。但是现在我们已经开始看到填充的随机问题。当我说随机时,我的意思是同样的事情一天有效,但前一天无效。有一天它决定随机工作。

现在,如果我像上面的答案中提到的那样将填充添加到 none 中,我可能会弄乱所有以前加密的文件。我正在考虑以这种方法在 catch 块中使用 GOTO 语句创建不同的方法,就像我更改加密密钥时所做的那样。 或者有没有更好的方法将填充更改为无?

/// <summary>
/// 
/// </summary>
[Serializable]
public static class EncryptDecrypt
{
    private static string EncryptionKey_old = "MAKV2SPBNI99212";
    private static string EncryptionKey = "Yi9BpGG1cXR01gBwGPZRTOznoJHpkGBOzisBg5jl3iRu48yhcFGdZu76fDpa5FUu";

    /// <summary>
    /// 
    /// </summary>
    /// <param name="clearText"></param>
    /// <returns></returns>
    public static string Encrypt(string clearText)
    {
        byte[] whitebs = Encoding.Unicode.GetBytes(clearText);

        using (Aes encryptor = Aes.Create())
        {

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            encryptor.Key = pdb.GetBytes(32);

            encryptor.IV = pdb.GetBytes(16);
            encryptor.Mode = CipherMode.ECB;
            encryptor.Padding = PaddingMode.PKCS7;

            using (MemoryStream ms = new MemoryStream())
            {

                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {

                    cs.Write(whitebs, 0, whitebs.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                clearText = Convert.ToBase64String(ms.ToArray());
            }
        }
        return clearText.EndsWith("==") ? clearText.Remove(clearText.Length - 2) : clearText;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="cipherText"></param>
    /// <returns></returns>
    public static string Decrypt(string cipherText)
    {
        int attempts = 0;
        string exception = string.Empty;


        StartHere:
        cipherText = cipherText.Replace(" ", "+");

        byte[] cipherBytes;
        try { cipherBytes = Convert.FromBase64String(cipherText); }
        catch { cipherBytes = Convert.FromBase64String(cipherText + "=="); }

        using (Aes encryptor = Aes.Create())
        {

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });

            encryptor.Key = pdb.GetBytes(32);

            encryptor.IV = pdb.GetBytes(16);
            encryptor.Mode = CipherMode.ECB;
            encryptor.Padding = PaddingMode.PKCS7;
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {

                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {

                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }

                    cipherText = Encoding.Unicode.GetString(ms.ToArray());

                }
            }
            catch
            {
                if (attempts == 2) throw;
                EncryptionKey = EncryptionKey_old;
                attempts++;
                goto StartHere;
            }
        }
        return cipherText;
    }
    '

现在更改它不是一个好主意,我也不知道该怎么做,因为我们使用此代码加密了数千个文件。

【问题讨论】:

  • 那是你刚刚发布在公共互联网上的真正的硬编码加密密钥吗?
  • 不,旧的是真实的,但不再使用了。
  • 我会尝试找出您遇到这些填充问题的原因。如果你弄清楚了,你就不必担心改变其他任何事情。您以错误的方式解决问题。
  • 刚刚根据调用位置发现了一种不同的行为。我有两个地方需要解密,一个来自 Download.aspx,它在按钮单击事件上调用解密方法,另一个在为其他项目设计的 MVC Api 中下载文件。 Api 提供文件下载没有任何问题,但 aspx 抛出异常说“填充无效....”
  • 您是否使用填充错误作为解密成功的指示?您期望什么类型的条件导致catch 执行?哇,我不记得上次在代码中看到goto 是什么时候了。

标签: c# encryption cryptography rijndael


【解决方案1】:

似乎正在使用填充错误来确定解密是否成功,这是错误的并且不起作用!您需要另一种方法来确定成功解密,在这种情况下,如果使用了正确的密钥。

PKCS#7 padding

如果使用错误的密钥解密,结果将基本上是随机数据,最后一个字节为 0x01 的概率为 1/256,这是正确的填充并且不会报告填充错误。在较小程度上,其他有效填充将随机出现。

需要另一种方法来确定是否获得正确的解密,通常使用 MAC 来验证加密。但它可以是数据中已知的东西,这通常称为crib,成功率取决于它的唯一性。

Re:填充:除非要加密的数据的长度始终是块大小(AES 为 16 字节)的精确倍数,否则需要填充并且 PKCS#7 填充是正确的填充

【讨论】:

    猜你喜欢
    • 2019-03-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 2010-12-13
    • 2019-05-09
    相关资源
    最近更新 更多