2012-01-20 56 views
0

我在PHP解密這個C#類編碼的字符串(這是here在PHP解密字符串C#編碼3DES

 
using System; 
using System.Security.Cryptography; 
using System.Text; 

public static class Encryption 
{ 
    public static string Encrypt(string input, string key) 
    { 
     byte[] inputArray = UTF8Encoding.UTF8.GetBytes(input); 
     TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); 
     tripleDES.Key = UTF8Encoding.UTF8.GetBytes(key); 
     tripleDES.Mode = CipherMode.ECB; 
     tripleDES.Padding = PaddingMode.PKCS7; 
     ICryptoTransform cTransform = tripleDES.CreateEncryptor(); 
     byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); 
     tripleDES.Clear(); 
     return Convert.ToBase64String(resultArray, 0, resultArray.Length); 
    } 

    public static string Decrypt(string input, string key) 
    { 
     byte[] inputArray = Convert.FromBase64String(input); 
     TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); 
     tripleDES.Key = UTF8Encoding.UTF8.GetBytes(key); 
     tripleDES.Mode = CipherMode.ECB; 
     tripleDES.Padding = PaddingMode.PKCS7; 
     ICryptoTransform cTransform = tripleDES.CreateDecryptor(); 
     byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); 
     tripleDES.Clear(); 
     return UTF8Encoding.UTF8.GetString(resultArray); 
    } 
} 

我試着在網絡上發現身邊不同的例子,但沒有似乎工作。我認爲第一個問題出現在php mcrypt_generic_init中的$ iv參數中,然後在php函數中缺少填充。 你能幫我轉換在PHP上面的c#解密函數嗎? 謝謝。

+0

如果您想嘗試,不需要'mcrypt',並會使您的代碼更解決方案可移植到沒有它的實例,可以嘗試[phpseclib](http://phpseclib.sourceforge.net/)。這將使用mcrypt函數(如果可用)以及內部實現(如果不可用)。 – DaveRandom

+0

這是有用的:http://sanity-free.com/131/triple_des_between_php_and_csharp.html –

+1

由於C#代碼使用CipherMode.ECB(這是不好的IMO),** IV **應該不重要。 – poupou

回答

2

由於IV在ECB模式下無關緊要,我們可以忽略它。但是,mcrypt並不是非常寬鬆。我們仍然需要提供四,即使它是假的。

// We'll be encrypting this data 
    $key = 'password'; 
    $data = 'The quick brown fox jumped over the lazy dogs.'; 
    $encrypted = null; 

// 3des in ECB mode 
    $m = mcrypt_module_open(MCRYPT_3DES, null, MCRYPT_MODE_ECB, null); 
// Our IV will be enough NUL bytes to satisfy mcrypt. 
    $fake_iv = str_repeat(chr(0), mcrypt_enc_get_iv_size($m)); 
    mcrypt_generic_init($m, $key, $fake_iv); 
    $encrypted = mcrypt_generic($m, $data); 
// "s/6HOXpVyMyFdSPYUgIgneMRY0o3Kubkwc++hSg9kC4Sw0TWsNTqzrhXY3z4PH9w" 
    echo base64_encode($encrypted), "\n"; 
    unset($m); 

// And now, in reverse! 
    $n = mcrypt_module_open(MCRYPT_3DES, null, MCRYPT_MODE_ECB, null); 
// Another fake IV 
    $fake_iv = str_repeat(chr(0), mcrypt_enc_get_iv_size($n)); 
    mcrypt_generic_init($n, $key, $fake_iv); 
    $original = mdecrypt_generic($n, $encrypted); 
// string(48) "The quick brown fox jumped over the lazy dogs." 
    var_dump($original); 

同樣,如果您堅持使用ECB模式,您只需要這樣做。 ECB模式可能非常糟糕。您可能需要查看the Wikipedia article on block cipher modes瞭解更多信息。

這裏沒有處理的唯一問題是填充。 mcrypt不會讓你選擇填充方法,並根據密碼做一些不同的操作。通常,它根本不添加任何填充。

如果您選擇的填充方法使用NUL字節,則需要自行預先填充數據以確保互操作性。您可以使用mcrypt_get_block_sizestr_pad以及STR_PAD_RIGHT選項來執行此操作。

同樣,在解密之後,您可能需要將NUL字節修剪掉。 trim的第二個參數將有所幫助。

+0

Charles做了正確的事情,將IV設置爲00h的字節,並使用適當的函數確定字節數。在CBC模式下,純文本與IV矢量異或,並且用00h值字節異或不會改變純文本。因此,即使IV將被底層代碼使用,將其饋送到零也不會受到傷害。 –

1

即使我想今天的代碼PHP和C#

<?php 
$key64 = "YOUR_KEY"; 
$iv64 = "YOUR_IV"; 


$keybytes = base64_decode($key64); 
$ivbytes = base64_decode($iv64); 

$text = ("4111111111111111"); 

// Padding the text 
$padding = strlen($text)%8; 
for($i=$padding; $i<8; $i++){ 
    $text .= chr(8-$padding); 
} 

$decryptRaw = mcrypt_encrypt(MCRYPT_3DES, $keybytes, $text, MCRYPT_MODE_CBC, $ivbytes); 
$encoded = base64_encode($decryptRaw); 

print "$encoded<br/>"; 
$encryptedString64 = $encoded; 
$decryptbytes = base64_decode($encryptedString64); 

$decryptRaw = mcrypt_decrypt(MCRYPT_3DES, $keybytes, $decryptbytes, MCRYPT_MODE_CBC, $ivbytes); 
$decryptString=trim($decryptRaw,"\x00..\x1F"); 
print "$decryptString<br/>"; 

?> 

C#

private string Decrypt(string encryptedValue) 
{ 
    SymmetricAlgorithm tripleDESKey = SymmetricAlgorithm.Create("TripleDES") ; 
    tripleDESKey.Key = Convert.FromBase64String("YOUR_KEY"); 
    tripleDESKey.IV = Convert.FromBase64String("YOUR_IV") ; 

    MemoryStream encryptedStream = new MemoryStream(); 
    encryptedStream.Write(Convert.FromBase64String(encryptedValue), 0, 
    Convert.FromBase64String(encryptedValue).Length); 
    encryptedStream.Position = 0; 
    CryptoStream cs = new CryptoStream(encryptedStream, 
    tripleDESKey.CreateDecryptor(), CryptoStreamMode.Read); 
    MemoryStream decryptedStream = new MemoryStream(); 

    byte[] buf = new byte[2049]; 
    int bytesRead = 0; 
    bytesRead = cs.Read(buf, 0, buf.Length); 
    while ((bytesRead > 0)) 
    { 
     decryptedStream.Write(buf, 0, bytesRead); 
     bytesRead = cs.Read(buf, 0, buf.Length); 
    } 
    return Encoding.ASCII.GetString(decryptedStream.ToArray()); 
} 
private string Encrypt(string encrypt) 
{ 
    SymmetricAlgorithm sa = SymmetricAlgorithm.Create("TripleDES") ; 
    sa.Key = Convert.FromBase64String("YOUR_KEY"); 
    sa.IV = Convert.FromBase64String("YOUR_IV") ; 
    byte[] inputByteArray = Encoding.ASCII.GetBytes(encrypt); 
    MemoryStream mS = new MemoryStream(); 
    ICryptoTransform trans = sa.CreateEncryptor(); 
    byte[] buf = new byte[2049]; 
    CryptoStream cs = new CryptoStream(mS, trans, CryptoStreamMode.Write); 
    cs.Write(inputByteArray, 0, inputByteArray.Length); 
    cs.FlushFinalBlock(); 
    return Convert.ToBase64String(mS.ToArray()); 
}