【问题标题】:Exchanging AES Key and VI between C# and PHP using RSA doesn't work (Encoding)使用 RSA 在 C# 和 PHP 之间交换 AES 密钥和 VI 不起作用(编码)
【发布时间】:2014-01-06 18:45:33
【问题描述】:

我尝试使用 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-file 的重要部分:

$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(parts[0]) 中的响应已用 UTF8 解码,超过 200 个字节,因此 RSADecrypt-Method 当然会出错。

【问题讨论】:

    标签: c# php aes rsa phpseclib


    【解决方案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?它会比这个方案安全得多(例如,这里没有针对中间人攻击的保护措施。)

    【讨论】:

    • 嘿,感谢您的回复;) 转换为 base-64 并将数据读取为 ISO-8859-1,因为网络服务器还对响应进行编码(而不是 UTF-8),工作正常。我只是想实现一种方法,您可以使用我现在正在处理的项目而无需 SSL 服务器端,因为不是每个人都有机会使用它。当然,主要还是会用到 SSL。
    猜你喜欢
    • 2018-05-31
    • 1970-01-01
    • 2019-01-06
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多