Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AES-256-CBC解密错误,声明填充无效且无法删除_C#_Php_Encryption_Cryptography - Fatal编程技术网

C# AES-256-CBC解密错误,声明填充无效且无法删除

C# AES-256-CBC解密错误,声明填充无效且无法删除,c#,php,encryption,cryptography,C#,Php,Encryption,Cryptography,我有一个PHP应用程序,它使用openSSL向.NET应用程序发送一个AES-256-CBC加密字符串和Base64编码。我启动了decrypt方法,但当我尝试实际解密数据时,总是出错。错误状态为“填充无效,无法删除”。我做错了什么 PHP函数生成的加密Base64值为: p07cNwcvcYLxvYHCUsmZqKYr40IXXYjEHr7r+JdgXiJT5/wpDSDmr48JLOXyNEL7 关键是: M2AZULUALPHA 盐是: TripBuilder2017x PHP函数是: f

我有一个PHP应用程序,它使用openSSL向.NET应用程序发送一个AES-256-CBC加密字符串和Base64编码。我启动了decrypt方法,但当我尝试实际解密数据时,总是出错。错误状态为“填充无效,无法删除”。我做错了什么

PHP函数生成的加密Base64值为: p07cNwcvcYLxvYHCUsmZqKYr40IXXYjEHr7r+JdgXiJT5/wpDSDmr48JLOXyNEL7

关键是: M2AZULUALPHA

盐是: TripBuilder2017x

PHP函数是:

function encrypt($text) {
$key = "M2AZULUALPHA";
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($text) % $block);
$text .= str_repeat(chr($padding), $padding);

$crypttext = openssl_encrypt($text,'aes-256-cbc', $key,  OPENSSL_RAW_DATA, 'TripBuilder2017x');
return base64_encode($crypttext);
}

.NET解密函数:

 private string Decrypt(string cipherText)
        {
            string EncryptionKey = "M2AZULUALPHA";
            byte[] saltArray = Encoding.ASCII.GetBytes("TripBuilder2017x");


            byte[] cipherBytes = Convert.FromBase64String(cipherText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, saltArray);
                encryptor.Mode = CipherMode.CBC;
                encryptor.BlockSize = 128;
                encryptor.KeySize = 256;
                encryptor.Padding = PaddingMode.PKCS7;
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);

                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }
                    cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }


            }
            return cipherText;
        }
更新我去了一个在线openSSL解密工具,输入了我的IV、密钥和base64文本。它生成了正确的字符串,但字符串中有一些奇怪的块

更新2 下面是更新的PHP代码。我还将密钥大小增加到16字节。我仍然收到同样的错误

$key = "M2AZULUALPHAECHO";
$salt = "TripBuilder2017x";
$mode = "aes-256-cbc";
$text = "BrassMonkey";

function encrypt($text,$key,$salt,$mode) {

    return base64_encode(encryptplain($text,$key,$salt,$mode));
}

function encryptplain($text,$key,$salt,$mode) {


    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $padding = $block - (strlen($text) % $block);
    $text .= str_repeat(chr($padding), $padding);

    $crypttext = openssl_encrypt($text, $mode, $key, 1, $salt);
    return ($crypttext);
}
更新3:我的.NET代码

private string Decrypt(string cipherText)
        {
            string EncryptionKey = "M2AZULUALPHAECHO";
            byte[] saltArray = Encoding.ASCII.GetBytes("TripBuilder2017x");

            byte[] cipherBytes = Convert.FromBase64String(cipherText);
            using (Aes encryptor = Aes.Create())
            {

                encryptor.Mode = CipherMode.CBC;
                encryptor.BlockSize = 128;
                encryptor.KeySize = 256;
                encryptor.Padding = PaddingMode.PKCS7;
                encryptor.Key = Encoding.ASCII.GetBytes(EncryptionKey);
                encryptor.IV = saltArray;

                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }
                    cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }


            }
            return cipherText;
        }

我可以看到几个迫在眉睫的问题:

  • 您的C#解密代码使用PBKDF2从密码和salt中派生出AES密钥和IV,而PHP加密代码直接使用密码和salt作为AES密钥和IV。如果希望它正常工作,您需要在这两个位置使用相同的逻辑
  • 在计算块长度和填充输入时,您在PHP代码中指定了错误的加密算法-Rijndael的各种版本都是根据其长度命名的,而AES的所有版本都有128位块长度(即Rijndael-128)并使用不同的密钥长度。因此,如果需要适当的填充,则需要指定MCRYPT_RIJNDAEL_128
  • 在加密过程中,您不应该自己执行填充,除非您还指定了OPENSSL_ZERO_padding标志-如果您未能指定此标志,OPENSSL将向输入文本添加其自己的PKCS#7填充,并将其扩展另一个块,而您的解密逻辑将仅剥离该部分,忽略手动添加的填充(并导致您使用联机OpenSSL解密工具观察到的“字符串中的奇怪块”)
  • 您需要确保指定的AES密钥大小实际上与指定的算法匹配-PHP的openssl_encrypt()函数扩展了密钥大小(使用空字节)为了匹配您指定的算法,C#将自动调整算法以匹配您提供的密钥大小。在这种情况下,您的C#代码实际上正在执行AES-128解密,这与PHP代码中执行的AES-256加密不兼容
  • 其他备注:

  • 如果希望从openssl_encrypt()获得Base64编码的结果,可以省略openssl_RAW_DATA标志,它将返回Base64编码的密文
  • 问题#1的正确解决方案应该是在两个位置执行密钥派生,或者使用二进制密钥和IV值-明文密钥的熵要小得多,安全性也要低得多
  • 您不应该在代码中硬编码密钥和IV-密钥应作为参数提供,并且IV应随机生成并随后与密文关联

  • 我可以看到几个迫在眉睫的问题:

  • 您的C#解密代码使用PBKDF2从密码和salt中派生出AES密钥和IV,而PHP加密代码直接使用密码和salt作为AES密钥和IV。如果希望它正常工作,您需要在这两个位置使用相同的逻辑
  • 在计算块长度和填充输入时,您在PHP代码中指定了错误的加密算法-Rijndael的各种版本是根据其长度命名的,而AES的所有版本都有128位块长度(即Rijndael-128)并使用不同的键长度。因此,如果需要适当的填充,则需要指定MCRYPT_RIJNDAEL_128
  • 在加密过程中,您不应该自己执行填充,除非您还指定了OPENSSL_ZERO_padding标志-如果您未能指定此标志,OPENSSL将向输入文本添加其自己的PKCS#7填充,并将其扩展另一个块,而您的解密逻辑将仅剥离该部分,忽略手动添加的填充(并导致您使用联机OpenSSL解密工具观察到的“字符串中的奇怪块”)
  • 您需要确保指定的AES密钥大小实际上与指定的算法匹配-PHP的openssl_encrypt()函数扩展了密钥大小(使用空字节)为了匹配您指定的算法,C#将自动调整算法以匹配您提供的密钥大小。在这种情况下,您的C#代码实际上正在执行AES-128解密,这与PHP代码中执行的AES-256加密不兼容
  • 其他备注:

  • 如果希望从openssl_encrypt()获得Base64编码的结果,可以省略openssl_RAW_DATA标志,它将返回Base64编码的密文
  • 问题#1的正确解决方案应该是在两个位置执行密钥派生,或者使用二进制密钥和IV值-明文密钥的熵要小得多,安全性也要低得多
  • 您不应该在代码中硬编码密钥和IV-密钥应作为参数提供,并且IV应随机生成并随后与密文关联

  • 我遇到了类似的问题,我的结论是openssl不会返回任何二进制数据:(,我使用了mcrypt Instead,但mcrypt也有同样的问题,这就是我尝试OpenSSL的原因。由于我遇到了同样的错误,我觉得这与我正在为其赋值的属性有关。我不建议使用mcrypt,因为这在当前的PHP版本中是一个不推荐使用的函数。在线查看器中的块可能是字符不可用的原因