【问题标题】:PHP to C# Encrypted message - trouble decryptingPHP 到 C# 加密消息 - 解密麻烦
【发布时间】:2021-04-05 20:41:08
【问题描述】:

我的 PHP 服务器上存储了一个私钥。使用 PHP 服务器上的私钥对消息进行加密。我的 C# 代码旨在从 PHP 的响应中接收密文并使用公钥对其进行解密。但是,我一直遇到诸如

之类的错误

Cryptography.CryptoThrowHelper.WindowsCryptographicException: '密钥不存在。'

我的PHP代码如下:

    $pkey = openssl_pkey_get_private("file://pkey");
    openssl_private_encrypt($text, $ciphertext, $pkey, OPENSSL_PKCS1_PADDING);
    echo base64_encode($ciphertext);

我的 C# 代码包含提到的函数 in this thread 的实现,其中答案有一个链接到 Github 的注释。下面是一个sn-p:

  string pubkey = "M...Q==";
  RSA rsa = CreateRsaProviderFromPublicKey(pubkey);
  byte[] bytes = Convert.FromBase64String(dataEncrypted);
  byte[] decryptedBytes = rsa.Decrypt(bytes, RSAEncryptionPadding.Pkcs1);
  return Encoding.UTF8.GetString(decryptedBytes);

错误发生在调用 rsa.Decrypt 的那一行。我从 PHP 函数 openssl_pkey_get_details 获得了公钥,然后我在其中剥离了 ----BEGIN PUBLIC KEY----- 页眉和页脚并删除了所有空格。

编辑 1:也许我应该发布我用来制作私钥的代码,因为这可能会有问题:

$config = array(
  "digest_alg" => "sha512",
  "private_key_bits" => 4096,
  "private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$res = openssl_pkey_new($config);

编辑 2:我尝试使用 2048 字节的 sha256 作为新密钥,没有任何区别。

【问题讨论】:

  • 请注意 - 加密必须使用收件人的公钥完成,解密(这里使用 C# 平台)是使用接收者的 私钥 完成的,而不是相反。它仅在某些系统上是可能的,但不会运行,例如在 Java 平台上。
  • 感谢您的回复。我明天试试(这里已经很晚了)。认为 PHP 服务器需要将公钥保密,而客户端(公开的)将携带私钥似乎很奇怪。希望这不是安全问题。
  • 想一想这种情况:您希望我向您发送一些秘密数据 - 为此您在您的网站、报纸上发布您的 公钥 或通过电子邮件发送给我。我将使用 您的公钥 加密数据并将加密后的数据发送给您。唯一可以/应该解密数据的人是有权访问您的私钥的人(您)[这就是为什么它被称为“私人”]。顺便说一句:数字签名的工作方式相反:签名是使用签名者的私钥完成的,验证是通过发布的公钥完成的。从德国到美国的问候:-)
  • 来自美国的问候!所以要明确一点,为此,PHP 代码需要其中一个密钥来加密数据,而 C# 需要另一个密钥来解密。 C# 代码将广泛分发,但我认为秘密持有的密钥是私钥还是公钥在安全性方面没有区别?

标签: c# php openssl


【解决方案1】:

请允许我用 3 个小而简单的程序解释 RSA 加密的完整工作流程。我正在在线编译器中运行所有程序,因此您可以轻松地直接运行代码。密钥对是 4096 位长的 RSA 密钥,在线生成需要几秒钟,出于安全原因,加密填充是 OAEP。

安全警告:所有程序运行时均未进行任何异常处理,仅用于教育目的。

第 1 步:密钥生成

由于加密是使用消息的收件人公钥完成的,因此收件人必须生成 RSA 密钥对。根据您的定义,PHP 端是发送者,C# 端是接收者,让我们在 C# 中生成密钥对。

第一个代码将以 XML 编码生成一个 4096 位长的 RSA 密钥对 - 这是 C# 的默认输出编码:

privateKeyXML: <RSAKeyValue><Modulus>u0pkuoAjII9KQ9OgEILB6MnGBAedO/Ho+O69W5USpQc+pDGxQbqcC9PKKQk4dymGnS70HVswHVUkdiLcEIMCjU8jdXFnOfh5SPKfR9bgmRQ3HhEaY5ejcCerCW96J5leNEcfkMpWjXy+hvzt0Whnv21Xckbkzo17HZrN+G9C5D1KEeQkdKdg8WVR+3XfhiFLj/S6ANmNjCNbcrR8GKY1GjZahDUyddEza76RuJ3Wqyle0BmNT0RoSHGvjBP+LlY3aOqzsU2sqnzGnItRzr2HnQwVV10MMFo3fbuWopzXqzVjQbnxJM9G79l20Np2eFLDVp4zpiYrGHWSFOnfIDqmy5ke57WnISJwnPz6A+ByhYVJfaxohkk+csbaPCsILQ0ZCzTnCcoh9svw9AIvlHn5YyAa8Gl5o6Ub8lsJXOSftGVtcCsWRiLbD1pg1CTQmoKPPxUFsaU9iPXrfb48+5hFFOVe6+22S8YShFl/HaRq8TMESXmCiRgbgzBV7zmABkJFtH6WUBkXqBTSlUoEsYUHIV61vptroHHui/aVxnynvtkJqTTfto2ukq5ZzpDmQeDE075kM/rOyUuUiJBQ7eszrXKTDKW2xqc6q/OQMfjEiPdtl1Rc44obdRGaTmJhi9h5a/SqH6KPDVoaR+hwLXggnLERroyogElyjbzrkfD5nCE=</Modulus><Exponent>AQAB</Exponent><P>1dlD8Q7ESEgsk507oFT1qZHKgV1Cl6bfNxm7dnCFlkp27kbvsKp5RBzRTCSxClkbwTBfbN0NIQq0o0Rwo9e1Z7yyMGs3v4k3i0Wlw9NkdtineE1dtk/7cBwb6anYZCiyV7TpYK6UCwcwwfyhNBYl5Y7Lr879tUsd1yXfZLVR0YS88gS0LMSsIMRJ6it9H+tcdg+eLTNr9CLIpxuUfYPixhI0xSTF5ZlCplfRaxlvqCh3RJ1IO6Mluv72Df46hKR6mJcMVc2YFUNp/O7038iqGnnBPAlwiT00C2eVh5Qjx4muTg64Zt98ckotsX1Lou8IlBOyem4R1c3b9G6Ga5AZNQ==</P><Q>4DUD8vf0+2LS2PC+cM1s9YqGmR7iukKTBtMPH+rj+wRezwPx7vmNuy8Z5bgfJxfdgHfdQWmQS6gK9OatYR+ZtxQN0B70C2tfEsPBRpPYwOWIiHZQgeczCKevI24w/YyhBU2p1IKljQUsjo1cxyH/es7tVIvfhDw6RVKg4KL8keV7YLSV8kYtJ3/VlrMw5NasfIC2vJ+fatachYRk1BUfB/x7mCDuQmNkQDPiSy24AjzDjMEOPLNNQRWdShkbVYXmX5388VLdbNCrXrCHVdwKrASCGfrCfqhmIY5BE/78c56MprbUCNphkywyiRzzEdhjs6ZgERu7ybQQvd+FQxsAvQ==</Q><DP>yyLdZSjvzvGwVnBvaXgK/A7fXE9oqIH9W2v4JSPx4bfOjb2YhisJkmgFcN0Rx5CpyrPWkaTRieePe9/RV/HaAja+1Tuj8y+3MXbxZblyn2pieuaS9FG5uN8arLWINmxqLOJPJmXvfyJPcJY30zCOwycH2XM4kXRPXkY9lH6gv/PlP8i0Fiqkj2OmCulQrHd4lzVyveEw1PINxJ9wSGJ1kk1ND1BFJDqXk0esSJ4a8JOv59+3896gQqdauCQdFk7fnf8t2nu30cr97SRYPBNzcj7iDdOxsMwQmhzFb8qKykrA5qkZBa+ZmT9ZdFZe+OEzNuYXDjFsg7pPDDvJOHfjWQ==</DP><DQ>1LZXnc9TtKCoi7uz4k9zPW2Ej4c28iGxXfsl0VFHpGIcFOmYQfKvXdStDD3oCG3i7zxJRQMDLFQsuPaVrZyOeJxlEnwbay4eEC56kxw3u6LJKzac4PHZgC+ewM2NWzBtoBtzsbOVnzo2cLR7Pk3qFbh2gA0ILWv6mMRw706Ss1R1/mS2Eho0QtJMcOJm0+U71g9Dz6bdVz5vV1kpU/EJ9Mi89bLgeUnU1fijjFG+zxiZKlQKztoJxGLeTGuPfE9CJps8XDQS8Wbz/y0Z6QKPeW35hO5cUlAwPUu6QF9dYdAdfxncBt4xTrDS7TTzA4454TpK0FBwlEfqzklfJDBdPQ==</DQ><InverseQ>KrqeLyuPFVeAb30HGnirKGLnAJ5SDNACcLnoqscbMC6huenwLL9E18EJQpmVFJLgqyXJTslfmyCcHYsnErKif21VqfQ9QnJrjS5Q2pDrUria7E1opwrhYAKWM/U2MXllCGMurOTLi4sfpkwiUQ8ld8jUJxrIk9XLSAOB+PBN1HZ5UTvzfzPtotms9Q1XBHIHwk1n0jT9z0kg91vVXwFv9JOqLOnDh5RX0JKOZw357bf7toZ2n5aLoAwdzTG6Gqdf/fkUQXOLmH5eaIxwLOJfmjrKHGzyOpbNqYyjjM+N/g3J1vBkDFhdSAibz35neFsJgMyHETSsFaWKZG3PzR80uQ==</InverseQ><D>gDzC1XPxGVUjS2e2XDe7n7GwNIgmH6pWk0OcQf3DQ12/hVtE/DVSrUJ5VDmtAOJc+njwyrzqJ9tpWL4rod6iO7EpHTvlqyq3mLwPVXgKVqYhyyN4xyJH1P5EPPSoVj7L4s2kDlaMhtoX9oNuLojnKIosauGhvs/esXmSd/1udqqEcdWdJIaKeR6f0KZ3wvY/L7UoOna7VW3MKrDrm1EKYQVAWu+1ujfglnBohFkGaDGuapxkRhcXtCqrQSVbT8zWqa6yFL+TbzR6JSu7euwI0/43Cpd6Rg0vm5Z64KK1hNPMP2+ablLCRm3GzeAXZ/F7MG6n/KZ7sYam3Ez56q5eDzO66UL2Ksi81FLTtq/NNegWnELZ79bJy9D1i2R6GmtDG/Lm6BWYHz4m7e7+DMmBJcQbE3cky6iKVyhYVgJ74cREetbXER6Ifriuv9RqumcE1+dN/9yBkinJqa9jFblIGwJMAK9u5fC/Y7Ddba1DS43TYGvnGuYO26QBZPwlyd78t3utHW+Fn38uN/XfYlxMcxlxUHo6eC//zWxRMga+U7AWAZZWLDgHZ+Jp+7cfYypBsIryDiZMUQSkH3o87SMVE9lhT7tO/waJ8mjcdwfAXmCXLhKkFU9CorsU5bIpGkQgGIXNswAGOh8hDvvW1GHLSruGMhoOM9TqHsoO66Ow77E=</D></RSAKeyValue>
publicKeyXML: <RSAKeyValue><Modulus>u0pkuoAjII9KQ9OgEILB6MnGBAedO/Ho+O69W5USpQc+pDGxQbqcC9PKKQk4dymGnS70HVswHVUkdiLcEIMCjU8jdXFnOfh5SPKfR9bgmRQ3HhEaY5ejcCerCW96J5leNEcfkMpWjXy+hvzt0Whnv21Xckbkzo17HZrN+G9C5D1KEeQkdKdg8WVR+3XfhiFLj/S6ANmNjCNbcrR8GKY1GjZahDUyddEza76RuJ3Wqyle0BmNT0RoSHGvjBP+LlY3aOqzsU2sqnzGnItRzr2HnQwVV10MMFo3fbuWopzXqzVjQbnxJM9G79l20Np2eFLDVp4zpiYrGHWSFOnfIDqmy5ke57WnISJwnPz6A+ByhYVJfaxohkk+csbaPCsILQ0ZCzTnCcoh9svw9AIvlHn5YyAa8Gl5o6Ub8lsJXOSftGVtcCsWRiLbD1pg1CTQmoKPPxUFsaU9iPXrfb48+5hFFOVe6+22S8YShFl/HaRq8TMESXmCiRgbgzBV7zmABkJFtH6WUBkXqBTSlUoEsYUHIV61vptroHHui/aVxnynvtkJqTTfto2ukq5ZzpDmQeDE075kM/rOyUuUiJBQ7eszrXKTDKW2xqc6q/OQMfjEiPdtl1Rc44obdRGaTmJhi9h5a/SqH6KPDVoaR+hwLXggnLERroyogElyjbzrkfD5nCE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

第 2 步:在 PHP 端使用公钥进行 RSA 加密

由于我们使用 PHP 内置的 OpenSSL 引擎,我们需要先将 XML 编码的公钥转换为 PEM 编码。因为它是我使用的公钥 此任务的在线服务 - 还有许多其他选项,但为了演示,没关系。转到https://superdry.apphb.com/tools/online-rsa-key-converter 并将publicKeyXML 复制/粘贴到第一个输入框,然后按“转换”按钮。在下面的输出框中,您会找到这个公钥:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu0pkuoAjII9KQ9OgEILB
6MnGBAedO/Ho+O69W5USpQc+pDGxQbqcC9PKKQk4dymGnS70HVswHVUkdiLcEIMC
jU8jdXFnOfh5SPKfR9bgmRQ3HhEaY5ejcCerCW96J5leNEcfkMpWjXy+hvzt0Whn
v21Xckbkzo17HZrN+G9C5D1KEeQkdKdg8WVR+3XfhiFLj/S6ANmNjCNbcrR8GKY1
GjZahDUyddEza76RuJ3Wqyle0BmNT0RoSHGvjBP+LlY3aOqzsU2sqnzGnItRzr2H
nQwVV10MMFo3fbuWopzXqzVjQbnxJM9G79l20Np2eFLDVp4zpiYrGHWSFOnfIDqm
y5ke57WnISJwnPz6A+ByhYVJfaxohkk+csbaPCsILQ0ZCzTnCcoh9svw9AIvlHn5
YyAa8Gl5o6Ub8lsJXOSftGVtcCsWRiLbD1pg1CTQmoKPPxUFsaU9iPXrfb48+5hF
FOVe6+22S8YShFl/HaRq8TMESXmCiRgbgzBV7zmABkJFtH6WUBkXqBTSlUoEsYUH
IV61vptroHHui/aVxnynvtkJqTTfto2ukq5ZzpDmQeDE075kM/rOyUuUiJBQ7esz
rXKTDKW2xqc6q/OQMfjEiPdtl1Rc44obdRGaTmJhi9h5a/SqH6KPDVoaR+hwLXgg
nLERroyogElyjbzrkfD5nCECAwEAAQ==
-----END PUBLIC KEY-----

将您的公钥复制并粘贴到第二个程序(函数 loadRsaPublicKeyPem)中,让它运行并加密数据,给出 Base64 编码输出:

RSA 2048 encryption OAEP-padding string
plaintext: The quick brown fox jumps over the lazy dog

* * * encrypt the plaintext with the RSA public key * * *
ciphertextBase64: Rot82ugHFtc3b/JNC+uUYMUSQgdHl4bwcdpLIpY7EJzrI7xwMdzKMoastjc4IFiAcXExC7YmpVkVXsHYVGDbMb+o/IKAp/LyH5SrlQqAJq65ZG7Fe54UgKatdqAIBMQIawiv+3g2YmrstdA2KIjW1+93FeH1vUgqSYxydSvIkngjqE//1Dwa/DY+bFrDfG9B1HtDEDFvAOOZE7qC4I2XYvD3LQVwp4zBzFXSzeJP9/BkksC6CN6caKDRdaQa+/oyRjZXJiFIx4YAhok4aBwg54er+2jEeKHcUM01eZBTCFtrIZF4Yg9GQRkCA89XsZkGypqPVL/HLZXx6yHF3kR3XVvCuKwzX/IyostUNbPeWWAWieUFbBWhdPSrENC//7M8nmE7dvcBbRHpoX4LWmD+kWYAFV3M+5n9SJhzwayI0rvQY9DQ4U5IiaP32TDjqyPyK2gzimpuYRe7KWYCBgCG503XThdWe4vpcDNYOKp0KO5TwHMNMTg/FLbwuQcvcpiT9lQLbr5Pz84swe1olhle0rTlBXOS6ONn5LWfrKYjfwluBYsxF/XtJcg+HytBZbCqMNHTeeS4a40r0XLxH/Gjdvw1zs7APrA9AN2SObthMeIXJlryLSshmoKsgBDCi3JzZ80kO4729SVtH1SbwElkZtJNqD6IilY2c1M6CV94tHg=

第 3 步:使用私钥在 C# 端进行 RSA 解密

在第三个程序(函数loadRsaPrivateKeyXml)中复制粘贴你的私钥,复制粘贴ciphertextBase64并运行程序,你 会得到这个输出:

RSA 2048 decryption OAEP-padding string

* * * decrypt the ciphertext with the RSA private key * * *
ciphertextReceivedBase64: Rot82ugHFtc3b/JNC+uUYMUSQgdHl4bwcdpLIpY7EJzrI7xwMdzKMoastjc4IFiAcXExC7YmpVkVXsHYVGDbMb+o/IKAp/LyH5SrlQqAJq65ZG7Fe54UgKatdqAIBMQIawiv+3g2YmrstdA2KIjW1+93FeH1vUgqSYxydSvIkngjqE//1Dwa/DY+bFrDfG9B1HtDEDFvAOOZE7qC4I2XYvD3LQVwp4zBzFXSzeJP9/BkksC6CN6caKDRdaQa+/oyRjZXJiFIx4YAhok4aBwg54er+2jEeKHcUM01eZBTCFtrIZF4Yg9GQRkCA89XsZkGypqPVL/HLZXx6yHF3kR3XVvCuKwzX/IyostUNbPeWWAWieUFbBWhdPSrENC//7M8nmE7dvcBbRHpoX4LWmD+kWYAFV3M+5n9SJhzwayI0rvQY9DQ4U5IiaP32TDjqyPyK2gzimpuYRe7KWYCBgCG503XThdWe4vpcDNYOKp0KO5TwHMNMTg/FLbwuQcvcpiT9lQLbr5Pz84swe1olhle0rTlBXOS6ONn5LWfrKYjfwluBYsxF/XtJcg+HytBZbCqMNHTeeS4a40r0XLxH/Gjdvw1zs7APrA9AN2SObthMeIXJlryLSshmoKsgBDCi3JzZ80kO4729SVtH1SbwElkZtJNqD6IilY2c1M6CV94tHg=
decryptedData: The quick brown fox jumps over the lazy dog

瞧——我们在 C# 上从 PHP 端接收原始明文。以下是在线资源:

程序 1 - 在 C# 端生成 RSA 密钥:https://repl.it/@javacrypto/CsharpGenerateRsaKeypair#main.cs 程序 2 - 在 PHP 端加密:https://repl.it/@javacrypto/PhpRsaOaepPaddingEncryption#main.php 程序 3 - 在 C# 端解密:https://repl.it/@javacrypto/CsharpRsaOaepPaddingDecryption#main.cs

代码程序1:

using System;
using System.Security.Cryptography;
using System.Text;

class RSACSPSample
{
    static void Main()
    {
        // Create a new instance of RSACryptoServiceProvider to generate
        // public and private key data.
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(4096);
        rsa.PersistKeyInCsp = false;
        string privateKeyXML = rsa.ToXmlString(true);
        string publicKeyXML = rsa.ToXmlString(false);
        Console.WriteLine("privateKeyXML: " + privateKeyXML);
        Console.WriteLine("publicKeyXML: " + publicKeyXML);
        Console.WriteLine();
    }
}

代码程序2:

<?php
function rsaEncryptionOaepSha1($publicKey, $plaintext) {
    openssl_public_encrypt($plaintext, $ciphertext, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
    return $ciphertext;
 }

function base64Encoding($input) {return base64_encode($input);}

function loadRsaPublicKeyPem() {
    // this is a sample key - don't worry !
    return '
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu0pkuoAjII9KQ9OgEILB
6MnGBAedO/Ho+O69W5USpQc+pDGxQbqcC9PKKQk4dymGnS70HVswHVUkdiLcEIMC
jU8jdXFnOfh5SPKfR9bgmRQ3HhEaY5ejcCerCW96J5leNEcfkMpWjXy+hvzt0Whn
v21Xckbkzo17HZrN+G9C5D1KEeQkdKdg8WVR+3XfhiFLj/S6ANmNjCNbcrR8GKY1
GjZahDUyddEza76RuJ3Wqyle0BmNT0RoSHGvjBP+LlY3aOqzsU2sqnzGnItRzr2H
nQwVV10MMFo3fbuWopzXqzVjQbnxJM9G79l20Np2eFLDVp4zpiYrGHWSFOnfIDqm
y5ke57WnISJwnPz6A+ByhYVJfaxohkk+csbaPCsILQ0ZCzTnCcoh9svw9AIvlHn5
YyAa8Gl5o6Ub8lsJXOSftGVtcCsWRiLbD1pg1CTQmoKPPxUFsaU9iPXrfb48+5hF
FOVe6+22S8YShFl/HaRq8TMESXmCiRgbgzBV7zmABkJFtH6WUBkXqBTSlUoEsYUH
IV61vptroHHui/aVxnynvtkJqTTfto2ukq5ZzpDmQeDE075kM/rOyUuUiJBQ7esz
rXKTDKW2xqc6q/OQMfjEiPdtl1Rc44obdRGaTmJhi9h5a/SqH6KPDVoaR+hwLXgg
nLERroyogElyjbzrkfD5nCECAwEAAQ==
-----END PUBLIC KEY-----
';
}

echo 'RSA 2048 encryption OAEP-padding string' . PHP_EOL;
$dataToEncryptString = "The quick brown fox jumps over the lazy dog";
echo 'plaintext: ' . $dataToEncryptString . PHP_EOL;

// encryption
echo PHP_EOL . '* * * encrypt the plaintext with the RSA public key * * *' .PHP_EOL;

$publicKeyLoad = openssl_pkey_get_public(loadRsaPublicKeyPem());
$ciphertextBase64 = base64Encoding(rsaEncryptionOaepSha1($publicKeyLoad, $dataToEncryptString));
echo 'ciphertextBase64: ' . $ciphertextBase64 . PHP_EOL;

// transport the encrypted data to recipient
?>

代码程序3:

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RsaDecryptionOaepPadding {
    static void Main() {
    Console.WriteLine("RSA 2048 decryption OAEP-padding string");
    
    string ciphertextBase64 = "Rot82ugHFtc3b/JNC+uUYMUSQgdHl4bwcdpLIpY7EJzrI7xwMdzKMoastjc4IFiAcXExC7YmpVkVXsHYVGDbMb+o/IKAp/LyH5SrlQqAJq65ZG7Fe54UgKatdqAIBMQIawiv+3g2YmrstdA2KIjW1+93FeH1vUgqSYxydSvIkngjqE//1Dwa/DY+bFrDfG9B1HtDEDFvAOOZE7qC4I2XYvD3LQVwp4zBzFXSzeJP9/BkksC6CN6caKDRdaQa+/oyRjZXJiFIx4YAhok4aBwg54er+2jEeKHcUM01eZBTCFtrIZF4Yg9GQRkCA89XsZkGypqPVL/HLZXx6yHF3kR3XVvCuKwzX/IyostUNbPeWWAWieUFbBWhdPSrENC//7M8nmE7dvcBbRHpoX4LWmD+kWYAFV3M+5n9SJhzwayI0rvQY9DQ4U5IiaP32TDjqyPyK2gzimpuYRe7KWYCBgCG503XThdWe4vpcDNYOKp0KO5TwHMNMTg/FLbwuQcvcpiT9lQLbr5Pz84swe1olhle0rTlBXOS6ONn5LWfrKYjfwluBYsxF/XtJcg+HytBZbCqMNHTeeS4a40r0XLxH/Gjdvw1zs7APrA9AN2SObthMeIXJlryLSshmoKsgBDCi3JzZ80kO4729SVtH1SbwElkZtJNqD6IilY2c1M6CV94tHg=";

        try {
        // receiving the encrypted data, decryption
        Console.WriteLine("\n* * * decrypt the ciphertext with the RSA private key * * *");
        string ciphertextReceivedBase64 = ciphertextBase64;
        Console.WriteLine("ciphertextReceivedBase64: " + ciphertextReceivedBase64);
        string privateKeyLoad = loadRsaPrivateKeyXml();
        byte[] ciphertextReceived = Base64Decoding(ciphertextReceivedBase64);
        byte[] decryptedtextByte = rsaDecryptionOaep(privateKeyLoad, ciphertextReceived);
        Console.WriteLine("decryptedData: " + Encoding.UTF8.GetString(decryptedtextByte, 0, decryptedtextByte.Length));
        }
        catch(ArgumentNullException) {
            Console.WriteLine("The data was not RSA encrypted");
        }
    }

  public static byte[] rsaDecryptionOaep(string privateKeyXml, byte[] ciphertext) {
    RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(2048);
        RSAalg.PersistKeyInCsp = false;
        RSAalg.FromXmlString(privateKeyXml);
    return RSAalg.Decrypt(ciphertext, true);
  }

  static byte[] Base64Decoding(String input) {
    return Convert.FromBase64String(input);
  }

  public static string loadRsaPrivateKeyXml() {
    return "<RSAKeyValue><Modulus>u0pkuoAjII9KQ9OgEILB6MnGBAedO/Ho+O69W5USpQc+pDGxQbqcC9PKKQk4dymGnS70HVswHVUkdiLcEIMCjU8jdXFnOfh5SPKfR9bgmRQ3HhEaY5ejcCerCW96J5leNEcfkMpWjXy+hvzt0Whnv21Xckbkzo17HZrN+G9C5D1KEeQkdKdg8WVR+3XfhiFLj/S6ANmNjCNbcrR8GKY1GjZahDUyddEza76RuJ3Wqyle0BmNT0RoSHGvjBP+LlY3aOqzsU2sqnzGnItRzr2HnQwVV10MMFo3fbuWopzXqzVjQbnxJM9G79l20Np2eFLDVp4zpiYrGHWSFOnfIDqmy5ke57WnISJwnPz6A+ByhYVJfaxohkk+csbaPCsILQ0ZCzTnCcoh9svw9AIvlHn5YyAa8Gl5o6Ub8lsJXOSftGVtcCsWRiLbD1pg1CTQmoKPPxUFsaU9iPXrfb48+5hFFOVe6+22S8YShFl/HaRq8TMESXmCiRgbgzBV7zmABkJFtH6WUBkXqBTSlUoEsYUHIV61vptroHHui/aVxnynvtkJqTTfto2ukq5ZzpDmQeDE075kM/rOyUuUiJBQ7eszrXKTDKW2xqc6q/OQMfjEiPdtl1Rc44obdRGaTmJhi9h5a/SqH6KPDVoaR+hwLXggnLERroyogElyjbzrkfD5nCE=</Modulus><Exponent>AQAB</Exponent><P>1dlD8Q7ESEgsk507oFT1qZHKgV1Cl6bfNxm7dnCFlkp27kbvsKp5RBzRTCSxClkbwTBfbN0NIQq0o0Rwo9e1Z7yyMGs3v4k3i0Wlw9NkdtineE1dtk/7cBwb6anYZCiyV7TpYK6UCwcwwfyhNBYl5Y7Lr879tUsd1yXfZLVR0YS88gS0LMSsIMRJ6it9H+tcdg+eLTNr9CLIpxuUfYPixhI0xSTF5ZlCplfRaxlvqCh3RJ1IO6Mluv72Df46hKR6mJcMVc2YFUNp/O7038iqGnnBPAlwiT00C2eVh5Qjx4muTg64Zt98ckotsX1Lou8IlBOyem4R1c3b9G6Ga5AZNQ==</P><Q>4DUD8vf0+2LS2PC+cM1s9YqGmR7iukKTBtMPH+rj+wRezwPx7vmNuy8Z5bgfJxfdgHfdQWmQS6gK9OatYR+ZtxQN0B70C2tfEsPBRpPYwOWIiHZQgeczCKevI24w/YyhBU2p1IKljQUsjo1cxyH/es7tVIvfhDw6RVKg4KL8keV7YLSV8kYtJ3/VlrMw5NasfIC2vJ+fatachYRk1BUfB/x7mCDuQmNkQDPiSy24AjzDjMEOPLNNQRWdShkbVYXmX5388VLdbNCrXrCHVdwKrASCGfrCfqhmIY5BE/78c56MprbUCNphkywyiRzzEdhjs6ZgERu7ybQQvd+FQxsAvQ==</Q><DP>yyLdZSjvzvGwVnBvaXgK/A7fXE9oqIH9W2v4JSPx4bfOjb2YhisJkmgFcN0Rx5CpyrPWkaTRieePe9/RV/HaAja+1Tuj8y+3MXbxZblyn2pieuaS9FG5uN8arLWINmxqLOJPJmXvfyJPcJY30zCOwycH2XM4kXRPXkY9lH6gv/PlP8i0Fiqkj2OmCulQrHd4lzVyveEw1PINxJ9wSGJ1kk1ND1BFJDqXk0esSJ4a8JOv59+3896gQqdauCQdFk7fnf8t2nu30cr97SRYPBNzcj7iDdOxsMwQmhzFb8qKykrA5qkZBa+ZmT9ZdFZe+OEzNuYXDjFsg7pPDDvJOHfjWQ==</DP><DQ>1LZXnc9TtKCoi7uz4k9zPW2Ej4c28iGxXfsl0VFHpGIcFOmYQfKvXdStDD3oCG3i7zxJRQMDLFQsuPaVrZyOeJxlEnwbay4eEC56kxw3u6LJKzac4PHZgC+ewM2NWzBtoBtzsbOVnzo2cLR7Pk3qFbh2gA0ILWv6mMRw706Ss1R1/mS2Eho0QtJMcOJm0+U71g9Dz6bdVz5vV1kpU/EJ9Mi89bLgeUnU1fijjFG+zxiZKlQKztoJxGLeTGuPfE9CJps8XDQS8Wbz/y0Z6QKPeW35hO5cUlAwPUu6QF9dYdAdfxncBt4xTrDS7TTzA4454TpK0FBwlEfqzklfJDBdPQ==</DQ><InverseQ>KrqeLyuPFVeAb30HGnirKGLnAJ5SDNACcLnoqscbMC6huenwLL9E18EJQpmVFJLgqyXJTslfmyCcHYsnErKif21VqfQ9QnJrjS5Q2pDrUria7E1opwrhYAKWM/U2MXllCGMurOTLi4sfpkwiUQ8ld8jUJxrIk9XLSAOB+PBN1HZ5UTvzfzPtotms9Q1XBHIHwk1n0jT9z0kg91vVXwFv9JOqLOnDh5RX0JKOZw357bf7toZ2n5aLoAwdzTG6Gqdf/fkUQXOLmH5eaIxwLOJfmjrKHGzyOpbNqYyjjM+N/g3J1vBkDFhdSAibz35neFsJgMyHETSsFaWKZG3PzR80uQ==</InverseQ><D>gDzC1XPxGVUjS2e2XDe7n7GwNIgmH6pWk0OcQf3DQ12/hVtE/DVSrUJ5VDmtAOJc+njwyrzqJ9tpWL4rod6iO7EpHTvlqyq3mLwPVXgKVqYhyyN4xyJH1P5EPPSoVj7L4s2kDlaMhtoX9oNuLojnKIosauGhvs/esXmSd/1udqqEcdWdJIaKeR6f0KZ3wvY/L7UoOna7VW3MKrDrm1EKYQVAWu+1ujfglnBohFkGaDGuapxkRhcXtCqrQSVbT8zWqa6yFL+TbzR6JSu7euwI0/43Cpd6Rg0vm5Z64KK1hNPMP2+ablLCRm3GzeAXZ/F7MG6n/KZ7sYam3Ez56q5eDzO66UL2Ksi81FLTtq/NNegWnELZ79bJy9D1i2R6GmtDG/Lm6BWYHz4m7e7+DMmBJcQbE3cky6iKVyhYVgJ74cREetbXER6Ifriuv9RqumcE1+dN/9yBkinJqa9jFblIGwJMAK9u5fC/Y7Ddba1DS43TYGvnGuYO26QBZPwlyd78t3utHW+Fn38uN/XfYlxMcxlxUHo6eC//zWxRMga+U7AWAZZWLDgHZ+Jp+7cfYypBsIryDiZMUQSkH3o87SMVE9lhT7tO/waJ8mjcdwfAXmCXLhKkFU9CorsU5bIpGkQgGIXNswAGOh8hDvvW1GHLSruGMhoOM9TqHsoO66Ow77E=</D></RSAKeyValue>";
  }
}

【讨论】:

    【解决方案2】:

    感谢 cmets 的 Michael Fehr。

    显然 C# 无法使用公钥解密,至少对于我正在使用的库而言。所以解决方案是给 C# 代码提供私钥,并用公钥解密来自 PHP 服务器的所有消息。

    据我了解,这不会是一个安全问题,尽管“私人”密钥被发送到野外,因为这两个密钥都是为这个目的而设计的。

    【讨论】:

    • 请不要将“加密”与“签名”混为一谈——加密是通过公钥解密完成的b> 使用 私钥 完成。谈到数字签名,签名是使用私钥验证使用公钥完成的。正如已经评论过的:一些库确实允许以相反的方式工作,但 Java 和 C# 不允许“错误的方式”(我认为这是好的)。
    • 我不确定你的意思。在这种情况下,加密是正在做的事情:PHP 正在使用公钥对字符串调用 openssl_public_encrypt(),而 C# 代码正在对 PHP 发送给它的密文调用 rsa.Decrypt()。原始字符串是从 RSA 函数返回的,因此它是加密的。正如维基百科解释的那样,“爱丽丝可以使用她的私钥从密文中恢复消息”。在这种情况下,C# 是 Alice,PHP 是 Bob。
    • 您在回答中写道“签署所有消息” - 这就是为什么我写道不要将签名与加密混为一谈。
    • 哦,哎呀。我现在已经修好了。我的错。
    猜你喜欢
    • 2012-01-20
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 2012-11-18
    • 2020-11-01
    相关资源
    最近更新 更多