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

Bro*_*ter 10 c# cryptography aes aescryptoserviceprovider

介绍

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

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

说我想解密这个文本:

Barnabe Googes Information & Homepage | Search and Research on BarnabeGooge.com;18/01/2013;18/01/2013;;http://www.googe.com

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

?????????????????????????????????????????????????????????????????

并解密回:

Barnabe Googes Information & Homepage | Search and Research on B???Ax2?!??f?M]18/01/20?;18/01[?;>??l?????m??*-??+??^A[=?

我尝试过的

  • 我试图改为其他编码,但UTF-8似乎对解密文本的影响最小.
  • 改为不同类型的填充,但Padding.Zeros似乎是最好的.我也不能使用,Padding.None因为它抛出了NotSupportedException: bad data length.
  • 改为ModeCBC(不是它应该重要).
  • 刷新/关闭CryptoStream以便它可以刷新最后的块或其他东西.
  • 为了防止故障与标题有关,我习惯WebUtility.HtmlDecode()解码标题,但它并没有影响它.

加密方法

您可以看到,下面的加密使用AES加密.我想指出,key并且IV这两个全局字符串与加密和解密方法在同一个类中.我这样做的原因是乱搞不同的编码,并且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;
}
Run Code Online (Sandbox Code Playgroud)

解密方法

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;    
}
Run Code Online (Sandbox Code Playgroud)

Bootnote

为了防止重要,我使用它来获取网页的标题,但正如我所提到的,使用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;
Run Code Online (Sandbox Code Playgroud)

Bro*_*ter 5

感谢汉斯·帕桑特,我找到了解决方案。问题是我在加密和解密时使用Encoding.GetString()or Encoding.GetBytes(),而我应该使用Convert.ToBase64String()or Convert.FromBase64String()