2012-07-27 79 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