gpt4 book ai didi

c# - 无法弄清楚为什么 PHP 到 C# .NET 不会对称加密/解密

转载 作者:太空宇宙 更新时间:2023-11-03 23:47:14 24 4
gpt4 key购买 nike

我从事此工作已有一段时间,但我对 PHP 或 C# 了解不多。我们正在构建一个应用程序,该应用程序使用 AES 128 CBC 模式加密将内容存储在数据库中。一部分是 PHP 和 JS,另一部分是 C# .NET WPF。

编写 PHP 的人使用 Mcrypt 库进行加密/解密。我正在使用 Chilkat 库来加密/解密。 Chilkat 有一个默认的 C# 示例,它应该模仿 PHP Mcrypt。

目前我可以对称地加密/解密 .Net 上的东西,而 .Net 可以从 PHP 解密任何东西。但是,PHP 端无法解密我从 .Net 端加密到数据库的任何内容。

我至少缩小了部分编码问题的范围,但我不确定如何解决它。 PHP 端的解密方案通常解密为 ASCII,但对于我发送的内容,解密为 UTF-8。我尝试对其进行解密,然后将其从 UTF-8 编码为 ASCII,但无济于事。

我将向您展示输入/输出和功能。 IV 被设置为 16 个 ASCII 0,以帮助我进行调试,尽管它并不重要。

从 .Net 到 mcrypt_encrypt 函数的输入:字符串“1220”输出:3tRIG7qUxUsU7WoXDybRRcdQRobOfeFGtQ438V7XRD8=
参数入库='同上'

PHP端解密的输入func = 3tRIG7qUxUsU7WoXDybRRcdQRobOfeFGtQ438V7XRD8= '同上'

mcrypt_decrypt 函数的输出 = ��J����{$��Z'?u 'iconv says utf-8 encoding'

如果有任何帮助,我会得到的。我确定这是一些我看不到的愚蠢的简单问题。

PHP 端 - 如果重要的话,PHP 字符集设置为 UTF-8

function encrypt($input)
{

$this->iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

/*No longer using random iv :(
$this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);*/

//use 16 zeros
$this->iv = '0000000000000000';

$encrypted = $this->iv .mcrypt_encrypt(MCRYPT_RIJNDAEL_128, KEY, $input, MODE, $this->iv);

//Finally encode this as base 64, see http://php.net/manual/en/function.base64-encode.php
$encrypted = base64_encode($encrypted);

return $encrypted;
}



function decrypt($input)
{
/*Get our message back!!!
First decode the base 64 string. Note, de/encoding bas 64 != encryption*/
$ciphertext_dec = base64_decode($input);

//Get the iv back out for decryption
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

//$iv_dec = substr($ciphertext_dec, 0, $iv_size);*/
$iv_dec = '0000000000000000';

//Now get the text of encrypted message (all but the iv in front)
$ciphertext_dec = substr($ciphertext_dec, $iv_size);

//Now decrypt the message
$plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, KEY, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

//Test
//test
//$plaintext_dec = iconv("UTF-8", "ASCII", $plaintext_dec);
//echo mb_detect_encoding($plaintext_dec, "auto");
//echo $plaintext_dec;

/*However, we might now have blank space @ end of output b/c
remember we de/encrypt via block, so a 10 char long message
could be padded to 16 char long with blank spaces. Get rid of those.*/
$plaintext_dec = trim($plaintext_dec);

//return so we can compare to, i.e., original input
return $plaintext_dec;
}

.NET C#

    public string mcrypt_encrypt(string plainText)
{
plainText = Encoding.ASCII.GetString(crypt.IV) + plainText;
byte[] myText = Encoding.ASCII.GetBytes(plainText);

// Do 128-bit AES encryption:
byte[] cipherText = crypt.EncryptBytes(myText);

return Convert.ToBase64String(cipherText);
}

public string mcrypt_decrypt(string cipher_text)
{

byte[] cipher_dec = Convert.FromBase64String(cipher_text);

byte[] plainBytes = crypt.DecryptBytes(cipher_dec);

string decrypted = Encoding.ASCII.GetString(plainBytes);

string plain_text = decrypted.Substring(16, decrypted.Length - 16);

return plain_text.TrimEnd('\0');
}

C# 奇尔卡特初始化: //AES 也称为 Rijndael。

          crypt.CryptAlgorithm = "aes";

// CipherMode may be "ecb" or "cbc"
crypt.CipherMode = "cbc";

// KeyLength may be 128, 192, 256
crypt.KeyLength = 128;

// Pad with NULL bytes (PHP pads with NULL bytes)
crypt.PaddingScheme = 3;

// EncodingMode specifies the encoding of the output for
// encryption, and the input for decryption.
// It may be "hex", "url", "base64", or "quoted-printable".
crypt.EncodingMode = "hex";

// The secret key must equal the size of the key. For
// 256-bit encryption, the binary secret key is 32 bytes.
// For 128-bit encryption, the binary secret key is 16 bytes.
string keyAscii = @"&=*FS6wksG@Zs3qG";
crypt.SecretKey = Encoding.UTF8.GetBytes(keyAscii);
crypt.Charset = "ASCII";

crypt.SetEncodedIV("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "ascii");

最佳答案

您在这里遇到了各种不同的问题。导致您看到无法解密在 .NET 中加密的 PHP 数据的问题的原因是,在 PHP 版本中,您在 密文substr > 在解密之前。代码中的注释表明您正在删除 IV,除了当您每次(正确)使用随机 IV 时,这似乎只与您代码的先前版本相关 - 现在您只是丢弃了前 16 个字节的密文由于操作模式而破坏了后续数据 block 。

另一个问题(尽管在 .NET 中解密时会丢弃明文数据的前 16 个字节这一事实掩盖了这一点)是您在 .NET 中使用的 IV(16 个字节的 0x00 ) 与您在 PHP 中使用的 IV 不同(16 个“0”字符 = 16 个字节的 0x30)。

我建议恢复为每次加密都使用随机 IV,并在加密 之后将 IV 加到密文前 解密时,从密文的第一个字节读取 IV,然后解密其余部分。这比使用静态 IV 安全得多,尤其是当被加密的数据可能通常相同时。

关于c# - 无法弄清楚为什么 PHP 到 C# .NET 不会对称加密/解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27227250/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com