与PHP7 openssl等效的C#加密/解密方法

时间:2018-08-15 21:13:46

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

在PHP 7程序中,以下行用于加密/解密数据:

$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));

这是可行的,PHP将“ hello”解密为“ 2XJxQXSbPuJ9LMsZ / FESGw ==“,反之亦然。但是,我正在尝试使用C#对相同的数据(从数据库)解密和加密,但似乎无法弄清楚。我使用以下方法进行解密(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;

    }

但是对此方法的调用:

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

返回:HellO ++++ ?????? +

加密方法似乎也不起作用(在线引用和修改):

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;
    }

对此方法的调用:EncryptIt(“ hello”,encryptionkey,encryptioniv);返回ul0axDR0WWGcpeijPRNusg ==,而不是PHP生成的2XJxQXSbPuJ9LMsZ / FESGw ==。有人知道这是怎么回事吗?

作为参考,我将这些方法与IV一起使用,它们可以正常工作:

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();
    }

1 个答案:

答案 0 :(得分:0)

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

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

原始帖子具有PaddingMode。无用于解密,具有PaddingMode.PKCS7用于加密。