Как я могу преобразовать два стиля формата открытого ключа: один «BEGIN RSA PUBLIC KEY», другой - «BEGIN PUBLIC KEY»

99

Как я могу преобразовать два стиля формата открытого ключа, один формат:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

другой формат:

-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

например, я сгенерировал пару id_rsa / id_rsa.pub с помощью команды ssh-keygen, я вычислил открытый ключ из id_rsa, используя:

openssl rsa -in id_rsa -pubout -out pub2 

затем я снова вычислил открытый ключ из id_rsa.pub, используя:

ssh-keygen -f id_rsa.pub -e -m pem > pub1

содержание pub1:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----

а содержание pub2:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----

Насколько я понимаю, pub1 и pub2 содержат одну и ту же информацию об открытом ключе, но они находятся в другом формате. Интересно, как я могу преобразовать эти два формата? Может ли кто-нибудь показать мне краткое введение в форматы буксировки?

Welkinwalker
источник
Stack Overflow - это сайт для вопросов по программированию и разработке. Этот вопрос кажется не по теме, потому что он не о программировании или разработке. См. Какие темы можно задать здесь, в Справочном центре. Возможно, лучше спросить Super User или Unix & Linux Stack Exchange .
jww

Ответы:

12

Используя phpseclib, чистую реализацию PHP RSA ...

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
$rsa->loadKey('-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----');
$rsa->setPublicKey();

echo $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW);

Похоже, что данные в кодировке base64 совпадают, даже если в заголовке написано BEGIN PUBLIC KEY, а не BEGIN RSA PUBLIC KEY. Так что, может быть, просто используйте str_replace, чтобы исправить это, и все будет хорошо!


источник
314

Я хотел помочь объяснить, что здесь происходит.

«Открытый ключ» RSA состоит из двух чисел:

  • модуль (например, 2048-битное число)
  • показатель степени (обычно 65 537)

Используя ваш открытый ключ RSA в качестве примера, два числа:

  • Модуль : 297,056,429,939,040,947,991,047,334,197,581,225,628,107,021,573,849,359,042,679,698,093,131,908, 015,712,695,688,944,173,317,630,555,849,768,647,118,986,535,684,992,447,654,339,728,777,985,990,170, 679,511,111,819,558,063,246,667,855,023,730,127,805,401,069,042,322,764,200,545,883,378,826,983,730, 553.730.138.478.384.327.116.513.143.842.816.383.440.639.376.515.039.682.874.046.227.217.032.079.079.790.098.143.158.087.443.017.552.531.393.264.852.461.292.775.129.262.080.851.633.535.934.010.704.122.673.027.067.442.627.059.982.393.297.716.922.243.940.155.855.127.430.302.323.883.824.137.412.883.916.794.359.982.603.439.112.095.116.831.297.809.626.059.569.444.750.808.699.678.211.904.501.083.183.234.323.797.142.810.155.862.553.705.570.600.021.649.944.369.726.123.996.534.870.137.000.784.980.673.984.909.570.977.377.882.585.701
  • Показатель : 65 537

Тогда возникает вопрос, как мы хотим хранить эти числа в компьютере. Сначала мы конвертируем оба в шестнадцатеричный:

  • Modulus : EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
  • Показатель степени : 010001

RSA изобрела первый формат

RSA первой изобрела формат:

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

Они решили использовать вариант DER стандарта двоичного кодирования ASN.1 для представления двух чисел [1] :

SEQUENCE (2 elements)
   INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
   INTEGER (24 bit): 010001

Окончательная двоичная кодировка в ASN.1:

30 82 01 0A      ;sequence (0x10A bytes long)
   02 82 01 01   ;integer (0x101 bytes long)
      00 EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
   02 03         ;integer (3 bytes long)
      010001

Если вы затем запустите все эти байты вместе и закодируете их в Base64, вы получите:

MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB

Затем лаборатории RSA сказали добавить заголовок и трейлер:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----

Пять дефисов и слова BEGIN RSA PUBLIC KEY. Это ваш открытый ключ PEM DER ASN.1 PKCS # 1 RSA

  • PEM: синоним base64
  • DER: разновидность кодировки ASN.1
  • ASN.1: используемая схема двоичного кодирования
  • PKCS # 1: формальная спецификация, которая диктует представление открытого ключа как структуры, состоящей из модуля, за которым следует показатель степени.
  • Открытый ключ RSA: используемый алгоритм открытого ключа

Не только RSA

После этого появились другие формы криптографии с открытым ключом:

  • Диффи-Хеллман
  • Эллиптическая кривая

Когда пришло время создать стандарт для представления параметров этих алгоритмов шифрования, люди взяли на вооружение многие идеи, изначально определенные RSA:

  • использовать двоичную кодировку ASN.1
  • base64 это
  • оберните его пятью дефисами
  • и слова BEGIN PUBLIC KEY

Но вместо того, чтобы использовать:

  • -----BEGIN RSA PUBLIC KEY-----
  • -----BEGIN DH PUBLIC KEY-----
  • -----BEGIN EC PUBLIC KEY-----

Вместо этого они решили включить идентификатор объекта (OID) того, что будет дальше. В случае открытого ключа RSA это:

  • RSA PKCS № 1 :1.2.840.113549.1.1.1

Итак, для открытого ключа RSA это было по существу:

public struct RSAPublicKey {
   INTEGER modulus,
   INTEGER publicExponent 
}

Теперь они создали SubjectPublicKeyInfo, который в основном:

public struct SubjectPublicKeyInfo {
   AlgorithmIdentifier algorithm,
   RSAPublicKey subjectPublicKey
}

Фактическое определение DER ASN.1:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm  ::=  SEQUENCE  {
        algorithm               OBJECT IDENTIFIER, -- 1.2.840.113549.1.1.1 rsaEncryption (PKCS#1 1)
        parameters              ANY DEFINED BY algorithm OPTIONAL  },
    subjectPublicKey     BIT STRING {
        RSAPublicKey ::= SEQUENCE {
            modulus            INTEGER,    -- n
            publicExponent     INTEGER     -- e
        }
}

Это дает вам ASN.1 из:

SEQUENCE (2 elements)
   SEQUENCE (2 elements)
      OBJECT IDENTIFIER 1.2.840.113549.1.1.1
      NULL
   BIT STRING (1 element)
      SEQUENCE (2 elements)
         INTEGER (2048 bit): EB506399F5C612F5A67A09C1192B92FAB53DB28520D859CE0EF6B7D83D40AA1C1DCE2C0720D15A0F531595CAD81BA5D129F91CC6769719F1435872C4BCD0521150A0263B470066489B918BFCA03CE8A0E9FC2C0314C4B096EA30717C03C28CA29E678E63D78ACA1E9A63BDB1261EE7A0B041AB53746D68B57B68BEF37B71382838C95DA8557841A3CA58109F0B4F77A5E929B1A25DC2D6814C55DC0F81CD2F4E5DB95EE70C706FC02C4FCA358EA9A82D8043A47611195580F89458E3DAB5592DEFE06CDE1E516A6C61ED78C13977AE9660A9192CA75CD72967FD3AFAFA1F1A2FF6325A5064D847028F1E6B2329E8572F36E708A549DDA355FC74A32FDD8DBA65
         INTEGER (24 bit): 010001

Окончательная двоичная кодировка в ASN.1:

30 82 01 22          ;SEQUENCE (0x122 bytes = 290 bytes)
|  30 0D             ;SEQUENCE (0x0d bytes = 13 bytes) 
|  |  06 09          ;OBJECT IDENTIFIER (0x09 = 9 bytes)
|  |  2A 86 48 86   
|  |  F7 0D 01 01 01 ;hex encoding of 1.2.840.113549.1.1
|  |  05 00          ;NULL (0 bytes)
|  03 82 01 0F 00    ;BIT STRING  (0x10f = 271 bytes)
|  |  30 82 01 0A       ;SEQUENCE (0x10a = 266 bytes)
|  |  |  02 82 01 01    ;INTEGER  (0x101 = 257 bytes)
|  |  |  |  00             ;leading zero of INTEGER
|  |  |  |  EB 50 63 99 F5 C6 12 F5  A6 7A 09 C1 19 2B 92 FA 
|  |  |  |  B5 3D B2 85 20 D8 59 CE  0E F6 B7 D8 3D 40 AA 1C 
|  |  |  |  1D CE 2C 07 20 D1 5A 0F  53 15 95 CA D8 1B A5 D1 
|  |  |  |  29 F9 1C C6 76 97 19 F1  43 58 72 C4 BC D0 52 11 
|  |  |  |  50 A0 26 3B 47 00 66 48  9B 91 8B FC A0 3C E8 A0
|  |  |  |  E9 FC 2C 03 14 C4 B0 96  EA 30 71 7C 03 C2 8C A2  
|  |  |  |  9E 67 8E 63 D7 8A CA 1E  9A 63 BD B1 26 1E E7 A0  
|  |  |  |  B0 41 AB 53 74 6D 68 B5  7B 68 BE F3 7B 71 38 28
|  |  |  |  38 C9 5D A8 55 78 41 A3  CA 58 10 9F 0B 4F 77 A5
|  |  |  |  E9 29 B1 A2 5D C2 D6 81  4C 55 DC 0F 81 CD 2F 4E 
|  |  |  |  5D B9 5E E7 0C 70 6F C0  2C 4F CA 35 8E A9 A8 2D 
|  |  |  |  80 43 A4 76 11 19 55 80  F8 94 58 E3 DA B5 59 2D
|  |  |  |  EF E0 6C DE 1E 51 6A 6C  61 ED 78 C1 39 77 AE 96 
|  |  |  |  60 A9 19 2C A7 5C D7 29  67 FD 3A FA FA 1F 1A 2F 
|  |  |  |  F6 32 5A 50 64 D8 47 02  8F 1E 6B 23 29 E8 57 2F 
|  |  |  |  36 E7 08 A5 49 DD A3 55  FC 74 A3 2F DD 8D BA 65
|  |  |  02 03          ;INTEGER (03 = 3 bytes)
|  |  |  |  010001

И, как и раньше, вы берете все эти байты, кодируете их в Base64, и вы получаете второй пример:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB   

Добавьте немного другой заголовок и трейлер, и вы получите:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB   
-----END PUBLIC KEY-----

И это ваш открытый ключ X.509 SubjectPublicKeyInfo / OpenSSL PEM [2] .

Сделай это правильно или взломай

Теперь, когда вы знаете, что кодировка не является волшебной, вы можете написать все части, необходимые для анализа модуля и экспоненты RSA. Или вы можете узнать, что первые 24 байта просто добавлены новые вещи поверх исходного стандарта PKCS # 1.

30 82 01 22          ;SEQUENCE (0x122 bytes = 290 bytes)
|  30 0D             ;SEQUENCE (0x0d bytes = 13 bytes) 
|  |  06 09          ;OBJECT IDENTIFIER (0x09 = 9 bytes)
|  |  2A 86 48 86   
|  |  F7 0D 01 01 01 ;hex encoding of 1.2.840.113549.1.1
|  |  05 00          ;NULL (0 bytes)
|  03 82 01 0F 00    ;BIT STRING  (0x10f = 271 bytes)
|  |  ...

Эти первые 24 байта - это «новый» материал:

30 82 01 22 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 82 01 0F 00

И благодаря необычайному стечению обстоятельств удачи и удачи:

24 байта точно соответствуют 32 символам в кодировке base64

Потому что в Base64: 3 байта превращаются в четыре символа:

30 82 01  22 30 0D  06 09 2A  86 48 86  F7 0D 01  01 01 05  00 03 82  01 0F 00
\______/  \______/  \______/  \______/  \______/  \______/  \______/  \______/
    |         |         |         |         |         |         |         |
  MIIB      IjAN      Bgkq      hkiG      9w0B      AQEF      AAOC      AQ8A

Это означает, что если вы возьмете второй открытый ключ X.509, первые 32 символа будут соответствовать только вновь добавленным материалам:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END PUBLIC KEY-----

Если вы удалите первые 32 символа и измените его на BEGIN RSA PUBLIC KEY :

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----

У вас есть именно то, что вы хотели - старый RSA PUBLIC KEYформат.

Ян Бойд
источник
29
Святые шары, это было познавательно! Спасибо. Это решило мою проблему с парнем-питоном, который ожидал только BEGIN RSA PUBLIC KEY. Хотя в вашем последнем примере похоже, что вы забыли удалить 32 символа.
NullVoxPopuli
Какой инструмент вы использовали для распечатки шестнадцатеричной структуры файлов?
Buge
7
@Buge Я использовал отличный декодер ASN.1 JavaScript . Это и TRANSLATOR, BINARY - два отличных инструмента, которые нужно иметь в своем арсенале трюков.
Ian Boyd
1
Начало модуля имеет дополнительный символ «1». Это должно начинаться так ... 297,056,429,939,040,947,991,047,334,197,581,225,628,107,02,573 ... но НЕ это ... 297,056,429,939,040,947,991,047,334,197,581,225,628,107,021,573 ... надеюсь, что это поможет кому-то разозлиться на их гексагональное преобразование.
EmpathicSage
2
jsFiddle версия ASN.1 js . Это также на github
Ян Бойд
52

Я нашел этот веб-сайт хорошим техническим объяснением различных форматов: https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem

«BEGIN RSA PUBLIC KEY» - это PKCS # 1, который может содержать только ключи RSA.

«НАЧАТЬ ОТКРЫТЫЙ КЛЮЧ» - это PKCS # 8, который может содержать множество форматов.

Если вы просто хотите преобразовать их с помощью командной строки, для этого подойдет "openssl rsa".

Чтобы преобразовать PKCS # 8 в PKCS # 1:

openssl rsa -pubin -in <filename> -RSAPublicKey_out

Чтобы преобразовать PKCS # 1 в PKCS # 8:

openssl rsa -RSAPublicKey_in -in <filename> -pubout
Эсме Повирк
источник
2
Я ничего не могу найти об открытом ключе в PKCS # 8 ( RFC 5208 ).
Франклин Ю
Не работает на MacOS:unknown option -RSAPublicKey_in
nakajuice 08
2
@FranklinYu: да, PKCS8 - это только приватный ключ, и в этом вопросе polarssl ошибается. Общая форма открытого ключа определяется X.509 и, в частности, типом SubjectPublicKeyInfo, как правильно указано в (длинном!) Ответе Яна Бойда; эта информация (более удобно) дублируется в RFC5280 плюс другие RFC в зависимости от алгоритма, с «базовым» RSA в RFC3279.
dave_thompson_085
@nakajuice: вам нужен OpenSSL версии 1.0.0 (выпущен в 2010 г.) или выше. AIUI Apple перестала поддерживать OpenSSL в OS (X), поэтому вам может потребоваться версия от brew или аналогичная.
dave_thompson_085
Это привело меня в правильное направление для преобразования из формата OpenSSH. В итоге я использовал ssh-keygen следующим образом: ssh-keygen -i -f ~ / .ssh / id_rsa.pub -e -m PKCS8> ~ / .ssh / id_rsa.pub.pem
Брэдли
13

Хотя приведенные выше комментарии относительно 32-байтовых заголовков, форматов OID и тому подобного интересны, я лично не вижу такого поведения, если я понимаю суть. Я подумал, что было бы полезно изучить это подробнее, что, по мнению большинства, является чрезмерным. Ничто не превосходит крайности.

Для начала я создал закрытый ключ RSA и проверил его:

>openssl rsa -in newclient_privatekey.pem  -check
RSA key ok
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4pOYWo+GeAEmU4N1HPZj1dxv70
4hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyozC/zSqcuU6iBrvzDTpyG1zhIG
76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknmLBrtZkLkBhchgYnMswIDAQAB
AoGAQaJ5aivspeEXcpahWavzAFLv27+Tz48usUV+stY6arRhqbBEkV19/N5t8EPA
01U6IGDQ8QIXEIW/rtsHKM6DAZhAbakPDJhJRatcMzJ08ryIkP/c3+onkTquiveG
brw7xzn6Xa8ls04aQ6VQR4jxXUjV5bB72pFZnGRoAmS2NiECQQDUoISbmTGjnHM+
kEfunNTXbNmKklwTYhyZaSVsSptnD7CvLWB4qB/g4h2/HjsELag6Z7SlWuYr7tba
H3nBYn35AkEAykFRudMqlBy3XmcGIpjxOD+7huyViPoUpy3ui/Bj3GbqsbEAt9cR
PyOJa1VFa2JqShta1Tdep8LJv1QvgvY7CwJBAML+al5gAXvwEGhB3RXg0fi2JFLG
opZMFbpDCUTkrtu3MeuVC7HbTVDpTSpmSO0uCed2D97NG+USZgsnbnuBHdECQQCw
S3FWPXdetQ0srzaMz61rLzphaDULuZhpBMNqnTYeNmMaUcPjewagd3Rf52rkKFun
juKE+Yd7SXGbYWEskT5zAkAD7tbNwe5ryD2CT71jrY/5uXMR2yg/A4Ry2ocZkQUp
iGflLrHnODvHO5LYLBlSKpjanBceYHJLuMFNZruf7uBM
-----END RSA PRIVATE KEY-----

(О, ужасы! Я открыл секретный ключ. Ммм ...)

Я извлекаю и показываю его открытый ключ:

>openssl rsa -in newclient_privatekey.pem -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4p
OYWo+GeAEmU4N1HPZj1dxv704hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyoz
C/zSqcuU6iBrvzDTpyG1zhIG76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknm
LBrtZkLkBhchgYnMswIDAQAB
-----END PUBLIC KEY-----

Так получилось, что есть еще один выходной параметр открытого ключа (как упоминалось в предыдущем комментарии). Вместо этого я извлекаю и отображаю открытый ключ, используя это ключевое слово:

>openssl rsa -in newclient_privatekey.pem -RSAPublicKey_out
writing RSA key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKf86UWTu8tFDp0GI1CS+OeGbik5haj4Z4ASZTg3Uc9mPV3G/vTiGbzR
5hzuHXbFzuhVwMsF0cHIYAYGlB+mOB0/KjML/NKpy5TqIGu/MNOnIbXOEgbvoqty
N1tfo+UoA872v90JGZSKMWFWhSVjrLAaSeYsGu1mQuQGFyGBicyzAgMBAAE=
-----END RSA PUBLIC KEY-----

Ну ну. Эти два значения открытого ключа не совпадают, хотя они получены из одного и того же закрытого ключа. Или они такие же? Я вырезаю и вставляю две строки открытого ключа в их собственные файлы, а затем проверяю модуль для каждой:

>openssl rsa -in newclient_publickey.pem -pubin -modulus
Modulus=
A7FCE94593BBCB450E9D06235092F8E7
866E293985A8F867801265383751CF66
3D5DC6FEF4E219BCD1E61CEE1D76C5CE
E855C0CB05D1C1C8600606941FA6381D
3F2A330BFCD2A9CB94EA206BBF30D3A7
21B5CE1206EFA2AB72375B5FA3E52803
CEF6BFDD0919948A316156852563ACB0
1A49E62C1AED6642E40617218189CCB3
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4p
OYWo+GeAEmU4N1HPZj1dxv704hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyoz
C/zSqcuU6iBrvzDTpyG1zhIG76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknm
LBrtZkLkBhchgYnMswIDAQAB
-----END PUBLIC KEY-----

«Pubin» говорит ПДС , что это на самом деле это должен быть открытый ключ, и не жалуются , что это не закрытый ключ.

Теперь мы берем открытый ключ RSA, отображаем модуль и преобразуем его в простой старый «открытый ключ» (опять же, мы должны сказать ему, что ввод является открытым ключом):

>openssl rsa -in newclient_rsapublickey.pem -RSAPublicKey_in -modulus
Modulus=
A7FCE94593BBCB450E9D06235092F8E7
866E293985A8F867801265383751CF66
3D5DC6FEF4E219BCD1E61CEE1D76C5CE
E855C0CB05D1C1C8600606941FA6381D
3F2A330BFCD2A9CB94EA206BBF30D3A7
21B5CE1206EFA2AB72375B5FA3E52803
CEF6BFDD0919948A316156852563ACB0
1A49E62C1AED6642E40617218189CCB3
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4p
OYWo+GeAEmU4N1HPZj1dxv704hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyoz
C/zSqcuU6iBrvzDTpyG1zhIG76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknm
LBrtZkLkBhchgYnMswIDAQAB
-----END PUBLIC KEY-----

Отображается тот же модуль и то же значение «открытого ключа». Чтобы сделать вещи более интересными (во всяком случае для меня), когда мы добавляем ключевое слово RSAPublicKey_out, мы получаем:

>openssl rsa -in newclient_rsapublickey.pem -RSAPublicKey_in -modulus -RSAPublicKey_out
Modulus=
A7FCE94593BBCB450E9D06235092F8E7
866E293985A8F867801265383751CF66
3D5DC6FEF4E219BCD1E61CEE1D76C5CE
E855C0CB05D1C1C8600606941FA6381D
3F2A330BFCD2A9CB94EA206BBF30D3A7
21B5CE1206EFA2AB72375B5FA3E52803
CEF6BFDD0919948A316156852563ACB0
1A49E62C1AED6642E40617218189CCB3
writing RSA key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKf86UWTu8tFDp0GI1CS+OeGbik5haj4Z4ASZTg3Uc9mPV3G/vTiGbzR
5hzuHXbFzuhVwMsF0cHIYAYGlB+mOB0/KjML/NKpy5TqIGu/MNOnIbXOEgbvoqty
N1tfo+UoA872v90JGZSKMWFWhSVjrLAaSeYsGu1mQuQGFyGBicyzAgMBAAE=
-----END RSA PUBLIC KEY-----

... и когда мы трансмогрифицируем простой старый `` открытый ключ '' в открытый ключ RSA:

>openssl rsa -in newclient_publickey.pem -pubin -RSAPublicKey_out
writing RSA key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKf86UWTu8tFDp0GI1CS+OeGbik5haj4Z4ASZTg3Uc9mPV3G/vTiGbzR
5hzuHXbFzuhVwMsF0cHIYAYGlB+mOB0/KjML/NKpy5TqIGu/MNOnIbXOEgbvoqty
N1tfo+UoA872v90JGZSKMWFWhSVjrLAaSeYsGu1mQuQGFyGBicyzAgMBAAE=
-----END RSA PUBLIC KEY-----

... неумолимо идем вперед, и хотя мы сделали это всего несколько команд назад, чтобы придать смысл, мы перевернули все так, чтобы трансмогрификация происходила от RSA к обычному старому «общедоступному ключу»:

>openssl rsa -in newclient_rsapublickey.pem -RSAPublicKey_in -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4p
OYWo+GeAEmU4N1HPZj1dxv704hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyoz
C/zSqcuU6iBrvzDTpyG1zhIG76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknm
LBrtZkLkBhchgYnMswIDAQAB
-----END PUBLIC KEY-----

... что возвращает нас к тому, с чего мы начали. Что мы узнали?

Резюме: клавиши внутри такие же, только выглядят по-разному. В предыдущем комментарии указывалось, что формат ключа RSA был определен в PKCS # 1, а простой старый формат «открытого ключа» был определен в PKCS # 8. Однако редактирование одной формы не превращает ее в другую. Надеюсь, теперь я забил это различие до смерти.

Тем не менее, если еще осталась искра жизни, давайте еще немного рассмотрим сертификат, который был изначально сгенерирован с помощью закрытого ключа RSA так давно, исследуя его открытый ключ и модуль:

>openssl x509 -in newclient_cert.pem -pubkey -noout -modulus
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn/OlFk7vLRQ6dBiNQkvjnhm4p
OYWo+GeAEmU4N1HPZj1dxv704hm80eYc7h12xc7oVcDLBdHByGAGBpQfpjgdPyoz
C/zSqcuU6iBrvzDTpyG1zhIG76KrcjdbX6PlKAPO9r/dCRmUijFhVoUlY6ywGknm
LBrtZkLkBhchgYnMswIDAQAB
-----END PUBLIC KEY-----
Modulus=
A7FCE94593BBCB450E9D06235092F8E7
866E293985A8F867801265383751CF66
3D5DC6FEF4E219BCD1E61CEE1D76C5CE
E855C0CB05D1C1C8600606941FA6381D
3F2A330BFCD2A9CB94EA206BBF30D3A7
21B5CE1206EFA2AB72375B5FA3E52803
CEF6BFDD0919948A316156852563ACB0
1A49E62C1AED6642E40617218189CCB3

... и все они жили долго и счастливо: сертификат имеет то же значение модуля, что и открытый ключ RSA, закрытый ключ RSA и простой старый «открытый ключ». Сертификат содержит то же самое обычное старое значение «открытого ключа», которое мы видели ранее, хотя он был подписан файлом, помеченным как закрытый ключ RSA. Можно с уверенностью сказать, что есть консенсус.

В квадранте X509 галактики OpenSSL нет эквивалентного ключевого слова «RSAPublicKey_out», поэтому мы не можем попробовать это, хотя значение модуля описывается как «модуль ключа RSA», который, как я полагаю, максимально приближен к нам.

Я не знаю, как все это будет выглядеть с сертификатом, подписанным DSA.

Я понимаю, что это не отвечает на исходный вопрос, но, возможно, дает некоторые полезные сведения. Если нет, мои извинения. По крайней мере, то, что не следует делать, и предположения, которых не следует делать.

Несомненно, можно было заметить немного раздражающее повторение «записи ключа RSA», когда ничего подобного не происходит. Я предполагаю, что имеется в виду, что модуль rsa распознает простой старый открытый ключ как истинный ключ RSA, и поэтому он продолжает твердить о «ключ RSA» (плюс, в конце концов, это модуль rsa). Если я правильно помню, в общей структуре EVP_PKEY есть объединение для всех типов ключей, причем каждый тип ключа имеет свой собственный специальный набор значений (услужливо названные g, w, q и другие согласные).

В заключение отмечу, что была жалоба на программирование и разработку; Теперь каждая команда OpenSSL, очевидно, имеет соответствующий код, и если кто-то хочет исследовать все чудеса программирования OpenSSL сегодня, командная строка может показаться разумным местом для начала. В этом конкретном случае (поскольку я использую недавний cygwin) можно начать с просмотра \ openssl-1.0.2f \ apps \ rsa.c и (учитывая высокую устойчивость к макросам) \ openssl-1.0. 2f \ крипто \ pem \ pem_all.c

Жаворонок
источник
8

Единственное различие между pub1 и pub2, кроме верхнего / нижнего колонтитула, эта дополнительная строка в pub2: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A. Если вы удалите это, Base 64 будет идентичен таковому в pub1.

Дополнительная строка соответствует идентификатору алгоритма в соответствии с этим ответом .

gtrig
источник