如何使用公开密钥解密数据

时间:2019-04-09 20:37:05

标签: .net rsa encryption-asymmetric

类似的问题被问了很多遍,但是我一直在寻找答案,但是没有找到我想要的东西。首先,从使用的角度来看,我对公/私钥安全性有相当的了解。我从来没有研究过背后的数学。据我了解,通常您使用公共密钥来加密数据,并使用私有密钥来解密数据。我还知道另一对操作:使用私钥对数据签名并使用公钥进行验证。在.NET中,有RSACryptoServiceProvider实现或包装所有这些操作。如果我们看一下Verify方法,它就是这样声明的

public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature)

我的问题是,我不想验证,而是希望将签名数据解密为使用私钥签名的原始哈希。现在,我有点困惑。我发现许多答案表明这是不可能的,但是从API的角度还是从数学的角度来看这是不可能的?我猜想可能仅从.NET API的角度来看是不可能的,因为如果我使用OpenSSL并这样做

.\openssl.exe rsautl -verify -certin -inkey dev.crt -in signature.dat -out original.dat

我可以将签名(signature.dat)解密为创建签名的原始值(original.dat)。我相信从数学上证明这是可能的。

现在最大的问题是,有没有一种方法可以使用.NET,任何变通方法,任何库,是否有什么可以为我做什么,OpenSSL可以做什么。请不要建议从代码中执行OpenSSL。我无法将其与应用程序打包在一起。我还需要其他东西,最好是使用现有的RSACryptoServiceProvider找到解决方法。

更新的分步示例:

我创建了一个哈希(128个字节)

3D 0C 20 5C 73 DD 81 73 2A 41 F8 C7 A1 32 86 A5
F5 B5 D4 80 E0 0E 43 D0 7C 81 37 5F E5 AA 85 2A
02 EC 63 FA B1 87 44 92 E7 6D AA 96 EA 5E AA 6D
FC 38 8E C4 21 F6 7E D5 2A C5 9E 0F 27 2A D7 B9
2C C8 7C CF 8E 52 B1 FD AF 1C E6 80 BB 68 81 55
DC 25 7B 8D ED 22 64 87 0F 4D 08 6A B1 33 74 FA
C3 9E AA 12 4A 56 01 AA A5 A8 5E 75 F5 A4 8F EF
F7 E4 AA DB 58 E7 61 96 F7 40 B7 A1 CA 49 E5 FC

然后我执行了

.\openssl.exe rsautl -sign -inkey dev.key -in hash.dat -out signed_hash.dat

生成签名,其中签名的哈希结果是这个。 256个字节

69 A3 DF A1 F6 4C 88 8B 83 E7 C1 BD 4E 12 D6 24
4B 5F 52 23 A4 3B 4F 27 11 37 C0 4C FA 99 3D 43
2B E5 0E 37 EF BB 2B 10 FF 28 4D 84 93 5A A2 75
52 DA C8 83 75 6A B2 29 91 79 AC 0C 12 8D C6 50
3A B4 71 CA 3F CD 15 73 2C 33 1E FA 4D E3 35 3A
68 A5 6E 1D 2B FD 91 03 3D 2E 97 C0 1A 4F A7 E2
FF 65 5A F9 96 3E 1B 68 A6 57 43 B4 62 35 32 F5
17 DF 76 55 8F 89 81 34 F2 B6 24 83 B8 76 8D E3
AD DB 7E 38 DE C0 94 5B 90 15 D7 4F 25 86 90 1C
B4 12 94 A4 0E BD 76 BB CF 54 2F 24 4D DE B5 8D
C8 40 DD 16 81 50 20 BD 11 A1 65 07 9B 00 D8 C1
60 D9 B2 4F 64 F7 4E 02 A7 B6 8B E6 2A D1 AC EF
3C E7 C5 4D 95 6D 70 B7 31 A2 60 AE 37 D3 83 21
23 BD 25 34 1E B7 D9 EA 05 7A A3 C3 9C DB DA A4
A6 14 11 C6 40 0D BD CB DD C2 F2 87 3A B8 A2 E3
7E 80 D5 8B 01 91 4B B2 0A 42 54 B6 3B 7F 41 3C

然后,如果我这样做

.\openssl.exe rsautl -verify -certin -inkey dev.crt -in signed_hash.dat -out original_hash.dat

我取回了原始哈希。从RSAParameters中获取的公共密钥的公共指数值是

01 00 01

模量是这个

aa 0e 02 74 4c b5 06 87 f6 ae 4c 2c 71 76 59 7a
84 47 07 db 8e dd 8a 58 2c ba e5 1b 91 45 3e de
7d a9 d4 0a b9 cf 9f c2 19 cf af d3 30 fd 55 fb
81 d0 ef 68 ef c7 b0 fc 49 c9 4f fd 20 e9 ea 04
31 57 8f c2 1e 85 76 86 63 12 e0 00 01 17 02 80
76 fc f9 bc 09 61 80 6b a3 0b 8e de 1d b2 2f d6
ed 18 32 4b 03 0b 3b 2c ca 75 b6 85 95 20 5a 16
dc 4f 33 4b 97 84 fe 3f 9f 04 5b ba 56 44 73 aa
9f b0 7d 44 f4 58 ea a2 9d 35 d9 5c 8d 2d 39 a8
ce ee 19 24 9e 78 74 dc 6d 16 2b d7 24 bf 80 fa
a6 12 bf bd 89 cd 47 d0 bd 19 21 7d 3d 65 7b 06
9b 24 55 3c ca 4c 63 ce 40 ad a3 c5 72 cf 66 79
e0 f2 23 05 fa 20 32 b0 02 96 f1 a3 82 40 b4 b9
ac 9c f1 cf 83 a3 f0 50 83 81 b6 d7 f8 5f 93 21
71 0b f9 26 87 3d 61 17 cc 0c 09 09 b4 40 e4 92
45 fb 77 ca 94 cb 15 fb 54 68 4a c3 31 2d 57 09

我需要做的是从我的C#.NET代码中的签名哈希中检索原始哈希,而我不知道该怎么做。

1 个答案:

答案 0 :(得分:1)

我不认为可以使用.NET加密API,至少我找不到方法。我被迫使用BigInteger重新实现RSA算法。出奇的简单。

  1. 将签名,公共指数和密钥模数转换为BigIntegers。
  2. 致电BigInteger.ModPow(signature, exponent, modulus)
  3. 将结果转换为字节[];这是您要查找的哈希。

注意字节顺序和签名问题... https://msdn.microsoft.com/en-us/library/dd268207(v=vs.110).aspx

以下是有关Java的特定主题的信息(并且不存在您将在.NET中遇到的字节序问题)... https://www.nayuki.io/page/java-biginteger-was-made-for-rsa-cryptography