OpenSSL加密无法解密C#

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenSSL加密无法解密C#相关的知识,希望对你有一定的参考价值。

我一直在努力解密一些通过SSL在Unix机器上加密的数据,我不断得到填充错误,并且不确定我错过了什么。

加密文件是一个简单的文本文件,只是说“Hello World”。

unix中使用的加密命令是:

openssl enc -base64 -aes-256-cbc  -k 12345678901234567890123456789012 -in test.txt -out cbc64.txt

我有两种方法可用于解密:

private static CipherMode sCipherMode = CipherMode.CBC;
private static PaddingMode sPaddingMode = PaddingMode.PKCS7;
private const int HigKeyLen = 32;
private const int HigKeySiz = 256;

public static string decrypt(string text, //the text to be decrypt                
    int cipherindex// the strength of the original encryption
    )
{
    byte[] plainText = null;
    try
    {
        string tempText = Regex.Replace(text, @"
", "");
        //get the cipher strength--from cipherindex            
        CipherKey Key = CipherKey.getCipherKey(cipherindex);
        //build and init the Decryptor
        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        rijndaelCipher.Mode = sCipherMode;
        rijndaelCipher.Padding = sPaddingMode;
        rijndaelCipher.KeySize = Key.Size;
        rijndaelCipher.BlockSize = Key.Size;
        byte[] encryptedData = Convert.FromBase64String(tempText);
        byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(pass);
        byte[] keyBytes = new byte[Key.Len];


        int len = pwdBytes.Length;
        if (len > keyBytes.Length)
        {
            len = keyBytes.Length;
        }
        Array.Copy(pwdBytes, keyBytes, len);

        rijndaelCipher.Key = keyBytes;
        rijndaelCipher.IV = keyBytes;
        ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
        plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

    }
    catch (Exception e)
    {
        // test code, do nothing
    }
    return System.Text.Encoding.UTF8.GetString(plainText);
}

这将返回以下错误:填充无效,无法删除。

第二种方法:

public static string Decryptor(string TextToDecrypt)
    {

        byte[] EncryptedBytes = Convert.FromBase64String(Regex.Replace(TextToDecrypt, @"
", ""));

        //Setup the AES provider for decrypting.            
        AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
        //aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
        //aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
        aesProvider.BlockSize = 128;
        aesProvider.KeySize = 256;
        //My key and iv that i have used in openssl
        aesProvider.Key = System.Text.Encoding.UTF8.GetBytes(pass);
        aesProvider.IV = System.Text.Encoding.UTF8.GetBytes(pass);
        aesProvider.Padding = PaddingMode.PKCS7;
        aesProvider.Mode = CipherMode.CBC;

        ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
        byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
        return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
    }

第二种方法由于密码不是块大小的正确长度而产生问题。

我做错了什么?

答案

你openssl命令是错误的,我认为它应该是: openssl enc -base64 -aes-256-cbc -k 12345678901234567890123456789012 -in test.txt -out cbc64.txt

阅读你的代码我看到你做了一些错误的假设:

  • 您正在使用密码作为密钥和IV(您从哪里获得?)密码不是密钥
  • 你假设输出是纯密文

尝试将-p参数添加到openssl enc命令,它将显示salt和派生密钥和iv

所以我们来修复一下:

  1. OpenSSL生成随机的8字节盐
  2. OpenSSL使用其“魔法”函数EVP_BytesToKey从密码和盐中导出密钥和IV,qazxsw poi
  3. OpenSSL输出如下:base64(Salted_ {salt} {ciphertext})

以上是关于OpenSSL加密无法解密C#的主要内容,如果未能解决你的问题,请参考以下文章

使用OpenSSL进行AES-256 / CBC加密并使用C#进行解密

使用openssl加密和解密一个小文件

c语言中的openssl aes解密

使用 OpenSSL/C++ 和 PHP/Mcrypt 的 AES-128-CBC 加密:仅解密第一个块

Openssl及加密解密数据加密解密及CA原理

Openssl及加密解密openssl