2012-07-27 58 views
1

我已将http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.aspx的解密代码作了如下修改。我有一个加密的例子,它解码时工作得很好。但是当使用加密函数时,它会用奇怪的符号返回垃圾字符串。下面是加密/解密的功能。为什么RijndaelManaged在加密后返回垃圾数据?

加密字符串“hey”的示例:“??? U?b?z?Y ???”
当再次解码:“UC {ÁpÅ`ñ”,“A”

我使用这个代码的字节数组转换为字符串:

private string ByteArrayToString(byte[] input) 
    { 
     ASCIIEncoding dec = new ASCIIEncoding(); 
     return dec.GetString(input); 
    } 

这里的加密/解密功能。解密功能工作正常。

private string DecryptStringFromBytesAes(byte[] cipherText, byte[] Key, byte[] IV) 
    { 
     // Check arguments. 
     if (cipherText == null || cipherText.Length <= 0) 
      throw new ArgumentNullException("cipherText"); 
     if (Key == null || Key.Length <= 0) 
      throw new ArgumentNullException("Key"); 

     // Declare the string used to hold 
     // the decrypted text. 
     string plaintext = null; 

     // Create an RijndaelManaged object 
     // with the specified key and IV. 
     using (RijndaelManaged aesAlg = new RijndaelManaged()) 
     { 
      aesAlg.Key = Key; 
      aesAlg.Padding = PaddingMode.Zeros; 
      aesAlg.Mode = CipherMode.ECB; 

      // Create a decrytor to perform the stream transform. 
      ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 

      // Create the streams used for decryption. 
      using (MemoryStream msDecrypt = new MemoryStream(cipherText)) 
      { 
       using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
       { 
        using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 
        { 

         // Read the decrypted bytes from the decrypting stream 
         // and place them in a string. 
         plaintext = srDecrypt.ReadToEnd(); 
        } 
       } 
      } 

     } 

     return plaintext; 

    } 




private byte[] EncryptStringToBytesAes(string plainText, byte[] Key, byte[] IV) 
    { 
     // Check arguments. 
     if (plainText == null || plainText.Length <= 0) 
      throw new ArgumentNullException("plainText"); 
     if (Key == null || Key.Length <= 0) 
      throw new ArgumentNullException("Key"); 
     byte[] encrypted; 
     // Create an RijndaelManaged object 
     // with the specified key and IV. 
     using (RijndaelManaged aesAlg = new RijndaelManaged()) 
     { 
      aesAlg.Key = Key; 
      aesAlg.Padding = PaddingMode.Zeros; 
      aesAlg.Mode = CipherMode.ECB; 
      // Create a decrytor to perform the stream transform. 
      ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 

      // Create the streams used for encryption. 
      using (MemoryStream msEncrypt = new MemoryStream()) 
      { 
       using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
       { 
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
        { 

         //Write all data to the stream. 
         swEncrypt.Write(plainText); 
        } 
        encrypted = msEncrypt.ToArray(); 
       } 
      } 
     } 
     return encrypted; 

    } 
+0

那么,任何加密过程的主要目标是将一些有意义的数据转换成看起来像垃圾的东西。它看起来像垃圾越多,加密算法就越好。 – 2012-07-27 15:22:01

+0

当你说加密函数返回垃圾代码时,你的意思是它返回一个加密的字符串,它看起来像垃圾吗? :-)加密的字符串将永远看起来“怪异” – Shawn 2012-07-27 15:22:09

+0

是的,它返回字符串像????和正方形 – cprogcr 2012-07-27 15:22:52

回答

1

为了有作为数据的十六进制编码您的输出,按照方法发现here。我稍微修改它们作为扩展方法:

public static string ToHexString(this byte[] bytes) 
    { 
     return bytes == null ? string.Empty : BitConverter.ToString(bytes).Replace("-", string.Empty); 
    } 

    public static byte[] FromHexString(this string hexString) 
    { 
     if (hexString == null) 
     { 
      return new byte[0]; 
     } 

     var numberChars = hexString.Length; 
     var bytes = new byte[numberChars/2]; 

     for (var i = 0; i < numberChars; i += 2) 
     { 
      bytes[i/2] = Convert.ToByte(hexString.Substring(i, 2), 16); 
     } 

     return bytes; 
    } 
+1

谢谢。正是我需要的。 – cprogcr 2012-07-27 15:41:36

+0

你很受欢迎。祝你好运! – 2012-07-27 15:42:05

1

加密的字符串看起来像是乱码。测试加密是否正常工作的方法是通过解密将字符串传回。如果它在解密工作,那么你知道字符串是正确的,尽管看起来像垃圾给你。

+0

加密的字符串必须如下所示:cfdece55b562efeeb37aa459a013dab3 而不是它们具有奇怪的符号,例如?和正方形 – cprogcr 2012-07-27 15:23:55

+0

这取决于使用的加密。你的号码看起来像一个散列,而不是一个加密值。我会尝试加密,然后使用解密,看看你是否得到你的原始价值。如果你这样做,它可能只是编辑器中的一个字符编码问题,它会改变你看到加密字符串的方式。使用base 64编码。 – Shawn 2012-07-27 15:27:08

+2

@cprogcr所以你想要十六进制输出,而不是实际的加密字节。请参阅http://stackoverflow.com/a/311179/3312关于如何转换和从这个表示法。 – 2012-07-27 15:30:23

4

您观察到的是将任意字节(范围0-255)映射到字符的问题。有意义的字符只在32-255或甚至32-127(ASCII)的范围内。低于32的值是所谓的不可打印字符,高于127的值取决于您使用的字符编码。这就是为什么加密文本看起来像垃圾。因此,肥大的密码系统将字节转换成合理的ASCII范围。一种这样的算法是BASE64。因此,通过BASE64修改加密的字节可以提供全部可打印的字符,并且通过电子邮件不会出现问题。解密之前,你必须撤消BASE64编码。

使加密结果看起来更好的另一种方法是显示它的十六进制表示形式。例如,如果您的字节值为15,那么您可以打印0F。你可以使用这个来代表你的十六进制字节数组:

private string ByteArrayToHexString(byte[] data) 
{ 
    return String.Concat(data.Select(b => b.ToString("x2"))); 
} 
+0

这是正确的。只是为了澄清不懂的读者Base64编码是编码而不是密码学。它是在ASCII范围内存储二进制文件的一种方式。 – Jodrell 2012-07-27 15:30:58

+0

是的,base64是一个解决方案,但杰西C.切片机的评论是我确切需要的。 – cprogcr 2012-07-27 15:37:29