-1

I need to exactly convert this .NET function in PHP Language, any help?

I've tried different solutions found on StackOverflow, but no-one seems work for me.

internal string Encrypt(string plaintext, string password)
{
    RijndaelManaged rijndaelCipher = new RijndaelManaged();

    byte[] plaintextByte = System.Text.Encoding.Unicode.GetBytes(plaintext);
    byte[] saltByte = Encoding.ASCII.GetBytes(password.Length.ToString());

    PasswordDeriveBytes secretKey = new PasswordDeriveBytes(password, saltByte);
    ICryptoTransform encryptor = rijndaelCipher.CreateEncryptor(secretKey.GetBytes(32), secretKey.GetBytes(16));
    MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

    cryptoStream.Write(plaintextByte, 0, plaintextByte.Length);
    cryptoStream.FlushFinalBlock();

    byte[] cipherBytes = memoryStream.ToArray();

    memoryStream.Close();
    cryptoStream.Close();
    encryptor.Dispose();

    return Convert.ToBase64String(cipherBytes);
}

Thanks!

EDIT:

Here one of the code I've tried:

class Crypt
{
private $key,$iv_size,$iv;

/**
 * constructor
 * @param $key (string:'TheKey')
 * @return void
 */
function __construct($key='TheKey'){
    $this->key = trim($key);
    $this->iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);
}

public function encrypt($string){
    $string=trim($string);
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $string, MCRYPT_MODE_ECB, $this->iv));
}
}
  • plz share the code what you've tried in PHP, thanks – Syed Ekram Uddin Jun 11 '19 at 09:07
  • How do we know what you tried, what does "*but no-one seems work for me*" mean, surely you can see the problem with this – TheGeneral Jun 11 '19 at 09:08
  • Possible duplicate of [How do I convert this C# Rijndael encryption to PHP?](https://stackoverflow.com/questions/9011635/how-do-i-convert-this-c-sharp-rijndael-encryption-to-php) – Bùi Đức Khánh Jun 11 '19 at 09:18
  • I've tried several codes, also the one suggested by @BùiĐứcKhánh and the one I've downloaded here https://www.phpclasses.org/browse/file/31455.html (added code in original question) – Roberta QPC Jun 11 '19 at 09:22
  • 1
    Rijndael is otherwise known as AES. Are you sure there isn't an AES encryption library in PHP already? – Steve Todd Jun 11 '19 at 09:25
  • 1
    @SteveTodd I would guess the main issue is the use of `PasswordDeriveBytes`. Thus we would also need PBKDF1 functionality in PHP and provide it with whatever values (especially iterations) PasswordDeriveBytes uses internally. – ckuri Jun 11 '19 at 09:30
  • On a side note: You shouldn't really use this encryption functions as its just bad. It's deriving the salt from the password and thus each message will be encrypted with the same salt, which is a no-go. Also the use of [PasswordDeriveBytes.GetBytes(int)](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.passwordderivebytes.getbytes?view=netframework-4.8) is obsolete. – ckuri Jun 11 '19 at 09:32
  • @ckuri I guessed that this code could be obsolete, but this is what the web api documentation reports. I'm not using .NET at all, I just need to call this web service using CURL from a Wordpress website – Roberta QPC Jun 11 '19 at 09:36
  • @SteveTodd I'm trying to use `base64_encode(openssl_encrypt($string, 'aes-256-ecb', $key, OPENSSL_RAW_DATA));` – Roberta QPC Jun 11 '19 at 10:18
  • @Roberta QPC, your problem appears to be the use of the PasswordDeriveBytes class, which is part of the System.Security.Cryptography library. As others have mentioned, it is used badly anyway. Do you have any scope for changing the C# code? – Steve Todd Jun 11 '19 at 11:09
  • @SteveTodd no, unfortunately, it's a third party web service – Roberta QPC Jun 11 '19 at 13:35
  • The problem you have then is the PasswordDeriveBytes class. I wouldn't even TRY to convert it, instead try using the original using https://www.php.net/manual/en/class.dotnet.php – Steve Todd Jun 11 '19 at 17:08

1 Answers1

0

I got the solution from web service developer, it works fine!

<?php
class RijndaelOpenSSL
{
    const METHOD = 'aes-256-cbc';
    private $pbkdfBase = '';
    private $pbkdfExtra = '';
    private $pbkdfExtracount = 0;
    private $pbkdfHashno = 0;
    private $pbkdfState = 0;
    private $iterations = 100;

    public function reset()
    {
        $this->pbkdfBase = '';
        $this->pbkdfExtra = '';
        $this->pbkdfExtracount = 0;
        $this->pbkdfHashno = 0;
        $this->pbkdfState = 0;
    }

    public function decrypt($inputText, $password)
    {
        $this->reset();
        $salt = (string) mb_strlen($password);
        $key = $this->pbkdf1($password, $salt, 32);
        $iv = $this->pbkdf1($password, $salt, 16);
        $decrypted = openssl_decrypt(base64_decode($inputText), self::METHOD, $key, OPENSSL_RAW_DATA, $iv);
        return mb_convert_encoding($decrypted, 'UTF-8', 'UTF-16LE');
    }

    public function encrypt($inputText, $password)
    {
        $this->reset();
        $salt = (string) mb_strlen($password);
        $key = $this->pbkdf1($password, $salt, 32);
        $iv = $this->pbkdf1($password, $salt, 16);
        $textUTF = mb_convert_encoding($inputText, 'UTF-16LE');
        $encrypted = openssl_encrypt($textUTF, self::METHOD, $key, OPENSSL_RAW_DATA, $iv);
        return base64_encode($encrypted);
    }

    private function pbkdf1($pass, $salt, $countBytes)
    {
        if ($this->pbkdfState == 0) {
            $this->pbkdfHashno = 0;
            $this->pbkdfState = 1;
            $key = $pass . $salt;
            $this->pbkdfBase = sha1($key, true);
            for ($i = 2; $i < $this->iterations; $i++) {
                $this->pbkdfBase = sha1($this->pbkdfBase, true);
            }
        }
        $result = '';
        if ($this->pbkdfExtracount > 0) {
            $rlen = strlen($this->pbkdfExtra) - $this->pbkdfExtracount;
            if ($rlen >= $countBytes) {
                $result = substr($this->pbkdfExtra, $this->pbkdfExtracount, $countBytes);
                if ($rlen > $countBytes) {
                    $this->pbkdfExtracount += $countBytes;
                } else {
                    $this->pbkdfExtra = null;
                    $this->pbkdfExtracount = 0;
                }
                return $result;
            }
            $result = substr($this->pbkdfExtra, $rlen, $rlen);
        }
        $current = '';
        $clen = 0;
        $remain = $countBytes - strlen($result);
        while ($remain > $clen) {
            if ($this->pbkdfHashno == 0) {
                $current = sha1($this->pbkdfBase, true);
            } else if ($this->pbkdfHashno < 1000) {
                $num = sprintf('%d', $this->pbkdfHashno);
                $tmp = $num . $this->pbkdfBase;
                $current .= sha1($tmp, true);
            }
            $this->pbkdfHashno++;
            $clen = strlen($current);
        }
        // $current now holds at least as many bytes as we need
        $result .= substr($current, 0, $remain);
        // Save any left over bytes for any future requests
        if ($clen > $remain) {
            $this->pbkdfExtra = $current;
            $this->pbkdfExtracount = $remain;
        }
        return $result;
    }
}
Pedram
  • 828
  • 9
  • 24