¿Cómo puedo transformar entre los dos estilos de formato de clave pública? Un formato es:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
el otro formato es:
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
por ejemplo, generé el par id_rsa / id_rsa.pub usando el comando ssh-keygen, calculé la clave pública de id_rsa usando:
openssl rsa -in id_rsa -pubout -out pub2
luego nuevamente calculé la clave pública de id_rsa.pub usando:
ssh-keygen -f id_rsa.pub -e -m pem > pub1
el contenido es pub1 es:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----
y el contenido de pub2 es:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----
Según tengo entendido, pub1 y pub2 contienen la misma información de clave pública, pero tienen un formato diferente, me pregunto cómo puedo transformar entre los dos formatos. ¿Alguien puede mostrarme una introducción concisa sobre los formatos de remolque?
Respuestas:
Usando phpseclib, una implementación pura de PHP RSA ...
Las cosas codificadas en base64 parecen coincidir aunque el encabezado dice BEGIN PUBLIC KEY y no BEGIN RSA PUBLIC KEY. Entonces, tal vez solo use str_replace para solucionarlo y ¡debería estar listo!
fuente
Quería ayudar a explicar lo que está pasando aquí.
Una "clave pública" RSA consta de dos números:
Usando su clave pública RSA como ejemplo, los dos números son:
La pregunta entonces es cómo queremos almacenar estos números en una computadora. Primero convertimos ambos a hexadecimal:
RSA inventó el primer formato
RSA inventó un formato primero:
Eligieron utilizar el tipo DER del estándar de codificación binaria ASN.1 para representar los dos números [1] :
La codificación binaria final en ASN.1 es:
Si luego ejecuta todos esos bytes juntos y lo codifica en Base64, obtiene:
RSA Labs luego dijo agregar un encabezado y un avance:
Cinco guiones y las palabras
BEGIN RSA PUBLIC KEY
. Esa es su clave pública PEM DER ASN.1 PKCS # 1 RSANo solo RSA
Después de eso, aparecieron otras formas de criptografía de clave pública:
Cuando llegó el momento de crear un estándar sobre cómo representar los parámetros de esos algoritmos de cifrado, la gente adoptó muchas de las mismas ideas que RSA definió originalmente:
BEGIN PUBLIC KEY
Pero en lugar de usar:
-----BEGIN RSA PUBLIC KEY-----
-----BEGIN DH PUBLIC KEY-----
-----BEGIN EC PUBLIC KEY-----
En cambio, decidieron incluir el Identificador de objeto (OID) de lo que sigue. En el caso de una clave pública RSA, es decir:
1.2.840.113549.1.1.1
Entonces, para la clave pública RSA fue esencialmente:
Ahora crearon SubjectPublicKeyInfo que es básicamente:
En la definición actual de DER ASN.1 es:
Eso le da un ASN.1 de:
La codificación binaria final en ASN.1 es:
Y como antes, tomas todos esos bytes, los codifica en Base64, terminas con tu segundo ejemplo:
Agregue el encabezado y el avance ligeramente diferentes, y obtendrá:
Y esta es su clave pública X.509 SubjectPublicKeyInfo / OpenSSL PEM [2] .
Hazlo bien o piratea
Ahora que sabe que la codificación no es mágica, puede escribir todas las piezas necesarias para analizar el módulo y el exponente RSA. O puede reconocer que los primeros 24 bytes simplemente se agregan cosas nuevas sobre el estándar PKCS # 1 original
Esos primeros 24 bytes son cosas "nuevas" agregadas:
Y debido a una extraordinaria coincidencia de fortuna y buena suerte:
Porque en Base64: 3 bytes se convierten en cuatro caracteres:
Eso significa que si toma su segunda clave pública X.509, los primeros 32 caracteres corresponden solo a las cosas recién agregadas:
Si elimina los primeros 32 caracteres y los cambia a BEGIN RSA PUBLIC KEY :
Tienes exactamente lo que querías: el
RSA PUBLIC KEY
formato anterior .fuente
Encontré que este sitio web es una buena explicación técnica de los diferentes formatos: https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem
"BEGIN RSA PUBLIC KEY" es PKCS # 1, que solo puede contener claves RSA.
"BEGIN PUBLIC KEY" es PKCS # 8, que puede contener una variedad de formatos.
Si solo desea convertirlos con la línea de comandos, "openssl rsa" es bueno para esto.
Para convertir de PKCS # 8 a PKCS # 1:
Para convertir de PKCS # 1 a PKCS # 8:
fuente
unknown option -RSAPublicKey_in
Si bien los comentarios anteriores sobre encabezados de 32 bytes, formatos OID y demás son interesantes, personalmente no veo el mismo comportamiento, suponiendo que entiendo el punto. Pensé que podría ser útil explorar esto más a fondo en lo que la mayoría podría pensar que es un detalle excesivo. Nada supera como exceso.
Para comenzar, creé una clave privada RSA y la verifiqué:
(¡Oh, horrores! He expuesto una clave privada. Meh ...)
Extraigo y muestro su clave pública:
Sucede que hay otro parámetro de salida de clave pública (como se menciona en un comentario anterior). Extraigo y muestro la clave pública usando esa palabra clave en su lugar:
Bien bien. Estos dos valores de clave pública no son los mismos, aunque se derivan de la misma clave privada. ¿O son lo mismo? Corto y pego las dos cadenas de claves públicas en sus propios archivos, y luego hago una verificación de módulo en cada una:
El 'pubin' le dice a rsa que esto realmente se supone que es una clave pública, y no se queje de que no es una clave privada.
Ahora tomamos la clave pública RSA, mostramos el módulo y lo transformamos en una 'clave pública' simple y antigua (nuevamente, tenemos que decirle que la entrada es una clave pública):
Se muestra el mismo módulo y el mismo valor de 'clave pública'. Para hacer las cosas más interesantes (para mí, de todos modos), cuando agregamos la palabra clave RSAPublicKey_out obtenemos:
... y cuando transformamos la vieja 'clave pública' en una clave pública RSA:
... marchando implacablemente, y aunque acabamos de hacer esto hace unos comandos, para aclarar el punto, cambiamos las cosas para que la transfiguración sea de RSA a una simple 'clave pública':
... lo que nos lleva de vuelta a donde empezamos. ¿Qué hemos aprendido?
Resumen: las claves internamente son las mismas, solo que se ven diferentes. Un comentario anterior señaló que el formato de la clave RSA se definió en PKCS # 1, y el formato antiguo simple de 'clave pública' se definió en PKCS # 8. Sin embargo, editar un formulario no lo convierte en el otro. Ojalá haya superado esta distinción hasta la muerte.
Sin embargo, en caso de que todavía quede una chispa de vida, analicemos esto un poco más y hagamos referencia al certificado que se generó originalmente con la clave privada RSA hace tanto tiempo, examinando su clave pública y su módulo:
... y todos vivieron felices para siempre: el certificado tiene el mismo valor de módulo que la clave pública RSA, la clave privada RSA y la vieja 'clave pública'. El certificado contiene el mismo valor simple de 'clave pública' que vimos anteriormente, aunque estaba firmado con un archivo marcado como clave privada RSA. Es seguro decir que hay consenso.
No hay una palabra clave equivalente 'RSAPublicKey_out' en el cuadrante X509 de la galaxia OpenSSL, por lo que no podemos intentarlo, aunque el valor del módulo se describe como el "módulo clave RSA", que supongo que es lo más cercano que obtendremos.
No sé cómo se vería todo esto con un certificado firmado por DSA.
Me doy cuenta de que esto no responde a la pregunta original, pero quizás proporcione algunos antecedentes útiles. Si no, mis disculpas. Por lo menos, cosas que no se deben hacer y suposiciones que no se deben hacer.
Sin duda uno ha notado la repetición un poco irritante de "escribir clave RSA", cuando no está haciendo tal cosa. Supongo que lo que se quiere decir es que el módulo rsa reconoce la vieja clave pública simple como una verdadera clave RSA, y es por eso que sigue insistiendo en la "clave RSA" (además, es el módulo rsa, después de todo). Si mal no recuerdo, la estructura genérica EVP_PKEY tiene una unión para todos los tipos de clave, y cada tipo de clave tiene su propio conjunto especial de valores (las amablemente llamadas g, w, q y otras consonantes).
En conclusión, observo que hubo una queja sobre programación y desarrollo; ahora, cada comando de OpenSSL obviamente tiene el código correspondiente, y si uno desea explorar todas las maravillas que es la programación de OpenSSL en la actualidad, la línea de comandos parece un lugar razonable para comenzar. En este caso particular (ya que estoy usando un cygwin reciente en este momento) uno podría comenzar revisando \ openssl-1.0.2f \ apps \ rsa.cy (dado que uno tiene una alta tolerancia para macros) \ openssl-1.0. 2f \ crypto \ pem \ pem_all.c
fuente
La única diferencia entre su pub1 y pub2, además del encabezado / pie de página, es esta cadena adicional en pub2:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
. Si elimina eso, la Base 64 es idéntica a la de pub1.La cadena adicional corresponde al identificador del algoritmo de acuerdo con esta Respuesta .
fuente