web-dev-qa-db-de.com

Wie konvertiert man einen öffentlichen Schlüssel von einem JWK in PEM für OpenSSL?

Es gibt einen RSA-Schlüssel von einem RFC:

https://tools.ietf.org/html/rfc7516#appendix-A.1

 {"kty":"RSA",
  "n":"oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW
       cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S
       psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a
       sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS
       tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj
       YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw",
  "e":"AQAB",
  "d":"kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N
       WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9
       3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk
       qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl
       t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd
       VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ",
  "p":"1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-
       SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lf
       fNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0",
  "q":"wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBm
       UDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aX
       IWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc",
  "dp":"ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KL
       hMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827
       rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE",
  "dq":"Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCj
       ywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDB
       UfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis",
  "qi":"VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7
       AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3
       eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY"
 }

Ich habe jwk-to-pem versucht:

https://stackoverflow.com/a/35995690/4742108

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAoahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E+BVvxkeDNjbC4
he8rUWcJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S
psk/ZkoFnilakGygTwpZ3uesH+PFABNIUYpOiN15dsQRkgr0vEhxN92i2asbOenS
ZeyaxziK72UwxrrKoExv6kc5twXTq4h+QChLOln0/mtUZwfsRaMStPs6mS6Xrgxn
xbWhojf663tuEQueGC+FCMfra36C9knDFGzKsNa7LZK2djYgyD3JR/MB/4NUJW/T
qOQtwHYbxevoJArm+L5StowjzGy+/bq6GwIDAQAB
-----END RSA PUBLIC KEY-----

Er musste auch "RSA PUBLIC KEY" durch "PUBLIC KEY" ersetzen.

Der Befehl openssl rsa -inform PEM -pubin gibt Folgendes aus:

unable to load Public Key
139911798556312:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1197:
139911798556312:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:374:Type=X509_ALGOR
139911798556312:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=algor, Type=X509_PUBKEY
139911798556312:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:83:

Wie bekomme ich einen brauchbaren Schlüssel?

7
Velkan

Der von Ihnen gepostete Schlüssel ist also eine einfache asn-Sequenz eines öffentlichen Schlüssels und des öffentlichen Exponenten. Es sieht ungefähr so ​​aus:

SEQUENCE ::= {
    n Integer,
    e Integer
}

OpenSSL mag das nicht, weil es einige andere Dinge fehlt, wie zum Beispiel einen ObjectIdenifier, so dass openssl weiß, für welchen Algorithmus der Schlüssel ist.

Sie können dies schnell beheben, indem Sie auch die Option -RSAPublicKey_in angeben, sodass der vollständige Befehl in etwa wie folgt aussehen wird:

openssl rsa -inform pem -in FILEPATH.pem -pubin -pubout -RSAPublicKey_in

und ändern Sie den Header der Datei zurück, um "RSA" aufzunehmen:

-----BEGIN RSA PUBLIC KEY-----

sowie die Fußzeile:

-----END RSA PUBLIC KEY-----

Dadurch wird es auch in einem "normalen" öffentlichen Schlüsselformat ausgegeben, das den fehlenden ObjectIdentifier enthält.

Hinweis: Ich bin nicht sicher, welche Versionsanforderungen für -RSAPublicKey_in gelten, aber ich habe OpenSSL 1.1.0 verwendet.

3
vcsjones

Ich entwickelte eine Klasse PHP, die öffentliche/private Schlüssel von JWK in PEM (und umgekehrt) konvertieren kann.

Sie finden diese Klasse hier .

Grundsätzlich müssen Sie jede Komponente von Base64UrlSafe in eine binäre Zeichenfolge dekodieren und sie gemäß der in RFC3447 beschriebenen ASN.1-Struktur zusammenstellen.

Trotzdem empfehle ich Ihnen, eine spezielle Bibliothek/ein spezielles Tool zu verwenden, um Ihre Arbeit zu vereinfachen. Mit meiner PHP -Bibliothek sieht Ihr Code folgendermaßen aus:

use  Jose\KeyConverter\RSAKey;
$key = new RSAKey([
    "kty" => "RSA",
    "n"   => "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUWcJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3Spsk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2asbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMStPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2djYgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw",
    "e"   => "AQAB",
    "d"   => "kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5NWV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD93Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghkqDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vlt3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSndVTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ",
    "p"   => "1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lffNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0",
    "q"   => "wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBmUDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aXIWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc",
    "dp"  => "ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KLhMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE",
    "dq"  => "Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCjywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDBUfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis",
    "qi"  => "VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY",
]);
$pem = $key->toPEM();
4

Ich habe ein Befehlszeilentool namens lokey geschrieben, um bei Schlüsselkonvertierungen wie dieser zu helfen. 

Mithilfe von curl, grep und tr können Sie den Schlüssel aus der Frage abrufen. Mit diesem Befehl können Sie den JWK-formatierten privaten Schlüssel in einen PEM-formatierten privaten Schlüssel konvertieren: 

$ curl -s https://tools.ietf.org/rfc/rfc7516.txt | grep '"n":"oahUI' -B1 -A28 | tr -d '[:space:]' | lokey to pem

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAoahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E+BVvxkeDN
jbC4he8rUWcJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2K
rf3Spsk/ZkoFnilakGygTwpZ3uesH+PFABNIUYpOiN15dsQRkgr0vEhxN92i2asb
OenSZeyaxziK72UwxrrKoExv6kc5twXTq4h+QChLOln0/mtUZwfsRaMStPs6mS6X
rgxnxbWhojf663tuEQueGC+FCMfra36C9knDFGzKsNa7LZK2djYgyD3JR/MB/4NU
JW/TqOQtwHYbxevoJArm+L5StowjzGy+/bq6GwIDAQABAoIBAQCQt20iPoZsOSz8
CkJJNhC16Vw222UqI7I/Mytcd4j7KTUXv6SkPFjj5Zjk1ZXkqe1oR5dLWPzYTfvn
HGFYwdfK+Nh5w9P1+nBH8z2BXyf0euHZqdOlMP3cO3rbKlbfIOwnMGdOeti7WLBZ
GAEqsRhjjqoBkisDbEDCebZfu4ZHWGCGSoOnRWqPeRtILPVfJ8Kzr8t6EHC3EcjK
HxGKnLjSnbiag4BuDFXDevFP++W3dRV7hY7cmQk7OWlR/4pNUjY+2Cb50BHFMS0T
6J37g4mvSH4r5UWzdVKd1VMjOdLF/KuPwgsvowb9S/xgC7tUgtIHeU5bTzn7ioTc
POCtOODJAoGBANa+dl5OOnPi7HweT+ONqe2rXT1K8UEsuJrYv7WSNzIH9hLhVW1K
Awb2kUPklsZG5JqBMy+yV66EgY0qyt2CEIGHTIMgBD0z417/4SNv9Xk0j1WX8y9J
X3zZ9NyF6lheTAxbqFGBNIc29r4a5Tf6yq23wyMFG06444InkW8AugpdAoGBAMC2
9+ce4ZkFmbFiZgf75XvO4oYGdfUvJQRETiyLGRuGsmVXvR4vYA1QjgZlA3Wg2FU0
jcf/BcsNWGGvVxqxpw3sNNCdvHEVKHgQf4yiNaJmtDq79U/WlyFsSsHeIL8RSJjl
q90ES/ShAUc5NkWrVAZ5g2SUyAH8E7NIOvFGR77XAoGAZK+YwE7diUh0qR1tR7w8
WHtolDx3MZ/OTowiFvgfeQ3SiresXjm9gZ5KLhMXvo+uz+KUJWDxS5pFQ/M0evdo
1dKiRTjVw/x4NyqyXPM5nULPkcpU827rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznj
nd/zVpAmZZq60WPMBMfKcuECgYAOrSB+AnUN0UZeIu9ARme4oQ3RRSawkHGSPJ1z
ePhlh0GIxEDLzrHS8cKPLBwyVhiDjKgLhhlr2E1VyyOoDcV6IvX2uTyDpCfb1O3R
yPyqrIWnP280MFR8ICIlV4RI6MkNk9Gd0djy/Vv6j5nZfm28vH5MJ6R/ujHJ4oNS
opaOKwKBgFSDKTGGz3+O3U9cP8w1F3z4prEnoJzDgNc02l+2hpP/Lq2OkfPmVtRc
VOwJVgMi1sm6qurdelRXe4UHdMun5VCuEpTsnQetYMGpzrFxjgDr/NnB6tBN3i+B
67WZFLir5z6zJ7FFBZX1Hcm1c8co8/SRf18mmNeGq3S0o3+C/xTW
-----END RSA PRIVATE KEY-----

lokey hat auch einen fetch-Befehl, mit dem JWK-Schlüssel von OpenID-Endpunkten abgerufen werden können:

$ lokey fetch jwk example.okta.com
$ lokey fetch jwk login.salesforce.com
$ lokey fetch jwk accounts.google.com

Sie können diese Ausgabe dann erneut an lokey übergeben, um ein PEM zu erhalten:

$ lokey fetch jwk example.okta.com | lokey to pem
2
Joël Franusic

Ich habe eine Swift-Bibliothek geschrieben, die öffentliche/private Schlüssel von JWK in PEM PKCS # 8-Codierung konvertieren kann.

Sie können es verwenden, indem Sie:

import JWKTransform

let key = try RSAKey(jwk: token)
let publicPem = try key.getPublicKey()
let privatePem = try key.getPrivateKey()

In Bezug auf die aktuelle JWK bedeuten die von Ihnen eingegebenen RSA-Felder Folgendes:

  • parameter n: URL-codierte Base64-Zeichenfolge, die das modulus des RSA-Schlüssels darstellt.
  • parameter e: Base64-URL-codierte Zeichenfolge, die den public exponent des RSA-Schlüssels darstellt.
  • parameter d: Base64-URL-codierte Zeichenfolge, die den private exponent des RSA-Schlüssels darstellt.
  • parameter p: Base64-URL-codierte Zeichenfolge, die den secret prime factor des RSA-Schlüssels darstellt.
  • parameter q: Base64-URL-codierte Zeichenfolge, die den secret prime factor des RSA-Schlüssels darstellt.
  • parameter dp: Base64-URL-codierte Zeichenfolge, die den first factor CRT exponent des RSA-Schlüssels darstellt. d mod (p-1)
  • parameter dq: Base64-URL-codierte Zeichenfolge, die den second factor CRT exponent des RSA-Schlüssels darstellt. d mod (q-1)
  • parameter qi: Base64-URL-codierte Zeichenfolge, die den first CRT coefficient des RSA-Schlüssels darstellt. q^-1 mod p

Ich habe neben jedem Parameter das entsprechende Feld in die RSA-Struktur von OpenSSL eingefügt. Dies ist nur für den Fall, dass Sie sich direkt mit OpenSSL befassen möchten :-)

Beachten Sie außerdem Folgendes, wenn Sie die mit der referenzierten Bibliothek erstellten Schlüssel mit OpenSSL-generierten RSA-Schlüsseln vergleichen:

  • public key: Diese Bibliothek sollte den öffentlichen Schlüssel erzeugen, den OpenSSL generiert.

  • private key: Für den privaten RSA-Schlüssel ist nur q erforderlich, aber RSA-Vorgänge sind im Allgemeinen viel schneller, wenn die restlichen oben genannten Werte angegeben werden. Die von OpenSSL generierten privaten RSA-Schlüsseldateien enthalten diese Werte. Wenn daher nicht alle privaten Parameter bereitgestellt werden, stimmt der erzeugte private Schlüssel möglicherweise nicht exakt mit der ursprünglich generierten OpenSSL überein.

0
channel

Online-Tool für die Konvertierung: https://keytool.online/

0
plajko