Decrypting in PHP a string encoded 3DES with C#

你说的曾经没有我的故事 提交于 2019-12-13 04:42:36

问题


I have to decrypt in PHP a string encoded with this C# class (it's here)

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);
   }
}

I've tried different examples found around on the web, but nothing seems to work. I think that the first problems comes with the $iv parameter in php mcrypt_generic_init and then another problem comes with padding that is missing in php functions. Can you please help me to convert the c# Decrypt function above in PHP? Thank you.


回答1:


Because the IV does not matter in ECB mode, we can ignore it. However, mcrypt isn't very lenient. We still need to provide an IV, even if it's fake.

// 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);

Again, you'll only want to do this if you stick with ECB mode. ECB mode can be pretty awful. You might want to review the Wikipedia article on block cipher modes for more information.

The only thing not handled here is the padding. mcrypt doesn't let you pick the padding method, and does something different depending on the cipher. Generally, it does not add any padding at all.

If your padding method of choice uses NUL bytes, you'll need to pre-pad the data yourself to ensure interoperability. You can use mcrypt_get_block_size and str_pad with the STR_PAD_RIGHT option to do this.

Likewise, you might need to trim NUL bytes off of the right after you decrypt. The second parameter to trim will help.




回答2:


Even I tried today code for both PHP and 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());
}


来源:https://stackoverflow.com/questions/8943873/decrypting-in-php-a-string-encoded-3des-with-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!