Как сохранить / получить открытый / закрытый ключ RSA
Я хочу использовать шифрование с открытым ключом RSA. Каков наилучший способ хранения или получения частных и открытых ключей? Является ли XML хорошей идеей здесь?
Как получить ключи?
RSAParameters privateKey = RSA.ExportParameters(true); RSAParameters publicKey = RSA.ExportParameters(false);
Поскольку RSAParameters имеют следующие элементы: D, DP, DQ, Exponent, InverseQ, Modulus, P, Q
- Подтвердить подпись Authenticode на EXE-C ++ без CAPICOM
- Почему SSL-квитирование дает исключение «Не удалось создать DH keypair»?
- Проблема шифрования RSA
- Шифрование шифрования RSA в iphone
- Почему при использовании функции Non-Random IV с режимом CBC существует уязвимость?
Какой ключ?
- Учитывая, что последний блок не заполнен неправильно
- iText / BouncyCastle ClassNotFound org.bouncycastle.asn1.DEREncodable и org.bouncycastle.tsp.TimeStampTokenInfo
- Шифрование / Расшифровка больших файлов (.NET)
- C # Экспорт частного / открытого ключа RSA из RSACryptoServiceProvider в строку PEM
- Почему мне нужно использовать class Rfc2898DeriveBytes (в .NET) вместо прямого использования пароля в качестве ключа или IV?
- Как долго переборщить соленый hash SHA-512? (соль предоставляется)
- Что является самым безопасным семенем для генерации случайных чисел?
- как использовать RSA для шифрования файлов (огромные данные) в C #
То, что я сделал успешно, – это хранить ключи как XML. В RSACryptoServiceProvider есть два метода: ToXmlString и FromXmlString. ToXmlString вернет строку XML, содержащую либо данные открытого ключа, либо данные открытого и закрытого ключей в зависимости от того, как вы устанавливаете свой параметр. Метод FromXmlString заполняет RSACryptoServiceProvider соответствующими ключевыми данными, если предоставляется строка XML, содержащая либо данные открытого ключа, либо данные открытого и закрытого ключей.
я хотел указать что-то в ответ на комментарий ala, спрашивающий:
Открытый ключ = модуль + показатель
Это точно верно. Существует несколько способов хранения этого exponent
+ modulus
. Первая попытка стандарта была в RFC 3447 ( Стандарты криптографии с открытым ключом (PKCS) № 1: Спецификация криптографии RSA версии 2.1 ), которая определяет структуру открытого ключа под названием RSAPublicKey
:
RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e }
В этом же RFC заявляется, что для хранения открытого ключа вы должны использовать аромат DER для кодирования ASN.1
. У меня есть образец открытого ключа:
- publicExponent : 65537 (условно, что все открытые ключи RSA используют 65537 в качестве экспонента)
- модуль :
0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55
Кодирование DER ASN.1 этого открытого ключа:
30 81 89 ;SEQUENCE (0x89 bytes = 137 bytes) | 02 81 81 ;INTEGER (0x81 bytes = 129 bytes) | | 00 ;leading zero of INTEGER | | DC 67 FA | | F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 82 | | 09 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 99 | | 5D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A | | 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 | | 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C | | 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 | | DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F | | D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55 | 02 03 ;INTEGER (0x03 = 3 bytes) | | 01 00 01 ;hex for 65537. see it?
Если вы возьмете все это выше DER ASN.1 закодированный modulus
+ exponent
:
30 81 89 02 81 81 00 DC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 82 09 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 99 5D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55 02 03 01 00 01
и вы PEM кодируете его (т.е. base64):
MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE 3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV ek9b9VAgMBAAE=
Это соглашение обернуть данные, закодированные в base64, в:
-----BEGIN RSA PUBLIC KEY----- MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE 3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV ek9b9VAgMBAAE= -----END RSA PUBLIC KEY-----
И вот у вас есть ключ PEM DER ASN.1 PKCS # 1 RSA Public .
Следующим стандартом был RFC 4716 ( формат файла открытого ключа Secure Shell (SSH) ). Они включали идентификатор алгоритма ( ssh-rsa
) перед экспонентой и модулем:
string "ssh-rsa" mpint e mpint n
Они не хотели использовать кодировку DER ASN.1 (поскольку она ужасно сложна) и вместо этого предпочли префикс длины в 4 байта :
00000007 ;7 byte algorithm identifier 73 73 68 2d 72 73 61 ;"ssh-rsa" 00000003 ;3 byte exponent 01 00 01 ;hex for 65,537 00000080 ;128 byte modulus DC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 82 09 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 99 5D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55
Возьмите всю вышеперечисленную последовательность байтов, а base-64 закодируйте ее:
AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80 dVek9b9V
И заверните его в заголовок и трейлер OpenSSH:
---- BEGIN SSH2 PUBLIC KEY ---- AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4S bc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80 dVek9b9V ---- END SSH2 PUBLIC KEY ----
Примечание : OpenSSH использует четыре тире с пробелом ( ----
), а не пять тире и пробел ( -----
).
Следующим стандартом был RFC 2459 ( Internet X.509 Сертификат инфраструктуры открытого ключа и Профиль CRL ). Они взяли формат открытого ключа PKCS №1:
RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e }
и расширил его, включив префикс идентификатора алгоритма (в случае, если вы хотите использовать алгоритм шифрования с открытым ключом, отличный от RSA):
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey RSAPublicKey }
«Идентификатор алгоритма» для RSA – 1.2.840.113549.1.1.1
, который исходит из:
-
1
– Идентифицированные ISO идентификаторы-
1.2
– Корпус ИСО-
1.2.840
– США-
1.2.840.113549
– RSADSI-
1.2.840.113549.1
– PKCS-
1.2.840.113549.1.1
– PKCS-1
-
-
-
-
-
X.509 – ужасный стандарт, который определяет ужасно сложный способ кодирования OID
в шестнадцатеричном SubjectPublicKeyInfo
, но в конце кодирование DER ASN.1 SubjectPublicKeyInfo
ключа X.509 SubjectPublicKeyInfo
RSA:
30 81 9F ;SEQUENCE (0x9f bytes = 159 bytes) | 30 0D ;SEQUENCE (0x0d bytes = 13 bytes) | | 06 09 ;OBJECT_IDENTIFIER (0x09 = 9 bytes) | | 2A 86 48 86 ;Hex encoding of 1.2.840.113549.1.1 | | F7 0D 01 01 01 | | 05 00 ;NULL (0 bytes) | 03 81 8D 00 ;BIT STRING (0x8d bytes = 141 bytes) | | 30 81 89 ;SEQUENCE (0x89 bytes = 137 bytes) | | | 02 81 81 ;INTEGER (0x81 bytes = 129 bytes) | | | 00 ;leading zero of INTEGER | | | DC 67 FA | | | F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 82 | | | 09 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 99 | | | 5D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A | | | 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 | | | 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C | | | 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 | | | DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F | | | D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55 | | 02 03 ;INTEGER (0x03 = 3 bytes) | | | 01 00 01 ;hex for 65537. see it?
Вы можете видеть в декодированном ASN.1, как они просто префикс старого RSAPublicKey
с OBJECT_IDENTIFIER
.
Принимая указанные выше байты и PEM (т.е. base-64), кодируя их:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/ 03RlJA3/NHVXpPW/VQIDAQAB
Затем стандарту следует обернуть его заголовком, аналогичным RSA PKCS # 1, но без «RSA» (поскольку это может быть нечто иное, чем RSA):
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcZ/r0nvJyHUUstIB5BqCUJ1CC Cd1nzle4bEpPQJ/S0Wn7mV2FDAeh+UcbVhZu9n+5zypYNjeZKapPqBLoT8eCK51y Kpzeb8LuEm3P8PK4xN18XBrIF1GprN8IIgSdK9f5SwnemutcURrY+PlWnvj7N5s/ 03RlJA3/NHVXpPW/VQIDAQAB -----END PUBLIC KEY-----
Вот как вы придумываете формат открытого ключа X.509 SubjectPublicKeyInfo / OpenSSL PEM .
Это не останавливает список стандартных форматов для открытого ключа RSA. Далее следует проприетарный формат открытого ключа, используемый OpenSSH:
SSH-RSA AAAAB3NzaC1yc2EAAAADAQABAAAAgNxn + vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hs Sk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk + oEuhPx4IrnXIqnN5vwu4Sbc / w8rjE3XxcGsgXUams3wgiBJ0r1 / lLCd6a61xRGtj4 + Vae + Ps3mz / TdGUkDf80dVek9b9V
На самом деле это формат открытого ключа SSH выше, но префикс ssh-rsa
, а не завернутый в ---- BEGIN SSH2 PUBLIC KEY ----
/ ---- END SSH2 PUBLIC KEY ----
.
Здесь RSAKeyValue
открытый ключ XML RSAKeyValue
:
- Exponent :
0x 010001
base64 encoded –AQAB
- Модуль :
0x 00 dc 67 fa f4 9e f2 72 1d 45 2c b4 80 79 06 a0 94 27 50 82 09 dd 67 ce 57 b8 6c 4a 4f 40 9f d2 d1 69 fb 99 5d 85 0c 07 a1 f9 47 1b 56 16 6e f6 7f b9 cf 2a 58 36 37 99 29 aa 4f a8 12 e8 4f c7 82 2b 9d 72 2a 9c de 6f c2 ee 12 6d cf f0 f2 b8 c4 dd 7c 5c 1a c8 17 51 a9 ac df 08 22 04 9d 2b d7 f9 4b 09 de 9a eb 5c 51 1a d8 f8 f9 56 9e f8 fb 37 9b 3f d3 74 65 24 0d ff 34 75 57 a4 f5 bf 55
base64 кодированиюANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V
,
Это означает, что XML:
ANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXYUMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dVek9b9V AQAB
Гораздо проще. Недостатком является то, что он не обертывает, не копирует, не вставляет, так же красиво (т.е. Xml не так удобен для пользователя):
-----BEGIN RSA PUBLIC KEY----- MIGJAoGBANxn+vSe8nIdRSy0gHkGoJQnUIIJ3WfOV7hsSk9An9LRafuZXY UMB6H5RxtWFm72f7nPKlg2N5kpqk+oEuhPx4IrnXIqnN5vwu4Sbc/w8rjE 3XxcGsgXUams3wgiBJ0r1/lLCd6a61xRGtj4+Vae+Ps3mz/TdGUkDf80dV ek9b9VAgMBAAE= -----END RSA PUBLIC KEY-----
Но он делает большой нейтральный формат хранения.
Смотрите также
- Переводчик, двоичный : отлично подходит для декодирования и кодирования данных base64
- ASN.1 JavaScript-декодер : отлично подходит для декодирования кодированных в формате ASN.1 шестнадцатеричных данных (которые вы получаете из
Translator, Binary
- Документация Microsoft ASN.1 : описывает отличительные правила кодирования (DER), используемые для структур ASN.1 (вы не найдете лучшего документа документации в другом месте, я бы сказал, что Microsoft является не только реальной документацией)
Используйте существующий стандартный формат, например PEM. Ваша библиотека криптографии должна предоставлять функции для загрузки и сохранения ключей из файлов в формате PEM.
Экспонентом и модулем являются открытый ключ. D и модуль являются частным ключом. Другие значения позволяют ускорить вычисление для владельца секретного ключа.
Открытый ключ идентифицируется по модулю и экспоненте. Частный ключ идентифицируется другими членами.
Является ли XML хорошей идеей здесь?
Обычно секретные ключи хранятся на смарт-карте HSM. Это обеспечивает хорошую безопасность.