PHP and C# 3DES Encryption
Asked Answered
Y

1

1

Need to convert the following function from PHP to C# (asp.net)

function encrypt_3DES($message, $key){
    // Se establece un IV por defecto
    $bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
    $iv = implode(array_map("chr", $bytes)); //PHP 4 >= 4.0.2

    // Se cifra
    $ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); //PHP 4 >= 4.0.2
    return $ciphertext;
}

Where $message is a string to encode and $key is the key

The $key is base 64 encoded and it is decoded before calling the function

$key = $this->decodeBase64($key);
$ciphertext = $this->encrypt_3DES($message, $key);

Following C# code I used:

key = Base64Decode(key);
ciphertext = encrypt_3DES(order, key,true);

where

 private  string Base64Decode(string base64EncodedData)
    {
        byte[] base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
        return Encoding.GetEncoding(28591).GetString(base64EncodedBytes);
        // 28591 for php compatibility
    }  

and

  private string encrypt_3DES(string message, string k,bool useHashing)
    {
        byte[] keyArray;
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(message);

        //If hashing use get hashcode regards to your key
        if (useHashing)
        {
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(Encoding.GetEncoding(28591).GetBytes(k));
            //Always release the resources and flush data
            // of the Cryptographic service provide. Best Practice

            hashmd5.Clear();
        }
        else
            keyArray = UTF8Encoding.GetEncoding(28591).GetBytes(k);

        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        //set the secret key for the tripleDES algorithm
        tdes.Key = keyArray;
        //mode of operation. there are other 4 modes.
        //We choose ECB(Electronic code Book)
        tdes.Mode = CipherMode.ECB;
        //padding mode(if any extra byte added)

        tdes.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = tdes.CreateEncryptor();
        //transform the specified region of bytes array to resultArray
        byte[] resultArray =
          cTransform.TransformFinalBlock(toEncryptArray, 0,
          toEncryptArray.Length);
        //Release resources held by TripleDes Encryptor
        tdes.Clear();
        //Return the encrypted data into unreadable string format
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);

    }

The results from PHP and C# are not the same.

Yeargain answered 27/10, 2015 at 16:46 Comment(5)
There are some differences like the hashing, cipher-mode and cipher-padding in C#. Also, it seems your PHP code is incomplete considering how your C# code looks. Can you additionally provide some example message and key?Shoat
You should use CBC, an explicit IV and you should use a key consisting of bytes, not a string. If you use a string in the method parameter you're already lost.Becker
@Artjom B. Complete source code at the following link linkYeargain
@Maarten Bodewes this is an interface to a credit cart payment circuit. The key is provided as a string Base 64 encoded. The bank IT department does not provide a C# interface. So I'm trying to translate from PHP. Thanks for your suggestions.Yeargain
Sorry, I meant that you should not use a string after base 64 decoding. After decoding you should use bytes. I.e. just base64EncodedBytes and byte[] k as parameter.Becker
C
2

I found a code that works for me in this spanish web. http://www.resuelvetusproblemas.com/convertir-encriptacion-en-php-3des-en-c/

This is the function in C# would be the same as you've written in PHP

    public static byte[] TripleDESEncrypt(string texto, byte[] key)
    {
        using (TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider())
        {
            byte[] iv_0 = { 0, 0, 0, 0, 0, 0, 0, 0 };

            byte[] toEncryptArray = Encoding.ASCII.GetBytes(texto);               

            tdes.IV = iv_0;

            //assign the secret key
            tdes.Key = key;

            tdes.Mode = CipherMode.CBC;

            tdes.Padding = PaddingMode.Zeros;

            ICryptoTransform cTransform = tdes.CreateEncryptor();
            //transform the specified region of bytes array to resultArray
            byte[] resultArray =
              cTransform.TransformFinalBlock(toEncryptArray, 0,
              toEncryptArray.Length);

            //Clear to Best Practices
            tdes.Clear();

            return resultArray;
        }
    }
Canoodle answered 29/10, 2015 at 7:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.