3

We have the following simple encryption method in c#, we want write the same method in php7+

method in C#

using System.Security.Cryptography; public string Encrypt(string strText, string encKey) { byte[] newEncKey = new byte[encKey.Length]; for (int i = 0; i < encKey.Length; i++) newEncKey[i] = (byte)encKey[i]; try { TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider(); byte[] bytes = Encoding.UTF8.GetBytes(strText); MemoryStream stream = new MemoryStream(); CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(newEncKey, newEncKey), CryptoStreamMode.Write); stream2.Write(bytes, 0, bytes.Length); stream2.FlushFinalBlock(); return Convert.ToBase64String(stream.ToArray()); } catch (Exception) { return string.Empty; } } 

We want get the same encryption text with the same key in c# and php7+, We tried to use the following code in php

 public function encryptData($key, $plainText) { $byte = mb_convert_encoding($key, 'ASCII'); $desKey = md5(utf8_encode($byte), true); $desKey .= substr($desKey,0,8); $data = mb_convert_encoding($plainText, 'ASCII'); // add PKCS#7 padding $blocksize = mcrypt_get_block_size('tripledes', 'ecb'); $paddingSize = $blocksize - (strlen($data) % $blocksize); $data .= str_repeat(chr($paddingSize), $paddingSize); // encrypt password $encData = mcrypt_encrypt('tripledes', $desKey, $data, 'ecb'); return base64_encode($encData); } 

, but encryption text using this method not match the encryption text in C# method.

Example :

C#: String key = "234576385746hfgr"; String text = "hello"; Console.WriteLine(Encrypt(text, key)); // output: Hg1qjUsdwNM= 

PHP:

$key = "234576385746hfgr"; $text = "hello"; echo encryptData($key, $text); // output: SRdeQHyKJF8= 

How to get the same encryption text in php7+, we want convert C# code to PHP!

1
  • 2
    It appears to me that the encoding parameters are very different between these two examples: the PHP code "adds PKCS#7 padding" and so on. You are not enciphering exactly the same data in exactly the same way. Commented Mar 4, 2020 at 18:23

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.