
Generé una clave privada usando libressl 3.0 usando curve secp521r1
.
openssl genpkey -aes128 -algorithm EC -pkeyopt ec_paramgen_curve:secp521r1 -pkeyopt ec_param_enc:named_curve
Hasta donde yo sé, esta curva es la misma que usa ssh-keygen con ssh-keygen -t ecdsa -b 521
y según la documentación. Sé que ssh-keygen ahora usa aes128 para cifrar la clave privada.
El tamaño de la clave privada libressl es 534
y el tamaño de la clave ssh-keygen es 736
.
Mi pregunta es: ¿qué hace ssh-keygen adicional que incrementa el tamaño de la clave?
Además: ¿ambos son intercambiables? ¿Se puede convertir una clave privada generada en uno en el otro?
Respuesta1
TLDR: hay muchos formatos diferentes para archivos de clave privada
Y depende en parte de la versión de OpenSSH, que no proporcionaste.
Históricamente, a excepción de la versión 1 del protocolo obsoleto (y el tipo de clave 'rsa1'), OpenSSH usaba (la parte libcrypto de) OpenSSL para realizar la mayoría de sus operaciones criptográficas, incluido el almacenamiento de claves privadas (o, de hecho, pares de claves) en archivos, usando elFormatos 'tradicionales' o 'heredados' definidos por SSLeay/OpenSSL. OpenSSL también admite formatos PKCS8 'nuevos' (¡desde aproximadamente 1998!), que son (algo) más seguros. Por lo tanto, OpenSSL admite 4 formatos PEM para "ECDSA" (más exactamente Weierstrass EC de estilo X9 que cubre tanto X9.62 ECDSA como X9.63 ECDH), de los cuales OpenSSHgenerasólo 2 pero (usando libcrypto) puedo leer todos. cuando ssh-keygen
cifraFormato OpenSSLarchivos, las versiones recientes utilizan AES-128-CBC, pero esto no siempre ha sido cierto.
A partir de la versión 6.5 en 2014-01,OpenSSH agregó su propio formato de archivo 'nuevo', en parte para proporcionar una mejor seguridad que los formatos heredados de OpenSSL (cuando están cifrados) y en parte para admitir el entonces nuevo algoritmo Ed25519, que OpenSSL no admitía en absoluto. ssh-keygen
tenía una opción -o
para solicitar un nuevo formato para cualquier tipo de clave que no sea ed25519 (o rsa1), y encontrará muchas preguntas y respuestas de Stack de los últimos años que hacen referencia y generalmente recomiendan esta opción. Los archivos de formato 'nuevo' están cifrados con AES256-CBC de forma predeterminada, que se puede anular con -Z ciphername
, pero aparentemente la página de manual no se ha actualizado para ninguno de estos. A partir de la versión 7.8 en 2018-08, OpenSSH ahora tiene de forma predeterminada el formato "nuevo" para todos los tipos de claves, aunque puede usarlo -m pem
para solicitar el formato OpenSSL para cualquier formato que no sea ed25519. Si verifica man ssh-keygen
su sistema (a menos que sea Windows), debería describir uno de estos casos, probablemente el último.
(También existe el formato PKCS12, también conocido como PFX, que OpenSSLpoderse usa para una clave privada, pero normalmente se usa solo para combinar una clave privada (o varias) con uno o más certificados X.509 para esa(s) clave(s), lo cual es una situación diferente y no aplicable a SSH, que nunca utiliza certificados X.509. Otros programas o sistemas utilizan otros formatos: 'comercial'/Tectia SSH tiene su propio formato, y PuTTY tiene su propio formato PPK = PuTTY Private Key. Etcétera, etcétera, Yul Brynner. Todos estos son semánticamente equivalentes y, con las herramientas adecuadas, se pueden interconvertir).
Todos los formatos de clave privada utilizados por OpenSSH sonestilo PEM; los datos binarios se codifican en texto como base64 con líneas de encabezado y final en el formulario
-----BEGIN (something)-----
(sometimes some headers here)
(data encoded in base64, broken into lines of 64 characters)
-----END (something)-----
para que pueda saber qué formato tiene con solo mirar la línea de guiones y COMIENZO. Ver casi duplicaciones cruzadashttps://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keyso más brevementehttps://security.stackexchange.com/questions/129724/how-to-check-if-an-ssh-private-key-has-passphrase-or-notyhttps://security.stackexchange.com/questions/200935/how-do-i-determine-if-an-existing-ssh-private-key-is-secure(mío).
Las diferencias:el tamaño de 736 caracteres para una clave ecdsa-p521 coincide con el nuevo formato OpenSSHsin cifrar-- eresseguro¿Le diste una contraseña? -- y 534 coincide con el formato cifrado PKCS8 creado por OpenSSL 1.0.2, que es IIRC cuando LibreSSL se bifurcó. (OpenSSL 1.1.0 cambia el cifrado PKCS8 para usar HMAC-SHA256 en PBKDF2, lo que hace que el archivo sea un poco más grande. OpenSSL 1.1.0 también hace que param_enc=named sea el valor predeterminado, por lo que ya no es necesario especificarlo). El nuevo OpenSSH El formato es más grande que el formato PKCS8-enc principalmente porque, sin ninguna razón obvia, almacena el valor de la clave pública (para ECDSA, un punto de curva en formato X9.62).dos veces-- una vez en la sección del archivo especificada para la clave pública, yde nuevoen la sección especificada para clave privada. Además, el formato OpenSSH tiene la mayoría de sus metadatos como cadenas de texto y todos los campos de longitud son de 4 bytes, mientras que PKCS8 (al igual que los formatos heredados de OpenSSL) usa ASN.1 con campos de longitud variable en su mayoría de solo 1 byte, y metadatos en su mayoría binarios, especialmente 'OID' para los algoritmos utilizados).
Además: ¿ambos son intercambiables? ¿Se puede convertir una clave privada generada en uno en el otro?
Si y no. Como se señaló, OpenSSH que usa OpenSSL puede leer (pero no escribir) PKCS8, por lo que ssh-keygen
puede convertirlo a OpenSSH-nuevo realizando un cambio nulo, es decir, 'cambiando' la contraseña al valor existente; de 6.5 a 7.7 debes especificar -o
y de 7.8 en adelante es el predeterminado. En el otro sentido, ssh-keygen
puede convertir a OpenSSL-legacy, pero no directamente a PKCS8, debe usar openssl
para hacerlo, ya sea explícitamente con pkcs8 -topk8
o en 1.0.0 en adelante (que a estas alturas debería ser para todos, y definitivamente todo LibreSSL) solo pkey
. (El primero está predeterminado como cifrado y el segundo como no cifrado, pero ambos se pueden anular).