使用RSA在C#和PHP之间交换AES密钥和VI不会';t工作(编码)

使用RSA在C#和PHP之间交换AES密钥和VI不会';t工作(编码),c#,php,aes,rsa,phpseclib,C#,Php,Aes,Rsa,Phpseclib,我尝试使用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.UT

我尝试使用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]);
//这是使用UTF8将请求发送到php
公共字符串SendRequest(Uri路径,NameValueCollection nvc)
{
HttpWebRequest请求=(HttpWebRequest)WebRequest.Create(路径);
byte[]输入=Encoding.UTF8.GetBytes(GetPostString(nvc));
request.Method=“POST”;
request.ContentType=“application/x-www-form-urlencoded”;
request.ContentLength=输入.Length;
使用(Stream=request.GetRequestStream())
{
stream.Write(输入,0,输入.长度);
}
HttpWebResponse=(HttpWebResponse)request.GetResponse();
StreamReader sr=新的StreamReader(response.GetResponseStream(),Encoding.UTF8);
字符串结果=sr.ReadToEnd();
高级关闭();
返回结果;
}
//这是我如何尝试将C#的公钥发送到php的一段代码:
字符串结果=SendRequest(builder.Uri,publicKeyNVC);
string[]parts=Regex.Split(结果“”);
this.cryptoHelper.ExchangedAESKey=this.cryptoHelper.DecryptRSA(部分[0]);
this.cryptoHelper.ExchangeDesiv=this.cryptoHelper.DecryptoRSA(第[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);
$key=md5(uniqid());
$size=mcrypt\u get\u iv\u size(mcrypt\u CAST\u 128,mcrypt\u MODE\u CBC);
$iv=mcrypt\u create\u iv($size,mcrypt\u DEV\u RANDOM);
$rsa=新的Crypt_rsa();
$public=str_replace(“,”

”,$public_key); $rsa->loadKey($public、CRYPT\u rsa\u PRIVATE\u FORMAT\u XML); $rsa->loadKey($rsa->getPublicKey()); $rsa->setEncryptionMode(CRYPT\u rsa\u ENCRYPTION\u PKCS1); $ciphertext_key=($rsa->encrypt($key)); $ciphertext_iv=($rsa->encrypt($iv)); echo($ciphertext_key.“.”$ciphertext_iv); 回音“$key.”.strlen($ciphertext_key)。“|”。.strlen($ciphertext_iv);
很抱歉发布了这么多代码,但我不能确定我的错误隐藏在哪里。我的问题是,php请求的长度

echo "</seperator>".$key."|".strlen($ciphertext_key)."|".strlen($ciphertext_iv);
echo.“$key.”.strlen($ciphertext_key)。“|”。.strlen($ciphertext_iv);

(128)的长度与我收到的响应不同。DecryptRSA(parts[0])中的响应用UTF8解码超过200字节,因此RSADecrypt方法当然会出错。

我猜PHP创建的密文是二进制的,并且由于将web响应解释为C#中的UTF-8,因此它正在被破坏。不能将任意二进制数据视为字符串,它们必须作为二进制数据处理或转换为适当的文本形式,例如Base64。您可以尝试替换此:

echo ($ciphertext_key."</seperator>".$ciphertext_iv);
与:

(您可能需要更改
DecryptRSA()
的签名以接受
字节[]
并删除该方法中当前正在进行的
字符串到
字节[]
转换)


最后,有什么理由不只是使用SSL吗?它将比此方案安全得多(例如,因为您无法抵御中间人攻击)。

嘿,谢谢您的回复;)转换为base-64并以ISO-8859-1的形式读取数据,因为Web服务器也对响应进行编码(而不是UTF-8),这是有效的。我只是想实现一种不用SSL服务器端就可以使用我的项目的方法,因为不是每个人都有机会使用它。当然,SSL将主要使用。
echo (base64_encode($ciphertext_key)."</seperator>".base64_encode($ciphertext_iv));
 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]));