gpt4 book ai didi

c# - 如何使用 PHP 加密字符串将 CSharp/.NET 设为 "play nice"?

转载 作者:可可西里 更新时间:2023-11-01 01:03:23 25 4
gpt4 key购买 nike

(前言:我是加密和安全方面的新手,认为这是一种有趣的学习方式)

我正在用 C# 构建一个程序,该程序使用标准 HTTP 协议(protocol)与用 PHP 编写的服务器进行通信。我希望这两个程序都能够发送和接收加密数据。然而,尽管它们都使用相同类型的函数,但似乎在处理加密方面存在不一致。

两个程序都在 CBC 模式下使用 Rjindael 128 位。

为了演示/测试,我制作了两个几乎相同的函数,每个函数都采用相同的字符串,对其进行加密,然后将结果作为 base64 字符串输出。

PHP 函数:

public static function EncryptionTest () {
echo 'Testing Encryption to base64 string...<br/>';

$originalString = 'This is the original String! How cool is that?';

$key = "abcdefghijklmnopqrstuvwxyz012345";
$iv = "1234567890123456";

$encrypted = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $key, $originalString, MCRYPT_MODE_CBC, $iv);

echo base64_encode ($encrypted);
}

它是 C# 的对应物:

public static void EncryptionTest ()
{
System.Console.WriteLine ("Testing Encryption to base64 string...");

string originalString = "This is the original String! How cool is that?";
byte [] encryptedData;
byte [] key = System.Text.ASCIIEncoding.UTF8.GetBytes ("abcdefghijklmnopqrstuvwxyz012345");
byte [] iv = System.Text.ASCIIEncoding.UTF8.GetBytes ("1234567890123456");

RijndaelManaged cryptor = new RijndaelManaged ();
cryptor.Key = key;
cryptor.IV = iv;
cryptor.BlockSize = 128;
cryptor.Mode = CipherMode.CBC;

ICryptoTransform encryptor = cryptor.CreateEncryptor (cryptor.Key, cryptor.IV);

using (MemoryStream msEncrypt = new MemoryStream ())
{
using (CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter (csEncrypt) )
{
swEncrypt.Write (originalString);
}
encryptedData = msEncrypt.ToArray ();
}
}

System.Console.WriteLine (System.Convert.ToBase64String (encryptedData) );
}

现在,这是 PHP 结果:

Testing Encryption to base64 string... yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUOJdFykLjsaKfK4VfaBGRv

C# 结果:

Testing Encryption to base64 string... yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUg74mGEQf9iW+OQ68m6cpp

如您所见,这两个结果显然已加密(好),字符数相同(好),但不同(可能不好)。

我编写了解密测试,获取这些字符串并对其进行处理。这是 PHP 函数:

public static function DecryptionTest () {
$phpBase64 = 'yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUOJdFykLjsaKfK4VfaBGRv';
$csBase64 = 'yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUg74mGEQf9iW+OQ68m6cpp';

$key = "abcdefghijklmnopqrstuvwxyz012345";
$iv = "1234567890123456";

$phpEncrypted = base64_decode ($phpBase64);
$phpDecrypted = mcrypt_decrypt (MCRYPT_RIJNDAEL_128, $key, $phpEncrypted, MCRYPT_MODE_CBC, $iv);

$csEncrypted = base64_decode ($csBase64);
$csDecrypted = mcrypt_decrypt (MCRYPT_RIJNDAEL_128, $key, $csEncrypted, MCRYPT_MODE_CBC, $iv);

echo 'Decrypted PHP string: "' . $phpDecrypted . '"<br/>' .
'Decrypted CS string: "' . $csDecrypted . '"';
}

和 C# 版本:

public static void DecryptionTest ()
{
System.Console.WriteLine ("Testing Decryption for PHP and CS generated base64 strings!");

string phpBase64 = "yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUOJdFykLjsaKfK4VfaBGRv";
string csBase64 = "yzwIdowhLj+cMOFPMuHSA80pWQ6R8yfFQlEsLx5kIzUg74mGEQf9iW+OQ68m6cpp";

byte [] phpEncrypted = System.Convert.FromBase64String (phpBase64);
byte [] csEncrypted = System.Convert.FromBase64String (csBase64);

string phpDecrypted;
string csDecrypted;

byte [] encryptedData;
byte [] key = System.Text.ASCIIEncoding.UTF8.GetBytes ("abcdefghijklmnopqrstuvwxyz012345");
byte [] iv = System.Text.ASCIIEncoding.UTF8.GetBytes ("1234567890123456");

RijndaelManaged cryptor = new RijndaelManaged ();
cryptor.Key = key;
cryptor.IV = iv;
cryptor.BlockSize = 128;
cryptor.Mode = CipherMode.CBC;

ICryptoTransform decryptor = cryptor.CreateDecryptor (cryptor.Key, cryptor.IV);

using (MemoryStream msDecrypt = new MemoryStream (csEncrypted))
{
using (CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader swDecrypt = new StreamReader (csDecrypt) )
{
csDecrypted = swDecrypt.ReadToEnd ();
}
}
}
System.Console.WriteLine ("Decrypted CS string: \"" + csDecrypted + "\"");

using (MemoryStream msDecrypt = new MemoryStream (phpEncrypted))
{
using (CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader swDecrypt = new StreamReader (csDecrypt) )
{
phpDecrypted = swDecrypt.ReadToEnd ();
}
}
}

System.Console.WriteLine ("Decrypted PHP string: \"" + phpDecrypted + "\"");
}

PHP 结果:

Decrypted PHP string: "This is the original String! How cool is that?"

Decrypted CS string: "This is the original String! How cool is that?"

C# 结果:

Decrypted CS string: "This is the original String! How cool is that?"

CryptographicException: Bad PKCS7 padding. Invalid length 0. at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position) [0x0005c] in > /Applications/buildAgent/work/84669f285f6a667f/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:363

因此,基本上,PHP 代码可以成功解密两个 base64 字符串,但 C# 代码只能解密由其自己的解密器创建的 base64 字符串。

其中很多是我在互联网上找到的代码,并根据我的需要进行了修改。就像我说的,我是密码学的新手,但我已经走得很远了。我可以整天推理和测试,但它开始占用我的日程安排,所以我正在寻找其他人的见解,以了解为什么它不起作用。谢谢!

最佳答案

您需要使用 PHPSecLib因为 PHP 实现与 C++/C# 不兼容。它具有不同的填充大小(我不是这里的加密专家,但这是我经过几天的测试后发现的)。因此,使用 phpseclib 中的 native 实现,它将起作用。

我自己前段时间碰到过这个问题。但是使用 C++/CryptoAPIPHP

关于c# - 如何使用 PHP 加密字符串将 CSharp/.NET 设为 "play nice"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17371706/

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