2012-07-24 140 views
2

我在我的Android應用程序中使用了用PHP編寫的REST服務,沒有太大麻煩。現在我試圖在Windows Phone應用程序中使用它,我已經瘋了!在PHP中加密,使用AES/Rijndael在C#(WP7/Silverlight)中解密

我所知道的,到目前爲止:Silverlight will accept only Aes in CBC mode and PKCS7 padding.

我得到什麼:「填充是無效的不能刪除」的例外(見完整的代碼在底部):

plaintext = srDecrypt.ReadToEnd(); 

如果我隱窩並在C#中解密,使用相同的配置,它工作正常。當我嘗試使用PHP加密字符串在C#中進行標識時,它會因上面提到的錯誤而失敗。

我的PHP腳本執行以下操作:

function encrypt128($message) { 
    $vector = "DB96A56CCA7A69FC"; 
    $key = "6DBC44F54CA3CFDEDDCA140CA46A99C1"; // PHP md5 function leaves it in lower case, so I just copied the key from C# debug. 

    //PKCS7 Padding 
    $block = mcrypt_get_block_size('rijndael_128', 'cbc'); 
    $pad = $block - (strlen($message) % $block); 
    $message.= str_repeat(chr($pad), $pad); 

    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', ''); 
    mcrypt_generic_init($cipher, $key, $vector); 
    $result = mcrypt_generic($cipher, $message); 
    mcrypt_generic_deinit($cipher); 

    return base64_encode($result); 
} 

而在C#(的Silverlight/Windows Phone 7的)我用下面的解密:

//Where buffer is the string data I got after calling the PHP REST service. 
DecryptStringFromBytes(Convert.FromBase64String(buffer), MD5Core.GetHash("7a272d3e41372c547a272d3e41372c54"), System.Text.Encoding.UTF8.GetBytes("DB96A56CCA7A69FC")); 

static string DecryptStringFromBytes(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"); 
    if (IV == null || IV.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 (AesManaged rijAlg = new AesManaged()) 
    { 
     rijAlg.Key = Key; 
     rijAlg.IV = IV; 

     // Create a decrytor to perform the stream transform. 
     ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.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; 
} 

最大的問題是:我是什麼做錯了?

在此先感謝!

+0

如果你加密每個方法中的一個非常小的字符串,並比較輸出,他們有區別嗎?怎麼樣? – Jonathan 2012-07-24 23:58:41

+0

如果我編碼「Test」,我會在C#中獲得「eScuqAGH8L6cKaRG9ii + uw ==」,在PHP中獲得「0RysWwzyHHDnwcf0cIQ8xg ==」。 – 2012-07-25 12:27:56

+0

我更改了StreamWriter構造函數以測試所有可用的編碼類型(UTF8,Unicode,BigEndian),但C#仍然生成不同的編碼字符串。 – 2012-07-25 14:11:36

回答

0

因此,這裏的答案:

我DROP掉了MD5屁滾尿流的PHP和C#,和他們現在工作正常。

爲防萬一你在這裏尋找相同的答案,這裏是一個示例代碼。不要忘了讓自己的密鑰和IV

PHP(雖然這些波紋管會的工作,不建議使用!):

function encrypt128($message) { 
    $vector = "0000000000000000"; 
    $key = "00000000000000000000000000000000"; 

    $block = mcrypt_get_block_size('rijndael_128', 'cbc'); 
    $pad = $block - (strlen($message) % $block); 
    $message .= str_repeat(chr($pad), $pad); 

    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', ''); 
    mcrypt_generic_init($cipher, $key, $vector); 
    $result = mcrypt_generic($cipher, $message); 
    mcrypt_generic_deinit($cipher); 

    return base64_encode($result); 
} 

C#:

byte[] cripted = EncryptStringToBytes("Test", System.Text.Encoding.UTF8.GetBytes("00000000000000000000000000000000"), System.Text.Encoding.UTF8.GetBytes("0000000000000000")); 
+0

馬科斯,你根本沒有使用你的矢量。你的矢量長度也應該等於密鑰大小。對於密碼名稱和方法,更好地使用'MCRYPT_RIJNDAEL_128','MCRYPT_MODE_CBC'這是內部定義的,不會被意外解釋爲任何其他內容。 'System.Text.Encoding.UTF8.GetBytes'會給你意想不到的IV數據,你可以使用'byte [] Key = new byte [] {0x00,....};'或'Encoding.ASCII.GetBytes( ......)第一種方法通常用於金融行業的安全關鍵定義。 – AaA 2015-02-27 16:31:40

-1

加密/解密使用PHP:

class Cipher { 
    private $key, $iv; 
    function __construct() { 
     $this->key = "edrtjfjfjlldldld"; 
     $this->iv = "56666852251557009888889955123458"; 
    } 
    function encrypt($text) { 

     $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
     $padding = $block - (strlen($text) % $block); 
     $text .= str_repeat(chr($padding), $padding); 
     $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $text, MCRYPT_MODE_CBC, $this->iv); 

     return base64_encode($crypttext); 
    } 

    function decrypt($input) { 
     $dectext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->key, base64_decode($input), MCRYPT_MODE_CBC, $this->iv); 
     return $dectext; 
    } 
} 

加密/解密中使用C#:

public class RijndaelSimple 
    { 
     const string iv = "56666852251557009888889955123458"; 
     const string key = "edrtjfjfjlldldld"; 

     static public String EncryptRJ256(string plainText) 
     { 
      var encoding = new UTF8Encoding(); 
      var Key = encoding.GetBytes(key); 
      var IV = encoding.GetBytes(iv); 
      byte[] encrypted; 

      using (var rj = new RijndaelManaged()) 
      { 
       try 
       { 
        rj.Padding = PaddingMode.PKCS7; 
        rj.Mode = CipherMode.CBC; 
        rj.KeySize = 256; 
        rj.BlockSize = 256; 
        rj.Key = Key; 
        rj.IV = IV; 

        var ms = new MemoryStream(); 

        using (var cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write)) 
        { 
         using (var sr = new StreamWriter(cs)) 
         { 
          sr.Write(plainText); 
         } 
         encrypted = ms.ToArray(); 
        } 
       } 
       finally 
       { 
        rj.Clear(); 
       } 
      } 

      return Convert.ToBase64String(encrypted); 
     } 

     static public String DecryptRJ256(string input) 
     { 
      byte[] cypher = Convert.FromBase64String(input); 

      var sRet = ""; 

      var encoding = new UTF8Encoding(); 
      var Key = encoding.GetBytes(key); 
      var IV = encoding.GetBytes(iv); 

      using (var rj = new RijndaelManaged()) 
      { 
       try 
       { 
        rj.Padding = PaddingMode.PKCS7; 
        rj.Mode = CipherMode.CBC; 
        rj.KeySize = 256; 
        rj.BlockSize = 256; 
        rj.Key = Key; 
        rj.IV = IV; 
        var ms = new MemoryStream(cypher); 

        using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) 
        { 
         using (var sr = new StreamReader(cs)) 
         { 
          sRet = sr.ReadLine(); 
         } 
        } 
       } 
       finally 
       { 
        rj.Clear(); 
       } 
      } 

      return sRet; 
     } 

    } 
+2

該代碼在Windows Phone中不起作用。 WP沒有RijndaelManaged類 – 2014-03-23 00:21:23

+0

我試過了c#代碼,這個簡單的測試不起作用 string encryptedString = EncryptRJ256(teststring); string decryptedString = DecryptRJ256(encryptedString); 斷言。AreEqual(decryptedString,teststring); – 2014-10-07 13:19:50

+0

@AlexMaker,這個作品: string teststring =「快速的棕色狐狸跳過懶惰的狗」; string encryptedString = RijndaelSimple.EncryptRJ256(teststring); string decryptedString = RijndaelSimple.DecryptRJ256(encryptedString); bool bAreEqual =(decryptedString == teststring?true:false); // bAreEqual = true – Melad 2014-10-10 13:48:34