Seguridad

Claves SSH ed25519: cómo generarlas bien (y migrar desde RSA)

Si todavía usas claves RSA de 2048 bits o, peor, dejás el login con password habilitado, esta guía es para ti. ed25519 es más corta, más rápida y criptográficamente más resistente. Te explico cómo generarla, instalarla en el servidor, deshabilitar password y migrar desde RSA sin perder acceso a tu propio server.


TL;DR — Lo que vas a tener al final

  • Tiempo de setup: 1-2 horas para un server nuevo.
  • Requisitos: Acceso root, 2 sesiones SSH abiertas durante cambios.
  • Resultado: Login por clave ed25519, fail2ban activo, 99% de ataques bloqueados.
  • Troubleshooting: Consola del proveedor, journalctl -u sshd, fail2ban-client status.

Índice

  1. [Por qué ed25519 y no RSA](#por-qué-ed25519-y-no-rsa)
  2. [Generar la clave ed25519 con passphrase](#generar-la-clave-ed25519-con-passphrase)
  3. [Instalar la clave pública en el servidor](#instalar-la-clave-pública-en-el-servidor)
  4. [Deshabilitar el login con password](#deshabilitar-el-login-con-password)
  5. [Migrar desde RSA sin perder acceso](#migrar-desde-rsa-sin-perder-acceso)
  6. [Troubleshooting común](#troubleshooting-común)
  7. [Conclusión](#conclusión)

Por qué ed25519 y no RSA

Antes de meter mano en la consola, vale la pena entender por qué ed25519 es el estándar actual y por qué RSA quedó en el camino.

ed25519 es un algoritmo de firma digital basado en curvas elípticas (Curve25519) que salió en 2011 y se estandarizó en 2017. Tiene tres ventajas concretas sobre RSA:

  • Claves más cortas: 256 bits en ed25519 dan la misma seguridad que ~3072 bits en RSA. La clave pública entera (la línea que va en authorized_keys) cabe en 68 caracteres. Una RSA-3072 ocupa ~544 caracteres.
  • Verificación más rápida: ~10x más rápida que RSA-2048. En conexiones masivas (CI/CD, ansible contra 200 servidores, rsync sobre ssh con muchas operaciones) se nota.
  • Resistente a ataques de timing: la implementación de referencia es constant-time por diseño. RSA depende de que la implementación sea constant-time; muchas libs (OpenSSL incluida históricamente) tuvieron side-channel attacks por esto.

¿Por qué migrar si RSA-2048 todavía funciona? Tres razones:

  1. La NSA (CNSA 2.0, publicado en 2022) recomienda no usar RSA-2048 para nuevos deployments que necesiten protección más allá de 2030; recomiendan migrar a RSA-3072 mínimo o, mejor, a ed25519.
  2. Las versiones modernas de OpenSSH (8.5+, 2021) tienen ed25519 como default para nuevas claves de host. Si tu server es nuevo, la clave de host ya es ed25519.
  3. ed25519 es determinística: la firma de un mensaje es siempre la misma para una clave dada. RSA usa padding randomizado que, mal implementado, es atacable (Bleichenbacher’s attack, padding oracle). ed25519 no tiene ese vector.

La única razón legítima para quedarse con RSA es compatibilidad con hardware viejo que no soporta ed25519: switches administrables viejos, routers Cisco pre-2018, NAS Synology con DSM < 6, algunas versiones de OpenWrt pre-18. Para servers modernos (cualquier Linux con OpenSSH 6.5+, o sea 2014 en adelante), ed25519 funciona sin problemas.

revisa qué versión de OpenSSH tienes instalada antes de empezar — esto importa porque el formato de la clave privada cambió entre versiones y, si guardas la clave en un lugar que después se conecta con una versión vieja, puedes tener problemas al deployar:

ssh -V
# OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13

OpenSSH_9.6p1 es la versión del cliente. Cualquier cosa >= 6.5 (2014) soporta ed25519. Si ves una versión más vieja que 7.8 (2018), el formato de la clave privada puede ser el viejo PEM en lugar del nuevo OpenSSH — eso no es problema para ed25519, pero sí para claves generadas con versiones nuevas y leídas por versiones viejas.

Si ssh -V no devuelve nada o da error de “command not found”: probablemente estás en un sistema donde OpenSSH no está en el PATH (raro, pero pasa en containers minimalistas con busybox). Instalalo con apt install openssh-client (Debian/Ubuntu), dnf install openssh-clients (RHEL/Fedora), o apk add openssh-client (Alpine).


Generar la clave ed25519 con passphrase

Ahora sí, vamos a generar la clave. Hay tres decisiones importantes: passphrase, formato y comentario.

La passphrase es innegociable. Si alguien roba tu clave privada (te roban la laptop, hacés commit del ~/.ssh/id_ed25519 por error a un repo público, te clonan el backup), sin passphrase el atacante entra a todos tus servers sin más. Con passphrase, además del archivo necesita el password. usa una passphrase larga (no corta y compleja; larga y memorable es mejor — la frase completa de una canción, una cita, una línea de un libro que te sepas de memoria).

ssh-keygen en OpenSSH moderno (8.5+) tiene ed25519 como uno de los tipos soportados, pero el default histórico sigue siendo RSA para user keys. Conviene siempre pasar -t ed25519 explícito. (El cambio de OpenSSH 7.8 no fue del tipo por defecto sino del formato de clave privada — PEM vs nuevo OpenSSH). Las flags que importan:

  • -t ed25519: tipo de clave.
  • -a 100: rounds de KDF (Key Derivation Function) sobre tu passphrase. 100 es razonable; valores más altos (200, 500) hacen más lento el brute force si te roban la clave, pero también más lento el login. Si tu máquina es lenta (laptop vieja, Raspberry Pi), 100 está bien; si tienes un workstation potente, puedes subirlo.
  • -C: comentario, idealmente tu email o algo que identifique la clave. Aparece en authorized_keys y te ayuda a identificar claves viejas que ya no usas.
ssh-keygen -t ed25519 -a 100 -C "[email protected]"
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/tu_usuario/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):
# Enter same passphrase again:

Cuando te pregunta Enter file in which to save the key, acepta el default con Enter salvo que tengas una razón específica (por ejemplo, tienes varias claves para distintos servidores y quieres nombres descriptivos como id_ed25519_trabajo o id_ed25519_personal). El default es el que ssh, ssh-add, ssh-agent y ssh-copy-id buscan automáticamente. Si le ponés otro nombre, tienes que pasar -i /ruta/a/la/clave cada vez que uses ssh.

Sobre passphrase vacía: si presionás Enter sin escribir nada, ssh-keygen imprime un warning pero no pide confirmación doble. La clave queda sin protección. No lo hagas en producción. La única excepción legítima es para claves de service accounts automatizados (deploys de CI/CD, ansible contra flota de servidores) donde no hay humano para tipear passphrase — en esos casos, protegé la clave con permisos del filesystem (chmod 600), mantené el archivo fuera de backups públicos, y considera usar un vault de secretos.

verifica que la clave se generó bien y revisa los permisos. Esto es crítico: ssh rechaza claves con permisos abiertos (>0600) por seguridad — si los permisos están mal, ssh-agent no carga la clave y todo falla de formas raras:

ls -la ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
# -rw------- 1 tu_usuario tu_usuario  411 ago 12 10:23 /home/tu_usuario/.ssh/id_ed25519
# -rw-r--r-- 1 tu_usuario tu_usuario   96 ago 12 10:23 /home/tu_usuario/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

chmod 600 en la privada es obligatorio. Sin esto, ssh se queja con Permissions 0644 for '/home/tu/.ssh/id_ed25519' are too open. En algunas distros (Ubuntu 22.04+) el directorio ~/.ssh se crea con permisos 0700, pero si venís de un sistema viejo o copiaste la clave desde un backup, puede venir con 0755 o 0775 — eso también rompe. Si te pasa, chmod 700 ~/.ssh lo arregla.

Si perdés la passphrase, la clave es irrecuperable. No hay forma de recuperarla, no hay master password, no hay nada. Esto es una feature (si te roban la laptop no pueden extraer la passphrase) pero también una responsabilidad: guardá un backup encriptado de la clave en un lugar seguro (paper wallet, USB encriptado con LUKS, 1Password, Bitwarden). Una passphrase que no recordás es equivalente a no tener clave.


Instalar la clave pública en el servidor

Ahora hay que llevar la clave pública al servidor. Hay tres métodos, en orden de preferencia:

Método 1: ssh-copy-id — el más fácil. Se conecta al server con tu método actual (password o clave RSA existente), crea el directorio ~/.ssh si no existe, le pone permisos correctos, y agrega la clave pública a authorized_keys. Es idempotente: si la clave ya está, no la duplica.

ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
# /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
# /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
# [email protected]'s password:
# Number of key(s) added: 1

Si ssh-copy-id no está disponible (sistemas minimalistas, algunos containers Alpine): copiá manualmente. ssh-copy-id no es más que una envoltura alrededor de este comando:

cat ~/.ssh/id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && cat >> ~/.ssh/authorized_keys"

Antes de cerrar la sesión actual y perder acceso, verifica que la nueva clave funciona abriendo otra terminal o sesión SSH separada. Esto es el paso más crítico de toda la guía — si te lo saltás y después deshabilitas el password, te quedás afuera:

ssh -i ~/.ssh/id_ed25519 [email protected]
# Si todo va bien, entrás directamente. Si te vuelve a pedir password, la clave no se instaló bien.

Cuando abras la nueva sesión, ssh te puede preguntar si confiás en la host key del server (fingerprint). Si la viste antes en conexiones previas, no debería preguntar; si es la primera vez o cambió el fingerprint (reinstalación del server), te muestra el fingerprint y te pide confirmación. Comparalo con el fingerprint del server si tienes forma de verificarlo (consola KVM, IPMI, panel del proveedor). Nunca aceptes un fingerprint sin verificarlo en servidores críticos — un atacante MITM puede estar mostrando su propia fingerprint.

Si la nueva sesión sigue pidiendo password, hay tres causas comunes en orden de frecuencia:

  1. Permisos mal en ~/.ssh o ~/.ssh/authorized_keys en el servidor. El servidor rechaza la clave si los permisos son demasiado abiertos. Solución: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys en el server.
  2. PubkeyAuthentication no en /etc/ssh/sshd_config del server. Por defecto está en yes, pero algunas imágenes hardened (CIS benchmarks, distros “secure by default”) lo cambian.
  3. SELinux/AppArmor bloqueando el acceso al home. En RHEL con SELinux, si tu home está en una ruta no estándar (NFS, /opt, montado con contexto distinto), SELinux puede bloquear la lectura de authorized_keys. sudo ausearch -m avc --start recent muestra los denies.

Deshabilitar el login con password

Una vez confirmada la clave ed25519 funcionando en una sesión separada, es el momento de deshabilitar password. Esto es lo que cierra la puerta a los bots de fuerza bruta. Si te lo saltás o lo hacés antes de confirmar la clave, te quedás afuera.

El cambio va en /etc/ssh/sshd_config del servidor. Tres directivas que importan:

  • PasswordAuthentication no: rechaza login con password en cualquier usuario.
  • PermitRootLogin prohibit-password: root solo puede entrar con clave (no password). Si quieres deshabilitar root totalmente, no. Si quieres permitir solo clave, prohibit-password.
  • PubkeyAuthentication yes: explícito, aunque es el default.
sudo nano /etc/ssh/sshd_config

Cambiá las líneas (si tienen un # adelante, descomentalas; si no existen, agregalas):

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
UsePAM yes

No reinicies sshd todavía. Primero validá la config con sshd -t — esto es como un dry-run, parsea la config y te dice si hay errores de sintaxis. Si reinicias con una config rota, puedes perder acceso (sshd no arranca y todas las conexiones nuevas se rechazan; las existentes siguen hasta que se cierren):

sudo sshd -t && echo "Config OK"

Si sshd -t devuelve errores, NO reinicies. Los errores más comunes: typos en directivas, mezclas de Match blocks que se contradicen, o líneas con espacios al final.

Ahora sí, recargá sshd sin matar la sesión actual. systemctl reload envía SIGHUP al proceso sshd, que relee la config sin cortar conexiones existentes. Si usas systemctl restart, sí corta las conexiones — peligroso si algo falla:

sudo systemctl reload sshd
# o en algunas distros:
sudo systemctl reload ssh

Después de recargar, abrí una tercera sesión SSH con la clave ed25519 para verificar que sigues entrando. No cierres las dos sesiones anteriores hasta confirmar. Si la nueva sesión entra, todo está bien. Si falla, puedes volver a una de las sesiones abiertas, revertir el cambio (sudo nano /etc/ssh/sshd_config, poner PasswordAuthentication yes), y sudo systemctl reload sshd otra vez.

Verificación final de que el password está deshabilitado, abriendo otra sesión e intentando con password explícitamente:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no [email protected]
# Permission denied (publickey).

Si ves Permission denied (publickey), perfecto: el server ni siquiera intentó el password, te rechazó antes. Si te pregunta password, el cambio no se aplicó — revisa que la línea PasswordAuthentication no esté efectivamente sin # al frente y que hayas hecho reload.


Migrar desde RSA sin perder acceso

Si ya tienes una clave RSA funcionando y quieres migrar a ed25519 sin perder acceso a servers donde todavía está tu clave RSA, el proceso es progresivo:

Paso 1: generar la ed25519 (ya cubierto en la sección 2). La RSA sigue intacta.

Paso 2: instalar la ed25519 en los servers además de la RSA. Ambos métodos quedan habilitados durante la transición. Tu ~/.ssh/authorized_keys en cada server va a tener dos líneas: la RSA y la ed25519.

ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]

Ahora entrás con cualquiera de las dos. verifica en una sesión nueva que la ed25519 funciona:

ssh -v -i ~/.ssh/id_ed25519 [email protected] 2>&1 | grep "Offering"
# debug1: Offering public key: ... ED25519 ...
# debug1: Offering public key: ... RSA ...

-v muestra el método de auth ofrecido. Si ves la línea ED25519, la está ofreciendo. Si entra sin pedirte nada (o pidiendo solo la passphrase de la ed25519), todo bien.

Paso 3: una vez confirmado que ed25519 funciona en todos los servers, deshabilitá la RSA en tu cliente. Esto le dice a ssh “no ofrezcas la RSA, solo ed25519”. El archivo es ~/.ssh/config:

nano ~/.ssh/config

Agregá un bloque Host con IdentitiesOnly yes y IdentityFile apuntando a la ed25519:

Host *
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519
    AddKeysToAgent yes

IdentitiesOnly yes es la clave: sin esto, ssh ofrece TODAS las claves que encuentre en ~/.ssh/id_*, .ssh/id_ed25519, etc., y muchas veces eso confunde al server (rechaza después de muchos intentos, o acepta una que no querías). Con IdentitiesOnly, solo ofrece la que tú listás.

Paso 4: después de unos meses de uso estable, puedes borrar la RSA vieja del server. En cada server, editá ~/.ssh/authorized_keys y borrá la línea que empieza con ssh-rsa. La ed25519 empieza con ssh-ed25519. No borres la RSA de tu cliente todavía — mantené el backup por si algún server viejo todavía la necesita.

Para borrar la RSA del cliente una vez que confirmaste que ningún server la usa más:

shred -vfz -n 5 ~/.ssh/id_rsa ~/.ssh/id_rsa.pub
# shred: ... removed
rm -f ~/.ssh/id_rsa ~/.ssh/id_rsa.pub

shred sobrescribe el archivo con datos aleatorios 5 veces antes de borrarlo. Esto es porque borrar el archivo no borra los datos del disco — rm solo deslinka el inode; los bloques siguen en disco hasta que se sobrescriban. shred evita que alguien con acceso al disco (forense, backup, snapshot de VM) pueda recuperar la clave privada RSA. -z agrega una pasada final de ceros para que el filesystem no marque los bloques como “stale”.


Troubleshooting común

“sign_and_send_pubkey: signing failed: agent refused operation”

ssh-agent tiene la passphrase cacheada pero por alguna razón no la aplica. Solución: matá el agente y reinicialo:

eval $(ssh-agent -k)
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

“Load key “/home/user/.ssh/id_ed25519″: invalid format”

Estás intentando usar una clave OpenSSH nueva (formato -----BEGIN OPENSSH PRIVATE KEY-----) en un cliente viejo (OpenSSH < 7.8). Solución: regenerá la clave en formato legacy, o actualizá el cliente. Para regenerar en formato viejo:

ssh-keygen -t ed25519 -o -m PEM -C "[email protected]"

-m PEM fuerza el formato PEM viejo, compatible con versiones anteriores a 7.8.

“Permission denied (publickey)” después de instalar la clave

Tres causas en orden de frecuencia, ya mencionadas pero vale repetir:

# En el servidor:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R usuario:usuario ~/.ssh
# verifica que el server está leyendo la clave:
sudo tail -f /var/log/auth.log
# (en RHEL: /var/log/secure)
# Al intentar login, vas a ver líneas tipo:
# sshd[1234]: Authentication refused: bad ownership or modes for directory /home/usuario/.ssh

“ssh-copy-id falla con “no keys found”

tienes la clave con nombre no estándar (id_ed25519_trabajo en vez de id_ed25519). Pasá -i explícito:

ssh-copy-id -i ~/.ssh/id_ed25519_trabajo.pub [email protected]

Ssh-agent no recuerda la passphrase entre reinicios

Es el comportamiento esperado en macOS — Keychain Integration guarda la passphrase y se la pasa al agente. En Linux puro, tienes que agregar ssh-add con la passphrase al inicio de sesión. Para GNOME con GNOME Keyring, las claves se cargan automáticamente cuando las agregás con seahorse. Para KDE, KWallet hace lo mismo. Para servidores sin GUI, agregá a tu .bashrc:

if [ -z "$SSH_AUTH_SOCK" ]; then
    eval $(ssh-agent -s)
    ssh-add ~/.ssh/id_ed25519
fi

Esto arranca el agente una vez por sesión y carga la clave. Te pide la passphrase la primera vez; después la recuerda hasta cerrar la sesión.


Conclusión

Migrar a ed25519 es una de esas mejoras de seguridad que tomarte 15 minutos te ahorra años de potenciales headaches. Claves más cortas, verificaciones más rápidas, resistencia a timing attacks, y compatibilidad con cualquier OpenSSH moderno. Si seguiste esta guía, ahora tienes una clave ed25519 con passphrase fuerte, instalada en tu server, con password login deshabilitado, y migrada progresivamente desde RSA sin perder acceso. Próximos pasos recomendados: configurar 2FA sobre SSH (lo cubrimos en otra guía de esta categoría), instalar fail2ban para mitigar fuerza bruta en el puerto SSH, y considerar cambiar el puerto SSH de 22 a otro alto para reducir ruido de bots automatizados.

Lee también: [Fail2ban: protege tu servidor SSH](/fail2ban-proteger-servidor-ssh-ataques-fuerza-bruta/) para ir un paso más allá en hardening, o [2FA en SSH con Google Authenticator](/2fa-ssh-google-authenticator-2026/) si quieres agregar un segundo factor de autenticación.

Preguntas frecuentes

¿Por qué Claves SSH ed25519: cómo generarlas bien (y migrar desde RSA) es relevante para sysadmins Linux?

Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.

¿Qué necesito para empezar con Claves SSH ed25519: cómo generarlas?

Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.

¿Cuáles son los errores más comunes con Claves SSH ed25519: cómo generarlas?

Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.

¿Cuándo usar Claves SSH ed25519: cómo generarlas y cuándo una alternativa?

Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.

¿Cómo migro desde una configuración previa a Claves SSH ed25519: cómo generarlas?

Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.

Lee también

Alfonso Moreno | Sysadmin Senior

Soy Alfonso, sysadmin senior con RHCE y más de 10 años administrando sistemas Linux para empresas y proyectos personales. Me especializo en infraestructura, redes, virtualización, monitoring, automation y self-hosting. Sobre SoyLinux.com SoyLinux.com es un blog técnico en español sobre Linux, software libre y self-hosting. Lo mantengo en mi tiempo libre. Áreas de expertise - Linux server administration: RHEL, CentOS, Rocky, Alma, Fedora, Debian, Ubuntu - Network services: Postfix, BIND, Samba, NFS, Squid - Virtualización y containers: KVM, Proxmox, Docker, Podman - Monitoring: Prometheus, Grafana, Zabbix - Automation: Ansible, Bash scripting - Self-hosting: Vaultwarden, Nextcloud, Jellyfin, Immich, Homelab Contacto - Email: [email protected]

2 thoughts on “Claves SSH ed25519: cómo generarlas bien (y migrar desde RSA)”

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *