使用RSA在C#和PHP之间交换AES密钥和VI不起作用(编码)

时间:2014-01-06 18:45:34

标签: 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.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当然会出错。

1 个答案:

答案 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[]并删除当前在该方法中正在进行的stringbyte[]转换。

最后,您是否有任何理由不只是使用SSL?它会比这个方案安全得多(因为你没有保护这里的中间人攻击。)