0

I try to convert C# encryption to PHP openssl Encryption, but the outside i different. I already use the same encryption method, but output still different, can someone advise me, which part i make mistake ?

C#

public static void Main() { Console.WriteLine(Encrypt("testt123boowe456", "{\"my_account\":\"100081\",\"status\":\"2\",\"ID\":\"3\",\"message\":\"Approved\"}")); } public static string Encrypt(string strKey, string strData) { try { byte[] key = Encoding.UTF8.GetBytes(strKey); byte[] iv = Encoding.UTF8.GetBytes("13313310"); byte[] data = Encoding.UTF8.GetBytes(strData); // Create a MemoryStream. MemoryStream mStream = new MemoryStream(); TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); tdsp.Mode = CipherMode.CBC; tdsp.Padding = PaddingMode.PKCS7; // Create a CryptoStream using the MemoryStream // and the passed key and initialization vector (IV). CryptoStream cStream = new CryptoStream(mStream, tdsp.CreateEncryptor(key, iv), CryptoStreamMode.Write); // Write the byte array to the crypto stream and flush it. cStream.Write(data, 0, data.Length); cStream.FlushFinalBlock(); // Get an array of bytes from the // MemoryStream that holds the // encrypted data. byte[] ret = mStream.ToArray(); // Close the streams. cStream.Close(); mStream.Close(); // Return the encrypted buffer. return byteToHexString(ret); //Convert.ToBase64String(ret); } catch (CryptographicException e) { Console.WriteLine("A Cryptographic error occurred: {0}", e.Message); return null; } } public static string byteToHexString(byte[] bytes) // 0xae00cf => "AE00CF " { string hexString = string.Empty; if (bytes != null) { StringBuilder strB = new StringBuilder(bytes.Length * 2 + 32); for (int i = 0; i < bytes.Length; i++) { strB.Append(bytes[i].ToString("X2")); } hexString = strB.ToString(); } return hexString; } 

PHP

public function encrypt() { $data = [ 'my_account' => "100081", 'status' => "2", 'ID' => "3", 'message' => 'Approved' ]; $stringData = json_encode($data); $key = utf8_encode("testt123boowe456"); $iv = utf8_encode("13313310"); $result = openssl_encrypt($this->zeroPadding(utf8_encode($stringData), 8), 'DES-EDE3-CBC', $key, 0, $iv); return bin2hex($result); } 

C# output

A5C56BEAC60ECAD0CFC9D44898EF4B159BC8E1FB318F83ADD6E474BEA17D0C6DF0F20C672FE0372F304DCB0A001A6005828702C54CA301AF06D49F21FF48260C15D278D2841963FF

PHP output

2f73547a753951745135785373564d38444757564a534666425a41744c6e38666161732f724d2b42335276536c76474450327343353675795a795577577850444a4c4668315a385a32463142676549676b6448587347416a2b684d71364d73734870744374797677744d513d

5
  • I'm giving it the old college try, but are you married to that C# code? Because that implementation is so many different flavors of awful and you really should not use it on data you care about. Commented Dec 19, 2019 at 0:54
  • possible duplicate of this Commented Dec 19, 2019 at 1:13
  • hi, thank for the fast respond, i am worrying both using same method but different library, is that possible? Commented Dec 19, 2019 at 1:15
  • @jagad89 MCrypt was removed as of PHP7.0 and had been deprecated/unmaintained for long before. Anyone who is still using it should ideally be working to not use it anymore. Commented Dec 19, 2019 at 1:41
  • @Sammitch oh, yes. You are right. Commented Dec 19, 2019 at 1:43

1 Answer 1

1

Problems in your code:

  1. The algorithm is actually DES-EDE-CBC.
  2. openssl_encrypt() returns base64'd data unless you specify OPENSSL_RAW_DATA as an option, so you're bin2hex()ing the wrong data.
  3. OPENSSL_ZERO_PADDING needs to be set, not that I can figure out why.
  4. PKCS7 padding is not zero-padding.
  5. When you're trying to debug your crypto use the exact input string, not a potentially buggy computation.
  6. Never ever use utf8_encode() or utf8_decode().
    • They only convert between ISO8859-1 and UTF-8.
    • They do not check what the input encoding is and will happily and silently corrupt your data.
    • All PHP strings are binary strings/byte arrays, and you are responsible for managing the encoding. You must always explicitly know the encoding of your string, because you're in trouble if you don't. See: UTF-8 all the way through
    • The output of json_encode() is always valid UTF-8, in line with the JSON spec.
    • If you do need to convert between encodings use something like mb_convert_encoding() and explicitly defined your input and output encodings.

So:

function pkcs7_pad($data) { $padlen = 8 - (strlen($data) % 8); return $data . str_repeat(chr($padlen), $padlen); } function encrypt($input) { $key = "testt123boowe456"; $iv = "13313310"; $result = openssl_encrypt(pkcs7_pad($input), 'DES-EDE-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); return $result; } $input = "{\"my_account\":\"100081\",\"status\":\"2\",\"ID\":\"3\",\"message\":\"Approved\"}"; $desired = "A5C56BEAC60ECAD0CFC9D44898EF4B159BC8E1FB318F83ADD6E474BEA17D0C6DF0F20C672FE0372F304DCB0A001A6005828702C54CA301AF06D49F21FF48260C15D278D2841963FF"; var_dump( strtoupper(bin2hex(encrypt($input))), $desired ); 

Yields:

string(144) "a5c56beac60ecad0cfc9d44898ef4b159bc8e1fb318f83add6e474bea17d0c6df0f20c672fe0372f304dcb0a001a6005828702c54ca301af06d49f21ff48260c15d278d2841963ff" string(144) "A5C56BEAC60ECAD0CFC9D44898EF4B159BC8E1FB318F83ADD6E474BEA17D0C6DF0F20C672FE0372F304DCB0A001A6005828702C54CA301AF06D49F21FF48260C15D278D2841963FF" 

That said, the reasons why the C# implementation is wholly inadvisable:

  1. 3DES is old, slow, and far less strong than other widely available and implemented algos.
  2. Using a text passphrase with no Key Derivation Function is weak.
  3. Using a text IV is weak.
  4. Using a static IV is unforgivable and drastically weakens your crypto.
Sign up to request clarification or add additional context in comments.

1 Comment

Hi Sammitch, thanks for the fast respond, It's working fine, thanks for your advise, really appreciate it so much.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.