c# - 为什么我的解密文本中出现随机字符?

标签 c# cryptography aes aescryptoserviceprovider

介绍

我正在尝试加密和解密文本,有时,尤其是对于较大的文本,解密文本中会出现随机字符。我在 System.Security.Cryptography 命名空间内使用 AES 密码术,我现在尝试加密的文本将是一个 URL 和一些信息,例如页面标题。我在下面提供了一个示例以及我尝试过的内容。我还编写了两种加密和解密方法,减去了输出到调试窗口的任何行。使用的 Key 和 IV 应该不是问题,因为目前它们是不变的。

我认为明智的做法是指出它按预期在单独的事件中加密和解密 18/01/2013;18/01/2013

例子

假设我想解密这段文字:

Barnabe Googes 信息和主页 |在 BarnabeGooge.com 上搜索和研究;18/01/2013;18/01/2013;;http://www.googe.com

默认情况下它使用 UTF-8 并将加密为:

뤟౏羜ڮ拙浅弊놛荧ꠃ区槝乔昜ầᄼꕒヘ⍩u潺뱂施㒞ꨛ殳硪픴ь뿨춃�燲ᯁﱪ뙊힓픴한 Ѭ쳀荫�྄其⭫ퟂ㪏�荾ꆺשּ붹松麦军

并解密回:

Barnabe Googes 信息和主页 | B����Ax2�!��f��M]18/01/20�;18/01[��;>َ��l?����m��*-��+��^ A[=�

我尝试过的

  • 我已尝试更改为其他编码,但 UTF-8 似乎对解密文本的影响最小。
  • 已更改为不同类型的填充,但 Padding.Zeros 似乎是最好的。我也不能使用 Padding.None,因为它会抛出一个 NotSupportedException: bad data length
  • Mode 更改为 CBC(这无关紧要)。
  • 刷新/关闭 CryptoStream 以便它可以刷新最后一个 block 或其他内容。
  • 为了防止错误出在标题上,我使用了 WebUtility.HtmlDecode() 来解码标题,但它并没有影响它。

加密方式

如您所见,下面的加密使用 AES 加密。我想指出 keyIV 是与加密和解密方法相同的类中的两个全局字符串。我这样做的原因是为了弄乱不同的编码和 CryptographyServiceProviders,如果偶然发生随机更改的话。请忽略这些,因为它们是常量,不会影响最终的加密/解密。

public static byte[] EncryptStringToBytes(string plainText, Encoding Enc)
{

    if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
    byte[] encrypted;
    using (AesCryptoServiceProvider tdsAlg = new AesCryptoServiceProvider())
    {
         tdsAlg.Key = (byte[])Enc.GetBytes(key).Take(tdsAlg.Key.Length).ToArray();
         tdsAlg.IV = (byte[])Enc.GetBytes(IV).Take(tdsAlg.IV.Length).ToArray();
         tdsAlg.Padding = PaddingMode.Zeros;
         tdsAlg.Mode = CipherMode.CBC;
         ICryptoTransform encryptor = tdsAlg.CreateEncryptor(tdsAlg.Key, tdsAlg.IV);

         using (MemoryStream msEncrypt = new MemoryStream())
         {
             using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
             {
                 using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                 {
                     swEncrypt.Write(plainText);
                 }
                 encrypted = msEncrypt.ToArray();
                 csEncrypt.Close();
             }
         }
    }

    return encrypted;
}

解密方法

public static string DecryptStringFromBytes(byte[] cipherText,Encoding Enc)
{
    if (cipherText == null || cipherText.Length <= 0)
        throw new ArgumentNullException("cipherText");

    string plaintext = null;

    using (AesCryptoServiceProvider tdsAlg = new AesCryptoServiceProvider())
    {
        tdsAlg.Key = (byte[])Enc.GetBytes(key).Take(tdsAlg.Key.Length).ToArray();
        tdsAlg.IV = (byte[])Enc.GetBytes(IV).Take(tdsAlg.IV.Length).ToArray() ;
        tdsAlg.Padding = PaddingMode.Zeros;
        tdsAlg.Mode = CipherMode.CBC;
        ICryptoTransform decryptor = tdsAlg.CreateDecryptor();

        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt,true))
                {
                    plaintext = srDecrypt.ReadToEnd().Replace("\0","");
                    csDecrypt.Close();
                    return plaintext.Replace("\0",string.Empty);
                }
            }
        }
   }    
   return plaintext;    
}

引导说明

以防万一,我使用它来获取网页的标题,但正如我所提到的,使用 HtmlDecode 不会影响它。

WebClient x = new WebClient();
string source = x.DownloadString(Url);
x.Dispose();
string title= Regex.Match(source, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
title = title.Replace(";", " ");
return title;

最佳答案

感谢 Hans Passant,我找到了解决方案。问题是我在加密和解密时使用了 Encoding.GetString()Encoding.GetBytes(),而我本应使用 Convert。 ToBase64String()Convert.FromBase64String()

关于c# - 为什么我的解密文本中出现随机字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14405057/

相关文章:

mysql - 如何将 MySQL AES_DECRYPT 与 aes-256-gcm 一起使用

c# - 来自 WPF 的数据库连接

php - 不使用HTTPS登录,如何安全?

c# - 验证子 ASP.NET MVC View 模型,该 View 模型在其父级中不是强制性的,但具有强制性字段

java - 从磁盘加载存储的 RSA 公钥/私钥?

cryptography - 为什么 XOR 是组合哈希值的默认方式?

java - 使用 Java 的 AES 加密

java - AES 中的错误填充异常

c# - 如何围绕私有(private)方法编写单元测试

c# - 将十六进制字符串转换为颜色