【发布时间】:2013-12-13 12:54:25
【问题描述】:
我正在尝试在客户端(C#)加密数据,然后通过 POST 将其传输到服务器并在服务器端(PHP)对其进行解码。
出于此测试目的,我还将附加到 POST 的所有值都在客户端使用以匹配服务器 值为:
- 纯文本
- 通过短语
- 四
- 由客户端加密文本生成
我在服务器端重复使用这些参数,这意味着我使用相同的纯文本、相同的密码短语和相同的 IV 但是结果不匹配
客户端的加密文本与服务器端的加密文本不匹配,它们都是从相同的输入参数生成的
这是控制台输出,您可以清楚地看到发生了什么: https://dl.dropboxusercontent.com/u/15715229/ConsoleOutput.JPG
如您所见,服务器使用相同的“in”参数生成不同的哈希...
我做错了什么?
这是我的代码:
C# 代码:
static void Main(string[] args)
{
string url = "http://localhost/temp.php";
WebClient web = new WebClient();
string plainText = "This is sentence I want to encrypt";
string passPhrase = "MyPassPhrase";
string IV = DateTime.Now.ToLongTimeString() + "InVector";
Console.WriteLine("");
Console.WriteLine("----- Start Client -----");
Console.WriteLine("Plain text = " + plainText);
Console.WriteLine("PassPhrase = " + passPhrase);
Console.WriteLine("IV = " + IV);
string encryptedText = Encrypt(plainText, passPhrase, IV);
Console.WriteLine("Encrypted Text = " + encryptedText);
string decryptedText = Decrypt(encryptedText, passPhrase, IV);
Console.WriteLine("Decrypted Text = " + decryptedText);
Console.WriteLine("----- End Client -----");
Console.WriteLine("");
NameValueCollection postData = new NameValueCollection();
postData.Add("plainText", plainText);
postData.Add("encryptedText", encryptedText);
postData.Add("passPhrase", passPhrase);
postData.Add("IV", IV);
string webData = Encoding.UTF8.GetString(web.UploadValues(url, "POST", postData));
Console.WriteLine("----- Start Server Respond -----");
Console.WriteLine(webData);
Console.WriteLine("----- End Server Respond -----");
}
public static string Encrypt(string plainText, string passPhrase, string IV)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(IV);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = Encoding.UTF8.GetBytes(passPhrase);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase, string IV)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(IV);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
byte[] keyBytes = Encoding.UTF8.GetBytes(passPhrase);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
我的 PHP 代码:
<?php
if(isset($_POST['plainText']))
{
$plainText = $_POST['plainText'];
$clientEncryptedText = $_POST['encryptedText'];
$passPhrase = $_POST['passPhrase'];
$iv = $_POST['IV'];
echo "Plain text = ".$plainText."\n";
echo "PassPhrase = ".$passPhrase."\n";
echo "IV = ".$iv."\n";
$encryptedText = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $passPhrase, $plainText, MCRYPT_MODE_CBC, $iv ));
echo "Server Encrypted Text = ".$encryptedText."\n";
echo "Client Encrypted Text = ".$clientEncryptedText."\n";
$decryptedText = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $passPhrase, base64_decode($encryptedText), MCRYPT_MODE_CBC, $iv );
echo "Server Decrypted Text = ".$decryptedText."\n";
$decryptedText = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $passPhrase, base64_decode($clientEncryptedText), MCRYPT_MODE_CBC, $iv );
echo "Decrypted text from Client = ".$decryptedText."\n";
}
else
{
echo "POST is not set";
}
你能告诉我我在哪里做错了吗?在客户端 (C#) 还是在服务器 (PHP)?
问候 瓦迪姆斯·布里克辛斯
【问题讨论】:
-
也许 C# 和 PHP 实现默认在不同的模式下工作(CBC、ECB)?
-
如果您检查代码,您会看到我专门为客户端和服务器设置了相同的“CBC”模式
-
我是否正确理解您正在传输解码加密消息所需的所有内容以及加密消息?是什么阻止了攻击者使用您免费提供的所有必要信息解密邮件?
-
在问题描述中我解释说我只是为了测试目的而将所有内容一起传输,以消除在服务器端可能错误生成/输入错误的事实。一旦加密开始工作,我显然会从 POST 中删除敏感数据并随机生成 IV。但现在它都是静态的并且以简单的方式传输。
标签: c# php encryption rijndael