Si cambio cualquier carácter en un PEM privado, ¿debería ser diferente el PEM público?

2

Estoy generando una clave pública en formato PEM a partir de una clave privada en formato PEM. Noté que si cambio algunos caracteres cerca del final del PEM privado, el PEM público generado a partir del PEM privado modificado es exactamente el mismo que el resultado del PEM privado no modificado.

Por ejemplo, este PEM privado

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCAAZXj8YAEQya8jF8l6Hy56BcRBgplxPd8ZM5LIAWm0w1k/CgB
gvrI28W+5orOyqST2gC4EBEGmLw9s3NC8McL3qqFIQvd6SpWzCJEiI9n+wCkJLYf
715t6BwZo8F82AdqRHwL1lL0T4JeakgcFO5zno2l/NYKpZtS78vIq2F8pwIDAQAB
AoGAIAdFh+lPTMG4mYjN7eBEBQgrbVkDlP85pWhbrbRvdZRtT41APVCWi1diHSf2
J1PQ5iWv9F4gxHPG9fFGr8MrKk+jCM0/rDJsN7yC1yiSerS9zNvoSWu4D1cizRn2
ZOFi+TJZVHAoVvuh1vJdsFLkDmfoXelR6v6ojQxp6IftblECQQD7W4F92yHVIkRt
ZEz5TMYxtFF2d5uwi6XA/1MDuWpK0dK20a7DUGmgQ8faNfSZ/Dr1JmLx0OK/+Ocg
5HnzNo5NAkEAgl7Wa/Lr0TUH5h4L3SsJ1aeYUC6CbzJHBpNTvhuC7YEcs0AJL2k3
qYSM8VpU7q9iGHvfQhnKH9eBXlQbJBt4wwJBAJ1Pj6Ns2afCYoD0HRiJbCD/cVxr
Tw0W2Q4IvbO+/z8EQpQYdv/V+8VJpnJzAjq9GUkEVThyOvdal4yGcaw9oKECQC8V
/a+jXxSCaMXuGC7bOoQWMebTxXxP1mNDlr1UxmbteOYsvKSJBfeNzjHlhENoyK87
HhmLovr5JNpi2iKiYW0CQDyniRLXCyBVayJd3QkuMFKVNUuOytXUFWNXTpLA1Nbb
2K+leKb2KSyyEmRFC2X+QwF9ZBP1C3b0lgBBlBVbpWQ=
-----END RSA PRIVATE KEY-----

y este PEM privado

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCAAZXj8YAEQya8jF8l6Hy56BcRBgplxPd8ZM5LIAWm0w1k/CgB
gvrI28W+5orOyqST2gC4EBEGmLw9s3NC8McL3qqFIQvd6SpWzCJEiI9n+wCkJLYf
715t6BwZo8F82AdqRHwL1lL0T4JeakgcFO5zno2l/NYKpZtS78vIq2F8pwIDAQAB
AoGAIAdFh+lPTMG4mYjN7eBEBQgrbVkDlP85pWhbrbRvdZRtT41APVCWi1diHSf2
J1PQ5iWv9F4gxHPG9fFGr8MrKk+jCM0/rDJsN7yC1yiSerS9zNvoSWu4D1cizRn2
ZOFi+TJZVHAoVvuh1vJdsFLkDmfoXelR6v6ojQxp6IftblECQQD7W4F92yHVIkRt
ZEz5TMYxtFF2d5uwi6XA/1MDuWpK0dK20a7DUGmgQ8faNfSZ/Dr1JmLx0OK/+Ocg
5HnzNo5NAkEAgl7Wa/Lr0TUH5h4L3SsJ1aeYUC6CbzJHBpNTvhuC7YEcs0AJL2k3
qYSM8VpU7q9iGHvfQhnKH9eBXlQbJBt4wwJBAJ1Pj6Ns2afCYoD0HRiJbCD/cVxr
Tw0W2Q4IvbO+/z8EQpQYdv/V+8VJpnJzAjq9GUkEVThyOvdal4yGcaw9oKECQC8V
/a+jXxSCaMXuGC7bOoQWMebTxXxP1mNDlr1UxmbteOYsvKSJBfeNzjHlhENoyK87
HhmLovr5JNpi2iKiYW0CQDyniRLXCyBVayJd3QkuMFKVNUuOytXUFWNXTpLA1Nbb
2K+leKb2KSyyEmRFC2X+QwF9ZBP1C3b0lgBBlBVbpWdddddddddddddddddddddddddQ=
-----END RSA PRIVATE KEY-----

ambos dan como resultado que se genere el mismo PEM público:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAAZXj8YAEQya8jF8l6Hy56BcR
BgplxPd8ZM5LIAWm0w1k/CgBgvrI28W+5orOyqST2gC4EBEGmLw9s3NC8McL3qqF
IQvd6SpWzCJEiI9n+wCkJLYf715t6BwZo8F82AdqRHwL1lL0T4JeakgcFO5zno2l
/NYKpZtS78vIq2F8pwIDAQAB
-----END PUBLIC KEY-----

Pensé que cambiar un carácter del PEM privado daría lugar a un PEM público completamente nuevo. ¿Me estoy perdiendo algo, o algunos caracteres pueden modificarse de hecho sin afectar el resultado PEM público?

La biblioteca de JavaScript que estoy usando para generar el PEM público a partir de un PEM privado es rzcoder's node-rsa , que utiliza la biblioteca criptográfica jsbn de Tom Wu's .

    
pregunta trusktr 22.04.2014 - 10:03
fuente

2 respuestas

3

El formato PEM es un remanente de un estándar antiguo y olvidado llamado Correo con privacidad mejorada (nunca fue ampliamente adoptado, pero sirvió como inspiración para protocolos ulteriores, en particular S / MIME y PGP). Una clave RSA privada en PEM es realmente la codificación Base64 de la DER que codifica una estructura ASN.1 que parece esto:

RSAPrivateKey ::= SEQUENCE {
    version           Version,
    modulus           INTEGER,  -- n
    publicExponent    INTEGER,  -- e
    privateExponent   INTEGER,  -- d
    prime1            INTEGER,  -- p
    prime2            INTEGER,  -- q
    exponent1         INTEGER,  -- d mod (p-1)
    exponent2         INTEGER,  -- d mod (q-1)
    coefficient       INTEGER,  -- (inverse of q) mod p
    otherPrimeInfos   OtherPrimeInfos OPTIONAL
}

(Esto se toma directamente de PKCS # 1 , el estándar RSA más utilizado.)

Lo que se debe tener en cuenta aquí es que una clave RSA privada consiste en numerosos campos, y entre ellos el módulo y el exponente público. Esto significa que la clave pública simplemente puede ser "extraída" de la clave privada.

Con tus caracteres adicionales, hiciste dos cosas:

  1. Has "dañado" el valor coefficient . Este es el inverso de q módulo p , donde p y q son los factores primos del módulo. Se utiliza para operaciones de clave privada, específicamente las que se implementan con el CRT (un truco ingenioso que cuadruplica la velocidad de privado) operaciones clave).

  2. Agregaste "basura" después de la estructura ASN.1. La codificación DER tiene cabeceras de longitud explícita, por lo que el decodificador sabe muy bien dónde se detiene la estructura principal.

En su caso, el decodificador PEM / DER que utiliza parece simplemente ignorar la basura final (algunas otras bibliotecas rechazarán la clave con un error; por ejemplo, eso es lo que OpenSSL hace). Dado que la extracción de la clave pública no usa el coefficient , se obtiene la misma clave pública que con la clave privada no dañada. Sin embargo, si intenta usar su clave privada modificada, es probable que no obtenga los resultados adecuados (dependiendo de si su implementación usa el CRT o no).

    
respondido por el Thomas Pornin 22.04.2014 - 14:44
fuente
1

A veces, depende de lo que cambies. Un archivo de clave privada normal RSA es una estructura de datos ASN.1 de DER codificada en PEM que contiene un número de versión , más ocho componentes clave numéricos, en orden:

  1. versión (0)
  2. el módulo, n
  3. exponente público, e
  4. el exponente privado, d
  5. el par original de primos utilizados para generar la clave, p y q
  6. tres valores adicionales utilizados en los CRT cálculos, e1 , e2 , q

Solo el primer par de números ( n y e ) terminan en la clave pública, siempre que permanezcan sin cambios, la salida será la misma. (No está utilizando un certificado X.509 firmado aquí, si tuviera otros detalles, como el número de serie, los rangos de fechas y más, también deben ser los mismos para que esto sea válido para el certificado).

Al modificar la estructura de uno de los cinco valores relacionados con CRT, esto generará errores o resultados incorrectos cuando cualquier cosa intente usarlos para descifrarlos, lo que es casi seguro que todas las bibliotecas estándar tienen en cuenta en la mejora del rendimiento. (Sin embargo, esos números son solo para optimización, mientras que los números lo suficientemente intactos para recuperar los números primos, el descifrado es posible).

También tenga en cuenta que el formato ASN.1 DER utiliza longitudes "contadas", el tipo y la longitud de los datos aparecen en un encabezado corto que precede a cada valor, gran parte de su contenido adicional aparecerá como basura final y se puede ignorar. También debe observar la estructura de relleno base64 (que usted no es, por lo que su decodificador debería ser quejándose de una entrada no válida con los datos clave modificados).

Puede inspeccionar la estructura ASN.1 de las claves convirtiéndolas a DER binario (es decir, base64-decodificando la carga útil) y luego utilizando dumpasn1 .

openssl rsa -in prv.pem -outform DER -out prv.der
dumpasn1 -tilda prv.der 
openssl rsa -pubin -in pub.pem -outform DER -out pub.der
dumpasn1 -tilda pub.der 

openssl x509 solo tratará con certificados confiables o firmados y no convertirá esta clave pública, openssl rsa -pubin procesa claves públicas sin firmar. Puedes hacer algo similar a lo anterior con openssl asn1parse , pero no es tan informativo o fácil de usar para esto.

    
respondido por el mr.spuratic 22.04.2014 - 14:59
fuente

Lea otras preguntas en las etiquetas