首页 > 解决方案 > 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();
    }

标签: c#phpencryption.net-4.5php-7.2

解决方案


老问题,但我最近又遇到了这个问题。

当使用 PHP 7.2 openssl_decrypt/openssl_encrypt 填充作为 OPENSSL_RAW_DATA 时,它仅在 chsarp AES 填充设置为 PaddingMode.PKCS7 时对我有效。

原始帖子具有用于解密的 PaddingMode.None 和用于加密的 PaddingMode.PKCS7。


推荐阅读