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

RamblinRose
  • 4,883
  • 2
  • 21
  • 33
php_dvp
  • 133
  • 1
  • 4
  • 14
  • 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. – Sammitch Dec 19 '19 at 00:54
  • possible duplicate of [this](https://stackoverflow.com/questions/31656191/c-sharp-tripledes-ecb-encryption-in-php) – jagad89 Dec 19 '19 at 01:13
  • hi, thank for the fast respond, i am worrying both using same method but different library, is that possible? – php_dvp Dec 19 '19 at 01: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. – Sammitch Dec 19 '19 at 01:41
  • @Sammitch oh, yes. You are right. – jagad89 Dec 19 '19 at 01:43

1 Answers1

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.
Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • Hi Sammitch, thanks for the fast respond, It's working fine, thanks for your advise, really appreciate it so much. – php_dvp Dec 19 '19 at 03:17