0

An existing C# implementation encrypts a string by implementing RijndaelManaged() as follows:

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

namespace sample
{
    class Program
    {
        static void Main(string[] args)
        {
            var sKey = "ABCDEF0123456789ABCDEF0123456789";
            var sData = "Some Data"; 

            var bData = Encoding.ASCII.GetBytes(sData);

            var oAes = new RijndaelManaged();
            oAes.Key = Encoding.ASCII.GetBytes(sKey.Substring(0, 32));
            oAes.IV = Encoding.ASCII.GetBytes(sKey.Substring(0, 16));
            var bEncrypted = oAes.CreateEncryptor(oAes.Key, oAes.IV).TransformFinalBlock(bData, 0, bData.Length);

            Console.WriteLine(Convert.ToBase64String(bEncrypted));
            // Output: NXyPbSVtB5LomNcsPK7cgg==
        }
    }
}

A php implementation must produce the same result, given the same input, so that the two resulting strings may be compared.

All of the libraries that I have tried lack a method similar to TransformFinalBlock().

Unfortunately, the C# implementation cannot be changed - we have to find a working php implementation.

A similar php implementation (using the phpseclib/phpseclib library) follows:

<?php

function getBytes($s) {
    $result = '';
    for ($i = 0; $i < mb_strlen($s, 'ASCII'); $i++) {
        $result .= ord($s[$i]);
    }
    return $result;
}

$sKey = "ABCDEF0123456789ABCDEF0123456789";
$sData = "Some Data"; 

$bData = getBytes($sData);
$bKey = getBytes(substr($sKey, 0, 32));
$bIV = getBytes(substr($sKey, 0, 16));

include 'vendor/autoload.php';
$oAes = new \phpseclib\Crypt\Rijndael(2); // MODE_CBC - Default for RijndaelManaged()
$oAes->setBlockLength(128); // Default for RijndaelManaged()
$oAes->setKey($bKey);
$oAes->setIV($bIV);
$bEncrypted = $oAes->encrypt($bData);

echo(base64_encode($bEncrypted)); 
// Output: HwznolyEl6472Hm0rbNzINEa6LUwo4O4UAWd90P9PUg=

How can the same result be achieved in php?

Werner
  • 3,523
  • 1
  • 22
  • 21
  • Make sure you match the padding algorithm also. – Seva Alekseyev Apr 19 '18 at 12:33
  • Maybe you just don't need to use those `getBytes` in php? Side note: using half of your key as IV is not a very good idea. – Evk Apr 19 '18 at 12:37
  • @SevaAlekseyev `PKCS7` padding is used by default on the .net side, but phpseclib seems to use `PKCS12` by default. I cannot see a way to change the padding in phpseclib, though. – Werner Apr 19 '18 at 12:42
  • @Evk Agreed, but as I have mentioned, the C# implementation has already been implemented like that, we had no control or influence in its implementation. – Werner Apr 19 '18 at 12:43
  • Well anyway I'd start with removing all `getBytes` calls. – Evk Apr 19 '18 at 12:45
  • @Evk I have verified that `getBytes()` produces the same output as `Encoding.ASCII.GetBytes()`. Please keep in mind that we need to 'clone' the existing C# functionality, hence the `getBytes()` function that emulates `Encoding.ASCII.GetBytes()`. – Werner Apr 19 '18 at 12:49
  • 1
    You are now encrypting string with digits in php, not "array of bytes". – Evk Apr 19 '18 at 13:02
  • 1
    To clarify above comment, getBytes creates string with digits, for example "8311110910132689711697", and that's what you encrypt instead of "Some Data". You might notice that because this string is longer than "Some Data" - your resulting base64 string is also longer (since AES is block cipher). Same story with key and iv. – Evk Apr 19 '18 at 13:48
  • @Evk Thanks, you are correct, Encoding.ASCII.GetBytes indeed returns array of Bytes – Werner Apr 19 '18 at 15:00

0 Answers0