简体   繁体   中英

C# encrypt/decrypt methods which are equivalent to PHP7 openssl

I have the following lines in a PHP 7 program encrypting/decrypting data:

$key = base64_decode("mykey===");
$iv = substr(hash('sha256', "myiv======"), 0, 16);
printf(base64_encode(openssl_encrypt("hello", "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv)));
printf("<br>");
printf(openssl_decrypt(base64_decode("2XJxQXSbPuJ9LMsZ/FESGw=="), "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));

This is working, PHP decrypts "hello" to "2XJxQXSbPuJ9LMsZ/FESGw==" and vice versa. However I'm trying to decrypt and encrypt the same data (from a Database) with C# but can't seem to figure it out. I used the following method for decryption (C#):

private string aes_decrypt(string cipherText, string key, string iv)
    {
        RijndaelManaged aes = new RijndaelManaged();
        aes.KeySize = 256;
        aes.BlockSize = 128;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.None;
        aes.Key = Convert.FromBase64String(key);
        aes.IV = Encoding.UTF8.GetBytes(iv);

        if (aes.Key.Length < 32)
        {
            var paddedkey = new byte[32];
            Buffer.BlockCopy(aes.Key, 0, paddedkey, 0, aes.Key.Length);
            aes.Key = paddedkey;
        }

        var decrypt = aes.CreateDecryptor();
        byte[] xBuff = null;
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
            {
                byte[] xXml = Convert.FromBase64String(cipherText);
                cs.Write(xXml, 0, xXml.Length);
            }

            xBuff = ms.ToArray();
        }

        String Output = Encoding.UTF8.GetString(xBuff);
        return Output;

    }

But a call to this method:

string encryptionkey = "mykey===";
string encryptioniv = GenerateSHA256String("myiv======").Substring(0, 16);
string str = aes_decrypt("2XJxQXSbPuJ9LMsZ/FESGw==", encryptionkey, encryptioniv);
Console.WriteLine(@str);

returns: HellO++++??????+

The encryption method doesnt seem to work either (referenced online and modified):

private static String EncryptIt(String s, string akey, string aIV)
    {
        String result;
        byte[] key = Convert.FromBase64String(akey);
        byte[] IV = Encoding.UTF8.GetBytes(aIV);

        RijndaelManaged rijn = new RijndaelManaged();
        rijn.Mode = CipherMode.CBC;
        rijn.Padding = PaddingMode.PKCS7;
        rijn.KeySize = 256;
        rijn.BlockSize = 128;

        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(s);
                    }
                }
            }
            result = Convert.ToBase64String(msEncrypt.ToArray());
        }
        rijn.Clear();

        return result;
    }

A call to this method: EncryptIt("hello", encryptionkey, encryptioniv); returns ul0axDR0WWGcpeijPRNusg== and not 2XJxQXSbPuJ9LMsZ/FESGw== which was generated by PHP. Anyone knows what's wrong here?

For reference, I used these methods with the IV, they are working without errors:

private string GenerateSHA256String(string inputString)
    {
        SHA256 sha256 = SHA256Managed.Create();
        byte[] bytes = Encoding.UTF8.GetBytes(inputString);
        byte[] hash = sha256.ComputeHash(bytes);
        return GetStringFromHash(hash);
    }
    private string GetStringFromHash(byte[] hash)
    {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            result.Append(hash[i].ToString("X2"));
        }
        return result.ToString();
    }

Old question, but I ran into this again recently.

When using PHP 7.2 openssl_decrypt/openssl_encrypt padding as OPENSSL_RAW_DATA, it only worked for me when the chsarp AES padding was set to PaddingMode.PKCS7.

The original post has PaddingMode.None for decrypt and PaddingMode.PKCS7 for encrypt.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM