Как расшифровать данные с открытым ключом - PullRequest
0 голосов
/ 09 апреля 2019

Подобные вопросы задавались много раз, но я искал ответ 2 дня и не нашел того, что искал.Прежде всего, у меня есть четкое понимание безопасности открытого / закрытого ключа с точки зрения потребителя.Я никогда не изучал математику за этим.Я понимаю, что обычно вы используете открытый ключ для шифрования данных и закрытый ключ для его расшифровки.Я также знаю о другой паре операций: подписание данных с помощью закрытого ключа и проверка его с помощью открытого ключа.В .NET есть RSACryptoServiceProvider, реализующий или упаковывающий все эти операции.Если мы посмотрим на метод Verify, он будет объявлен как

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

. Моя проблема в том, что вместо проверки я хотел бы расшифровать данные подписи в исходный хеш, который был подписан с помощью закрытого ключа.Теперь я немного смущен.Я нашел много ответов о том, что это невозможно, но невозможно ли это с точки зрения API или с математической точки зрения?Я бы предположил, что это может быть невозможно только с точки зрения API .NET, потому что если я использую OpenSSL и делаю это

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

, я могу расшифровать подпись (signature.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 Ответ

1 голос
/ 10 апреля 2019

Я не верю, что это возможно с помощью крипто API .NET, по крайней мере, я не смог найти способ.Я был вынужден повторно реализовать алгоритм RSA, используя BigInteger.Это удивительно просто.

  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

...