How to Convert Code from C# to PHP

How to convert code from C# to PHP

I know you're hoping for someone who had experience but in case no one comes forward...

You might consider just copy and pasting the code into a PHP script and checking what breaks. Write a parser to fix that, run it across the entire script, and see what's the next thing that breaks. Continue until the script functions as expected.

If you're not using any of the more involved .Net classes I can't imagine you'll have too much trouble.

Converting Csharp to PHP with cs2php

According to @Magnus Eriksson comments, I'll try to rewrite my code and convert manually

Converting C# function to PHP

At first glance, this seems to be an XOR cipher. The one string provided is the key, and the other is a string which has been XOR'd by the key once before. XOR'ing it again with the key results in getting back the original string.

I would try to reimplement the code instead of copying it word for word, because it's not particularly well written (unless I am mistaken about the intent of the C# code, this can be rewritten in a much more readable 3 or 4 lines, without using goto, etc). There seem to be PHP examples out there on this type of thing.

Convert C# code to PHP

I am no encryption expert, but this should be working example...

# original C# code

# private static readonly byte[] IV = new byte[8] { 240, 3, 45, 29, 0, 76, 173, 59 };
# public string Decrypt(string encryptedData,string key)
# {
# encryptedData = HttpUtility.UrlDecode(encryptedData);
# byte[] buf = Convert.FromBase64String(encryptedData);
# TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
# MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider();
# des.Key = MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(key));
# des.IV = IV;
# return Encoding.ASCII.GetString(
# des.CreateDecryptor().TransformFinalBlock(
# buf,
# 0,
# buf.Length
# )
# );

# }

# }

// packs array into bytestring
function pack_array($a) {
$out = null;
foreach ($a as $i) { $out .= chr(ord(substr($i,0,1))); }
return $out;

class Sample {
public static $IV = array( 240, 3, 45, 29, 0, 76, 173, 59 );
public static $key = 's3cr3tk3yl0ng1n4ph';

// 3des encryption
public static function Encrypt($data) {
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');

$ks = mcrypt_enc_get_key_size($td);

// create key
$key = substr(md5(self::$key), 0, $ks);
// pack IV
$IVPacked = pack_array(self::$IV);
mcrypt_generic_init($td, $key, $IVPacked);
$encryptedData = mcrypt_generic($td, $data);

$encryptedData = base64_encode($encryptedData);
$encryptedData = urlencode($encryptedData);
return $encryptedData;

// 3des decryption
public static function Decrypt($encryptedData, $key) {
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');

$encryptedData = urldecode($encryptedData);
$encryptedData = base64_decode($encryptedData);

$key = substr(md5($key), 0, mcrypt_enc_get_key_size($td));
$IVPacked = pack_array(self::$IV);
mcrypt_generic_init($td, $key, $IVPacked);
$decryptedData = mdecrypt_generic($td, $encryptedData);

return $decryptedData;

// __main__
$data = "methodname=GetClientшђшђ";

//var_dump(unpack_str($data, strlen($data)));
$encryptedData = Sample::Encrypt($data);

var_dump (bin2hex($encryptedData));

$decryptedData = Sample::Decrypt($encryptedData, Sample::$key);
echo "\n";

Convert C# to PHP

Your arrays don't look right. ItemLines and PaymentLines should be arrays instead of an object containing an array.

Even though StartSale returns them as objects, they should still be an array for the call to SaveSale. The reason they are returned as objects is a quirk of the PHP SoapClient. What happens is, if there is just one element in the array, the SoapClient gives you an object with its properties set as the single element properties. However if there is more than one element in the array, you get an array of objects instead, and so is one level deeper than the result when there's only a single element. So because they are returned with no elements from StartSale, they are given as objects instead of an empty array.

$Sale->StartSaleResult->ItemLines = array($line);

// Payment line, cash
$cash = new stdClass();
$cash->Type = 'Cash';
$cash->Qty = 1;
$cash->LineAmount = 600;

// Payment line, Change
$change = new stdClass();
$change->Type = 'Change';
$change->Qty = 1;
$change->LineAmount = -100;
$Sale->StartSaleResult->PaymentLines = array($cash, $change);

Also depending on what the WSDL looks like, you may need to pass an associative array as the parameters, with keys as sale and key (according to the WSDL), instead of passing two separate arguments:

$response = $client->SaveSale(array('sale' => $Sale->StartSaleResult, 'key' => 'xxxxxxxx'));

Change sale and key to whatever the WSDL defines them as.

Convert C# Code to PHP Code to extract one xml tag from html

the translation of

private static String CutOutXML(string resp)
var url = resp.Substring(resp.IndexOf("<div>") + "<div>".Length);
url = url.Substring(0, url.IndexOf("</div>"));
return url;

would be

function CutOutXML(string $resp):string
$url = substr($resp,strrpos($resp,'<div>')+ strlen('<div>'));
$url = substr($url,0, strrpos($url,"</div>"));
return $url;

however as the other comments say there are much better ways of doing what you appear to be trying to do


$matches = [];
preg_match('/<div>(.*)<\/div>/', $resp, $matches);

Convert simple encryption method in c# to php

In the C# code, the mode is not explicitly specified, so that the CBC mode is used by default. In the PHP code, however, the ECB mode is applied, which must be changed into the CBC mode.

In the C# code newEncKey is used as key, which is 16 bytes in size and is implicitly extended to 24 bytes (3 times the TripleDES block size of 8 bytes) by appending the first 8 bytes at the end (this corresponds to 2TDEA). This must be done explicitly in the PHP code. Also remove the MD5 digest, as it's not used in C# code:

$byte = mb_convert_encoding($key, 'ASCII');
//$desKey = md5(utf8_encode($byte), true);
$desKey = $byte . substr($byte, 0, 8);

In the C# code newEncKey is also used as IV, of which implicitly only the first 8 bytes are applied (1 times the TripleDES block size). In the PHP code the shortening of the IV must be done explicitely, e.g. with

$desIV = substr($byte, 0, 8);

The IV must be passed as 5th parameter in mcrypt_encrypt:

$encData = mcrypt_encrypt('tripledes', $desKey, $data, 'cbc', $desIV);

The C# code uses PKCS7 padding by default, so this is consistent with the padding of the PHP code.

With these changes, the PHP code produces the same result as the C# code.

For security reasons, key/IV pairs may not be used more than once. The logic used here (generation of the IV from the key) therefore requires a new key for each encryption. Furthermore mcrypt_encrypt is deprecated, a better alternative is openssl_encrypt, which also uses PKCS7 padding by default.

Converting C# code to php encoding issue

The solution, updated:

$a = "SF0D9G9SGGF0gdsfg976590";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a, true);
$res = '';
for($i=0; $i<16; $i+=2) {
// System.Text.Encoding.Unicode.GetString(byteHashValue) replaces invalid characters to 0xfffd ('я')
// while PHP to 0x003d ('?') or empty string. So replace them like C# does
$a2 = mb_convert_encoding($a[$i].$a[$i+1], "UTF-16LE","UTF-16LE"); // check if this is invalid UTF-16 character
if(strlen($a2)==0 || $a[$i]!=$a2[0]) {
// replace invalid UTF-16 character with C# like
$v = 0xfffd;
else {
// prepare a word (UTF-16 character)
$v = ord($a[$i+1])<<8 | ord($a[$i]);
// print each word without leading zeros as C# code does
$res .= sprintf("%x",$v);

Related Topics

Leave a reply