12

I would like to convert C# function to PHP function. Here is link to Function in C# : https://stackoverflow.com/a/19441805/3581428

public static string Encrypt(string clearText)
{
    string EncryptionKey = "MAKV2SPBNI99212";
    byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    using (Aes encryptor = Aes.Create())
    {
        Rfc2898DeriveBytes pdb = new 
            Rfc2898DeriveBytes(EncryptionKey, new byte[] 
            { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        encryptor.Key = pdb.GetBytes(32);
        encryptor.IV = pdb.GetBytes(16);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            clearText = Convert.ToBase64String(ms.ToArray());
        }
    }
    return clearText;
}

public static string Decrypt(string cipherText)
{
    string EncryptionKey = "MAKV2SPBNI99212";
    byte[] cipherBytes = Convert.FromBase64String(cipherText);
    using (Aes encryptor = Aes.Create())
    {
        Rfc2898DeriveBytes pdb = new 
            Rfc2898DeriveBytes(EncryptionKey, new byte[] 
            { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        encryptor.Key = pdb.GetBytes(32);
        encryptor.IV = pdb.GetBytes(16);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(cipherBytes, 0, cipherBytes.Length);
                cs.Close();
            }
            cipherText = Encoding.Unicode.GetString(ms.ToArray());
        }
    }
    return cipherText;
}

I have tried in function below but It created different Encrypted string:

function encrypt_decrypt($action, $string) {
    $output = false;

$encrypt_method = "AES-256-CBC";
$secret_key = '3sc3RLrpd17';

$secret_iv=chr(0x49).chr(0x76).chr(0x61).chr(0x6e).chr(0x20).chr(0x4d).chr(0x65).chr(0x64).chr(0x76).chr(0x65).chr(0x64).chr(0x65).chr(0x76);


$key = substr(hash('sha1', $secret_key), 0, 32);;
//echo "key: ".$key."<br>";

$iv = substr(hash('sha1', $secret_iv), 0, 16);
//echo "iv key: ".$iv."<br>";
if( $action == 'encrypt' ) {
    $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
    $output = base64_encode($output);
}
else if( $action == 'decrypt' ){
    $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}

return $output;
}

$plain_txt = "1122334411223344";
echo "Plain Text = $plain_txt\n"."<br/>";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n"."<br/>";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n"."<br/>";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS"."<br/>";
else echo "FAILED"."<br/>";

echo "\n"."<br/>";
exit;

Encrypted String using C# method :

thkTvpUmSWV9lKAOfWNIIu9n7jHcku7C6WDD/hsvll+xjqOWdk3fyI+eRhBbvJlX

Length is 64

Encrypted String Using PHP method :

OTlIYXJDcTl0SVpKRlhaV0l3dFk1ZjFYM3FPcHB3ckdTRERITGhHVEVoTT0=

Length is 60

How can I generate same Encrypted string as C# function ? How can I replicate C# function for PHP?

Able to Create Encrypted Text Length of 64 using this example Link : AES ENCRYPTION 64 length encrypted string

jww
  • 97,681
  • 90
  • 411
  • 885
user3581428
  • 173
  • 1
  • 1
  • 9
  • I think `Rfc2898DeriveBytes` uses SHA-1 and not SHA-256. – odan Aug 08 '17 at 12:43
  • 1
    The cipher IV length for AES-256-CBC must be 16 and not 13. – odan Aug 08 '17 at 12:53
  • @DanielO. $iv = substr(hash('sha1', $secret_iv), 0, 16); IV length is 16 and updated code to use sha1 but encrypted text is not the same – user3581428 Aug 08 '17 at 13:23
  • @DanielO. can you explain me this part ? Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); – user3581428 Aug 08 '17 at 13:25
  • The Rfc2898DeriveBytes class implements PBKDF2 functionality by using a pseudorandom number generator based on HMACSHA1. The Rfc2898DeriveBytes class takes a password, a salt, and an iteration count (Default=1000), and then generates keys through calls to the GetBytes method. – odan Aug 08 '17 at 13:36
  • @DanielO. How can i do that in PHP using key "3sc3RLrpd17"? – user3581428 Aug 08 '17 at 13:37
  • @user3581428 The output of PBKDF2 can not be 13 bytes, start looking there. PBKDSF2 must use the same hash method, salt and iteration count. Ensure the keys, IV and data (in hex) are identical. Please add that to the question. – zaph Aug 08 '17 at 18:30

3 Answers3

13

Please try this (beta):

PHP

<?php

$plaintext = 'My secret message 1234';
$password = '3sc3RLrpd17';
$method = 'aes-256-cbc';

// Must be exact 32 chars (256 bit)
$password = substr(hash('sha256', $password, true), 0, 32);
echo "Password:" . $password . "\n";

// IV must be exact 16 chars (128 bit)
$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);

// av3DYGLkwBsErphcyYp+imUW4QKs19hUnFyyYcXwURU=
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $password, OPENSSL_RAW_DATA, $iv));

// My secret message 1234
$decrypted = openssl_decrypt(base64_decode($encrypted), $method, $password, OPENSSL_RAW_DATA, $iv);

echo 'plaintext=' . $plaintext . "\n";
echo 'cipher=' . $method . "\n";
echo 'encrypted to: ' . $encrypted . "\n";
echo 'decrypted to: ' . $decrypted . "\n\n";

exit;

C#

    public string EncryptString(string plainText, byte[] key, byte[] iv)
    {
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;

        // Set key and IV
        byte[] aesKey = new byte[32];
        Array.Copy(key, 0, aesKey, 0, 32);
        encryptor.Key = aesKey;
        encryptor.IV = iv;

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

        // Convert the plainText string into a byte array
        byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

        // Encrypt the input plaintext string
        cryptoStream.Write(plainBytes, 0, plainBytes.Length);

        // Complete the encryption process
        cryptoStream.FlushFinalBlock();

        // Convert the encrypted data from a MemoryStream to a byte array
        byte[] cipherBytes = memoryStream.ToArray();

        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();

        // Convert the encrypted byte array to a base64 encoded string
        string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);

        // Return the encrypted data as a string
        return cipherText;
    }

    public string DecryptString(string cipherText, byte[] key, byte[] iv)
    {
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;

        // Set key and IV
        byte[] aesKey = new byte[32];
        Array.Copy(key, 0, aesKey, 0, 32);
        encryptor.Key = aesKey;
        encryptor.IV = iv;

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

        // Will contain decrypted plaintext
        string plainText = String.Empty;

        try
        {
            // Convert the ciphertext string into a byte array
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Decrypt the input ciphertext string
            cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

            // Complete the decryption process
            cryptoStream.FlushFinalBlock();

            // Convert the decrypted data from a MemoryStream to a byte array
            byte[] plainBytes = memoryStream.ToArray();

            // Convert the decrypted byte array to string
            plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
        }
        finally
        {
            // Close both the MemoryStream and the CryptoStream
            memoryStream.Close();
            cryptoStream.Close();
        }

        // Return the decrypted data as a string
        return plainText;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string message = "My secret message 1234";
        string password = "3sc3RLrpd17";

        // Create sha256 hash
        SHA256 mySHA256 = SHA256Managed.Create();
        byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));

        // Create secret IV
        byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

        string encrypted = this.EncryptString(message, key, iv);
        string decrypted = this.DecryptString(encrypted, key, iv);

        Console.WriteLine(encrypted);
        Console.WriteLine(decrypted);
    }
odan
  • 4,757
  • 5
  • 20
  • 49
  • 1
    Thanks Daniel... Let me try your provided C# and PHP functions... I will update you on this in short time. – user3581428 Aug 09 '17 at 06:26
  • Thank you so much! I was looking for this ! Which perfectly reproduce the behavior of the java library https://github.com/scottyab/AESCrypt-Android – Pecana Feb 28 '20 at 08:28
0

As @odan given , minor changes for those how needed PHP, openssl_encrypt with AES-128-CBC , key and IV, below PHP code

$plaintext = 'My secret message 1234';
$key = '3d756227f8be6f85';
// CBC has an IV and thus needs randomness every time a message is encrypted
$method = 'AES-128-CBC';
$iv = 'ba7e0bb79b61f82d';

$cipher  =   openssl_encrypt($plaintext, $method, $key, $options=OPENSSL_RAW_DATA,$iv );
$body=       base64_encode($cipher);
echo $body;
$decrypted = openssl_decrypt($cipher, $method, $key, OPENSSL_RAW_DATA, $iv);
echo ' decrypted to: ' . $decrypted . "\n\n";

and C# code link in fiddle also : https://dotnetfiddle.net/LE8lTx

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program
{
    public static void Main()
    {
        string message = "My secret message 1234";
        string password = "3d756227f8be6f85";
        string ivstr = "ba7e0bb79b61f82d";  
        
        Program p=new Program();

        string encrypted = p.EncryptString(message, password, ivstr);
        string decrypted = p.DecryptString(encrypted, password, ivstr);
                

        Console.WriteLine(encrypted);
        Console.WriteLine(decrypted);
        
    }
    
    public  string EncryptString(string plainText, string password,string ivstr)
    {
         byte[] key = Encoding.UTF8.GetBytes(password);
         byte[] iv = Encoding.UTF8.GetBytes(ivstr);
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;

        // Set key and IV
        byte[] aesKey = new byte[16];
        Array.Copy(key, 0, aesKey, 0, 16);
        encryptor.Key = aesKey;
        encryptor.IV = iv;

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

        // Convert the plainText string into a byte array
        byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

        // Encrypt the input plaintext string
        cryptoStream.Write(plainBytes, 0, plainBytes.Length);

        // Complete the encryption process
        cryptoStream.FlushFinalBlock();

        // Convert the encrypted data from a MemoryStream to a byte array
        byte[] cipherBytes = memoryStream.ToArray();

        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();

        // Convert the encrypted byte array to a base64 encoded string
        string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);

        // Return the encrypted data as a string
        return cipherText;
    }

    public  string DecryptString(string cipherText,  string password,string ivstr)
    {
         byte[] key = Encoding.UTF8.GetBytes(password);
         byte[] iv = Encoding.UTF8.GetBytes(ivstr);
        
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;

        // Set key and IV
        byte[] aesKey = new byte[16];
        Array.Copy(key, 0, aesKey, 0, 16);
        encryptor.Key = aesKey;
        encryptor.IV = iv;

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

        // Will contain decrypted plaintext
        string plainText = String.Empty;

        try
        {
            // Convert the ciphertext string into a byte array
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Decrypt the input ciphertext string
            cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

            // Complete the decryption process
            cryptoStream.FlushFinalBlock();

            // Convert the decrypted data from a MemoryStream to a byte array
            byte[] plainBytes = memoryStream.ToArray();

            // Convert the decrypted byte array to string
            plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
        }
        finally
        {
            // Close both the MemoryStream and the CryptoStream
            memoryStream.Close();
            cryptoStream.Close();
        }

        // Return the decrypted data as a string
        return plainText;
    }
}
Somnath Kadam
  • 6,051
  • 6
  • 21
  • 37
0

I suggest you use similar classes I have already written in C# and PHP for this purpose:

My Cryptography class in PHP

class Cryptography{
    private $Method = 'aes-256-cbc';
    private $Password = null;
    private $Cost = 12;

    public function __construct($password = null, $cost = null){
        $this->Password = $password??"my default password";
        $this->Cost = $cost??12;
    }
    
    public function Encrypt($plaintext, $password = null, $cost = null){
        return base64_encode(
            openssl_encrypt(
                $plaintext, 
                $this->Method, 
                $this->GetKey($password, $cost),
                OPENSSL_RAW_DATA,
                $this->GetIV()
            )
        );
    }
    
    public function Decrypt($ciphertext, $password = null, $cost = null){
        return openssl_decrypt(
            base64_decode($ciphertext),
            $this->Method,
            $this->GetKey($password, $cost),
            OPENSSL_RAW_DATA,
            $this->GetIV()
        );
    }
    
    
    private function GetKey($password = null, $cost = null){
        return password_hash($password??$this->Password, PASSWORD_BCRYPT, ['cost' => $cost??$this->Cost]);
    }
    private function GetIV(){
        return chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);
    }
}

and this one is a similar class in C#

class Cryptography
{
    private string Password = null;
    private int Cost = null;

    public Cryptography(string password = null, int? cost = null)
    {
        Password = password??"my default password";
        Cost = cost??12;
    }

    public string Encrypt(string plainText, string password = null, int? cost = null)
    {
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;
        //encryptor.KeySize = 256;
        //encryptor.BlockSize = 128;
        //encryptor.Padding = PaddingMode.Zeros;

        // Set key and IV
        encryptor.Key = GetKey(password,cost).Take(32).ToArray();
        encryptor.IV = GetIV();

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

        // Convert the plainText string into a byte array
        byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

        // Encrypt the input plaintext string
        cryptoStream.Write(plainBytes, 0, plainBytes.Length);

        // Complete the encryption process
        cryptoStream.FlushFinalBlock();

        // Convert the encrypted data from a MemoryStream to a byte array
        byte[] cipherBytes = memoryStream.ToArray();

        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();

        // Convert the encrypted byte array to a base64 encoded string
        string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);

        // Return the encrypted data as a string
        return cipherText;
    }

    public string Decrypt(string cipherText, string password = null, int? cost = null)
    {
        // Instantiate a new Aes object to perform string symmetric encryption
        Aes encryptor = Aes.Create();

        encryptor.Mode = CipherMode.CBC;
        //encryptor.KeySize = 256;
        //encryptor.BlockSize = 128;
        //encryptor.Padding = PaddingMode.Zeros;

        // Set key and IV
        encryptor.Key = GetKey(password, cost).Take(32).ToArray();
        encryptor.IV = GetIV();

        // Instantiate a new MemoryStream object to contain the encrypted bytes
        MemoryStream memoryStream = new MemoryStream();

        // Instantiate a new encryptor from our Aes object
        ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

        // Instantiate a new CryptoStream object to process the data and write it to the 
        // memory stream
        CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

        // Will contain decrypted plaintext
        string plainText = String.Empty;

        try
        {
            // Convert the ciphertext string into a byte array
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Decrypt the input ciphertext string
            cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

            // Complete the decryption process
            cryptoStream.FlushFinalBlock();

            // Convert the decrypted data from a MemoryStream to a byte array
            byte[] plainBytes = memoryStream.ToArray();

            // Convert the decrypted byte array to string
            plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
        }
        finally
        {
            // Close both the MemoryStream and the CryptoStream
            memoryStream.Close();
            cryptoStream.Close();
        }

        // Return the decrypted data as a string
        return plainText;
    }

    private byte[] GetKey(string password = null, int? cost = null)
    {
        // hash the password with BCrypt
        string hashedPassword = BCrypt.Net.BCrypt.HashPassword(password??Password, cost??Cost);

        // Convert hashed password to array
        return Encoding.ASCII.GetBytes(hashedPassword);
    }
    private byte[] GetIV()
    {
        // Create secret IV
        return new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
    }

}

reference: https://gist.github.com/Oranzh/2520823f9d1cea603e60b8e8f3fe1d36

Enjoy...

MiMFa
  • 981
  • 11
  • 14