Home > Software engineering >  openssl encryption in php decrypts incorrectly with c# .NET
openssl encryption in php decrypts incorrectly with c# .NET

Time:12-11

I encrypt some data in PHP with openssl and try to decrypt it with the C# .NET cryptography methods. The result is a data block that's correct in size, but the data itself is incorrect. I'm sure I'm missing something trivial, but I've been at it for days for now and I can't seem to figure it out. (The reverse, encrypting in C# and decrypting in PHP works fine, so the methods provided are compatible.)

PHP code:

function encrypt($data, $key)
    {
    $method = "AES-256-CBC";
    $ivSize = openssl_cipher_iv_length($method);
    $iv = openssl_random_pseudo_bytes($ivSize);
    $encrypted = openssl_encrypt($data, $method, $key, 0, $iv);

    return array(strlen($data), $iv, $encrypted);
    }

[Code for handling other stuff here.]

if (!empty($_GET["upKey"]))
    {
    $upKey = str_replace(" ", " ", $_GET["upKey"]);
    if (openssl_private_decrypt(base64_decode($upKey), $decryptedUpKey, $privateKey))
        {
        $toEncrypt = file_get_contents("filename");
        $encryptionData = array(0, 0, 0);
        $encryptionData = encrypt($toEncrypt, $decryptedUpKey);
        echo $encryptionData[0]."\n".base64_encode($encryptionData[1])."\n".base64_encode($encryptionData[2])."\n\nKey: ".base64_encode($decryptedUpKey)."\nPlaintext: ".bin2hex($toEncrypt);
        }
    }

C# code:

byte[] upKey = new byte[32];
for (int i=0; i<32; i  )
    {
    upKey[i] = (byte) rand.Next(0, 256);
    }

byte[] encryptedUpKey = rsa.Encrypt(upKey, false);
string finalResult = await client.GetStringAsync("http://www.websitename.com/pagename.php?password="   Convert.ToBase64String(password)   "&upKey="   Convert.ToBase64String(encryptedUpKey));
            
Console.WriteLine("HTTP RESULT:\n\n" finalResult "\n");
string[] encryptionInfo = finalResult.Split("\n");
int length = Int32.Parse(encryptionInfo[0]);
byte[] IV = Convert.FromBase64String(encryptionInfo[1]);
byte[] data = Convert.FromBase64String(encryptionInfo[2]);

Console.WriteLine("\nLOCAL DATA:\n\nLen: "   length   "\nIV: "   Convert.ToBase64String(IV)   "\nKey: "   Convert.ToBase64String(upKey)   "\nData: "   Convert.ToBase64String(data)   "\n");

Console.WriteLine(binaryToString(decrypt(data, upKey, length, IV), false));

client is and HttpClient instance. The actual decryption method:

static byte[] decrypt(byte[] data, byte[] key, int? predefinedLength = null, byte[]? predefinedIV = null)
    {
    try
        {
        int length;
        if (predefinedLength == null)
            {
            length = BitConverter.ToInt32(data, 0);
            }
            else
            {
            length = (int) predefinedLength;
            }

        byte[] IV = new byte[16];

        if (predefinedIV == null)
            {
            for (int i = 4; i < 20; i  )
                {
                IV[i - 4] = data[i];
                }
            }
            else
            {
            IV = predefinedIV;
            }

        byte[] actualData;
        if (predefinedIV != null || predefinedLength != null)
            {
            actualData = data;
            }
            else
            {
            actualData = new byte[data.Length - 20];
            for (int i = 0; i < actualData.Length; i  )
                {
                actualData[i] = data[i   20];
                }
            }

        using (Aes aes = Aes.Create())
            {
            aes.Key = key;
            aes.IV = IV;

            if (predefinedIV != null || predefinedLength != null)
                {
                aes.Mode = CipherMode.CBC;
                }

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

            using (MemoryStream ms = new MemoryStream(actualData))
                {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    {
                    using (BinaryReader br = new BinaryReader(cs))
                        {
                        return br.ReadBytes(length);
                        }
                    }
                }
            }
        }
        catch (CryptographicException ce)
        {
        //Console.WriteLine(ce.Message);
        return new byte[0];
        }
    }

Output:

HTTP RESULT:

656 69X3YXiijHWxqgwI81Sj6g== QjRlazllS2EyaFBndHljUzdzbk9EbWxkb29renp6aWRMMTV4OHdJTXRtRzR3cnQvVkZsT2dJbk14c2MzdEFnd24wcFJJcS9weHR4bzFGMVJCVHF6NE1xU1BrQURrQnhxQkdET1RxdnkrUWZTU2c2NVVoU1h1MHN6blZVTXdQenhYcXkxdUIyT3lFYjJPaHh3Z2xZZ0VkWTViUFpwYVpCOFl1ZFIrTUVWNVV3VCtpWDF1SmVOeDVza1g1NHUxUG1WNXM3dkpKSklSYUl6VW5mSXR4QVNrNDU0NmFhcEt2K3ZCengyYWdFcTkyb2hZLzYwT3hPeTdybUJhclB3ZkhVYmVraW5vbCtLYUQ3aHA5NUVkMjdpOFluMXlJRDVkWnAzejBJankxRWhxQkNILzR0cFNkQVNBZDN1Wm9WV3RxTFVyVEZCYTFCT0JQcUp3Z3F1anJudXJsQ3VMSGNIdEIyeW4rODg1Sk8wd1JXTXA3R3hoOE45a1MvR09VdGpxSjNTUUd1b1Vya1U5NE0yZXFnd1R3UHZzbjdsUE5wb2VBODN3TUhTRkpSdkIxYkdMdDY4dkpPZHZQQ1JzWGtDTEY2VmZYY3ZMWDJHWllWZHlNNmtBYVpIWVFaZW5xQXQ5bUo1VEplQjlWd0VTYWp2U09DSUpJa1I5VXVlYmRINmRmWjV2WFVVZ2xWamJlLzNWMUxJVHJmZEVXYjIrSEFJVTM5OTc4S0daRG1WREplRFJpZ3lDSGdmMWc3bk5VeEwzcmxlNDVVQ0c4R2EwRDlFcUtIMWxQWllzUzV6YlJVYWNhTktxd2dvRUVVL3RSeTIzK0w5K0JoSll0WlZ1VGFLNlpJSWc4Q1JPbDVIbWU1N0cvYmE3dFdwZkhZY2J0TlV5c0xacWY5RmxIUXY3aks1OE04TWlkK29HL2lXRWFZdUt4WUZ5UEFtU0pwTnhSVTVBVzdhaVU0ZlBWenZBZkhDMDM4VEdnL3dRdVF1cGpjQzBESVB2SEVvRjFjQjdLZ3hJL1g2RmJEakFuRllaWDBJdFhxTlZ4c2h1SDREZkhKWllPZThJRDNvMXpIZkIyZmdUY3NaTXVvZTIrQk93WGdKSCsyWlJ3U3dSa0pIbVRGelZ0ZVdpUloxTVVhNW80cS9aU0xkQ1BObDdVMEVyQlVqUkxLM2FFT0lTR2ZmVVhzOUI1enk=

Key: Vhxi VF1PcWDi/IkP1Is1r86QBX6a/g8cdugW/JM/m0= Plaintext: 3800380030003000300030003000300036003000300043003400380044004600320043003900300037003200300035003800390043003800340045004600370045003600370043003300390038004600300045004200370046003100360032004600420044004300370031004100300046004400410033004400410044004600370041004100330031004400380044003200460041003000330037004300430032004100410041004200410044003000420043004100330045003400310039003900320038004200320037004100310031003800350034003100460034004300330032003400330044004100460039003700320037003800320031003100430038003200430046003700440030004600430039003700300038004600350038003800410045004200460035003800320036003600390046004600380039003800330035004400460038003300450037003600450033003800420043003600360044003700460034004300320036003900330030003400450033003800450037004300410043003600430031004300340042003800420031004400380046004600460044003200380037004500320042004400460030003900330038003700350038004500390035004100370036004500390044003000360039004300330034003500360037003300420030003600310045003400390043003500390041004500300032003600360033004200410038004200300039003300370031003700440033003100380034003200370044003600360031003600410043003900380033004600380035004300310039004100370043003600420033003800440033003600380033003200450036004600320031003300350038003900390041003500320042004200460036003500450038003500

LOCAL DATA:

Len: 656 IV: 69X3YXiijHWxqgwI81Sj6g== Key: Vhxi VF1PcWDi/IkP1Is1r86QBX6a/g8cdugW/JM/m0= Data: QjRlazllS2EyaFBndHljUzdzbk9EbWxkb29renp6aWRMMTV4OHdJTXRtRzR3cnQvVkZsT2dJbk14c2MzdEFnd24wcFJJcS9weHR4bzFGMVJCVHF6NE1xU1BrQURrQnhxQkdET1RxdnkrUWZTU2c2NVVoU1h1MHN6blZVTXdQenhYcXkxdUIyT3lFYjJPaHh3Z2xZZ0VkWTViUFpwYVpCOFl1ZFIrTUVWNVV3VCtpWDF1SmVOeDVza1g1NHUxUG1WNXM3dkpKSklSYUl6VW5mSXR4QVNrNDU0NmFhcEt2K3ZCengyYWdFcTkyb2hZLzYwT3hPeTdybUJhclB3ZkhVYmVraW5vbCtLYUQ3aHA5NUVkMjdpOFluMXlJRDVkWnAzejBJankxRWhxQkNILzR0cFNkQVNBZDN1Wm9WV3RxTFVyVEZCYTFCT0JQcUp3Z3F1anJudXJsQ3VMSGNIdEIyeW4rODg1Sk8wd1JXTXA3R3hoOE45a1MvR09VdGpxSjNTUUd1b1Vya1U5NE0yZXFnd1R3UHZzbjdsUE5wb2VBODN3TUhTRkpSdkIxYkdMdDY4dkpPZHZQQ1JzWGtDTEY2VmZYY3ZMWDJHWllWZHlNNmtBYVpIWVFaZW5xQXQ5bUo1VEplQjlWd0VTYWp2U09DSUpJa1I5VXVlYmRINmRmWjV2WFVVZ2xWamJlLzNWMUxJVHJmZEVXYjIrSEFJVTM5OTc4S0daRG1WREplRFJpZ3lDSGdmMWc3bk5VeEwzcmxlNDVVQ0c4R2EwRDlFcUtIMWxQWllzUzV6YlJVYWNhTktxd2dvRUVVL3RSeTIzK0w5K0JoSll0WlZ1VGFLNlpJSWc4Q1JPbDVIbWU1N0cvYmE3dFdwZkhZY2J0TlV5c0xacWY5RmxIUXY3aks1OE04TWlkK29HL2lXRWFZdUt4WUZ5UEFtU0pwTnhSVTVBVzdhaVU0ZlBWenZBZkhDMDM4VEdnL3dRdVF1cGpjQzBESVB2SEVvRjFjQjdLZ3hJL1g2RmJEakFuRllaWDBJdFhxTlZ4c2h1SDREZkhKWllPZThJRDNvMXpIZkIyZmdUY3NaTXVvZTIrQk93WGdKSCsyWlJ3U3dSa0pIbVRGelZ0ZVdpUloxTVVhNW80cS9aU0xkQ1BObDdVMEVyQlVqUkxLM2FFT0lTR2ZmVVhzOUI1enk=

77DB03C6CC26393BC0815D0394326AAAD931C973A23A06005AE9F08C044B3C5B8932E7655A47C1B78B439F9876D50C52A0723D5F083D0CA07DDD080BD31109772785E8C6C36564C5C10C0799EB99ABDB9894A6CF310969B9A8717B8FE879E713A34C301D93D4B2271E93632272A9497A4D14B996CA0D37A17B7EF2BEF26C83044173EF76AB6730D34AB5242B8C99B9176AEE12AF17E1AB0376E315D2B5F10A8AE7BE5ED4B5391582500146C54D41162FA766A789313916B501B64A35F2220E138759C572D0B0484AB48435EF31ACB01A2CD39D7F83807FC70606C21D57AA8AA61291B1A74561A8766E21A18B7BD04BB56BCC3604CDFE5748FF9345F395B5CDD3C3F841482AE750D1ABC19DD7681C6F817987CA68D6FF91DABA10BD2A7D0981F5F035F10E53347D4AEABF6061B2237C93F57FF6DDDB822239D62A59E782EE39E6C583078E3C98F2251A1062ED09CAD2BA9F72C2CF92259E8F2C6E8BF5F11FB481B57256214690C60BDDC7BFFDB86DF1AB9C7680DDEFCAF0B9D6F43ED7829C3FACA6BF4B8DF83CC16EB3950FB6215B1B598061EAACB1403B05B0D2CF28E65E2B0A2C800ED358852D7E3CDC29BC00571FEA26CB0B20D5F3E0B79F1FF366BC19DE23596BB489D40DE112CB3823E43CA739BE9580D8D8060E7E6E445DF25F10B3C7D2987BF7002182E8D1766CEB0326BF24F97BBCE0123F557DFC63A774C42212BCD6C3DECEAE76F831EFC7FF381D1E2926DABC2A787053294445BC3895828C6AF4709CE826E326CF153050CC20C527C5A482704A1EA44A3E6BCCBAA820FA2400F3DD03E58E715260F216DC648E6C793A33CACB8A584CF7B20C4AFBBA7E56D1BB5BB089695EB4BF8C6DBF9859AD03E017873F8A18DB194165DB4F78938ABD0035236FC63D7081D7336283D120C4273CA1D7F6

As you can see, everything, IV, key, method and plaintext matches, but the decryption still fails. What am I missing?

CodePudding user response:

Alright, thanks to Topaco's kind contribution I finally found out what the issue is. I needed to set the flag OPENSSL_RAW_DATA in the openssl_encrypt call. That's all it was.

  • Related