我尝试使用HTTPWebRequest在C#和PHP之间交换AES密钥:
// This is to send the request to php using UTF8
public string SendRequest(Uri path, NameValueCollection nvc)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path);
byte[] input = Encoding.UTF8.GetBytes(GetPostString(nvc));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = input.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(input, 0, input.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string result = sr.ReadToEnd();
sr.Close();
return result;
}
// That's a piece of code of how i try to send the C#'s public key to php:
string result = SendRequest(builder.Uri, publicKeyNVC);
string[] parts = Regex.Split(result, "</seperator>");
this.cryptoHelper.ExchangedAESKey = this.cryptoHelper.DecryptRSA(parts[0]);
this.cryptoHelper.ExchangedAESIV = this.cryptoHelper.DecryptRSA(parts[1]);
这是我的exchange-php文件的重要部分:
$key = md5(uniqid());
$size = mcrypt_get_iv_size(MCRYPT_CAST_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
$rsa = new Crypt_RSA();
$public = str_replace('</RSAKeyValue>', '<P></P><Q></Q><DP></DP><DQ></DQ><InverseQ></InverseQ><D></D></RSAKeyValue>', $public_key);
$rsa->loadKey($public, CRYPT_RSA_PRIVATE_FORMAT_XML);
$rsa->loadKey($rsa->getPublicKey());
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$ciphertext_key = ($rsa->encrypt($key));
$ciphertext_iv = ($rsa->encrypt($iv));
echo ($ciphertext_key."</seperator>".$ciphertext_iv);
echo "</seperator>".$key."|".strlen($ciphertext_key)."|".strlen($ciphertext_iv);
很抱歉发布了这么多代码,但我无法确定我的错误隐藏在哪里。我的问题是,php要求的长度为
echo "</seperator>".$key."|".strlen($ciphertext_key)."|".strlen($ciphertext_iv);
(128)与我收到的回复长度不同。 DecryptRSA(部分[0])中的响应,用UTF8解码,超过200个字节,因此RSADecrypt-Method当然会出错。
答案 0 :(得分:1)
我猜想PHP创建的密文是二进制文件,并且由于在C#中将Web响应解释为UTF-8,它正在被破坏。您不能将任意二进制数据视为字符串,它们必须作为二进制处理或转换为适当的文本形式,例如Base64编码。您可以尝试替换它:
echo ($ciphertext_key."</seperator>".$ciphertext_iv);
使用:
echo (base64_encode($ciphertext_key)."</seperator>".base64_encode($ciphertext_iv));
然后在C#端替换:
this.cryptoHelper.ExchangedAESKey = this.cryptoHelper.DecryptRSA(parts[0]);
this.cryptoHelper.ExchangedAESIV = this.cryptoHelper.DecryptRSA(parts[1]);
使用:
this.cryptoHelper.ExchangedAESKey = this.cryptoHelper.DecryptRSA(Convert.FromBase64String(parts[0]));
this.cryptoHelper.ExchangedAESIV = this.cryptoHelper.DecryptRSA(Convert.FromBase64String(parts[1]));
(您可能需要更改DecryptRSA()
的签名以接受byte[]
并删除当前在该方法中正在进行的string
到byte[]
转换。
最后,您是否有任何理由不只是使用SSL?它会比这个方案安全得多(因为你没有保护这里的中间人攻击。)