Claves SSH en Nitrokey

Nacho - - Tiempo de lectura 7 mins

Me compré un jueguete nuevo, una llave USB Nitrokey. Bueno, en realidad me compré dos, porque no tengo criterio y se me ocurrió que capaz que rendía.

La cosa es que aparte de soportar el tema de passkeys, tiene también la capacidad de guardar claves SSH adentro. La clave SSH que estaba usando estaba un poco demasiado vieja y hace rato que tenía que cambiarla, así que por qué no aprovechar y ya meterlas adentro de la Nitrokey. Se supone que es más seguro.

Generar las claves

Como siempre, la forma de generar la clave es con ssh-keygen.

El comando es:

ssh-keygen -t ed25519-sk -O resident -f ~/.ssh/id_nitrokey

Ok, vamos por partes con eso.

  • -t ed25519-sk le dice a ssh-keygen que genere una clave de tipo ed25519-sk, donde el -sk significa “subilo al koso”, o su equivalente en inglés. Si no tiene -sk, la clave se genera y guarda en tu computadora, si tiene el -sk se genera y guarda en el Nitrokey (o el aparato que sea que estás usando), y en tu computadora sólo se guarda un puntero a la clave en el dispositivo. Si mirás el directorio ~/.ssh vas a ver una clave privada, pero no le hagas caso, no es, ese es el puntero.
  • -O resident le dice que guarde la clave de forma “descubrible”. Permite “bajar” el puntero que se te generó a otra computadora derecho desde el dispositivo. O al menos eso entiendo, no me terminó de quedar muy claro lo de discoverable contra non discoverable.
  • -f ~/.ssh/id_nitrokey es dónde guardar la clave. Podés ignorarlo para usar la ubicación por defecto (~/.ssh/id_ed25519_sk), y capaz que es lo más fácil.

Si tenés un PIN configurado (y deberías), te va a pedir el PIN, y que toques el dispositivo para confirmar, y listo, se genera la clave al toque.

Usar la clave

Para usarla, la usás como cualquier otra clave: copiá la clave pública a donde quieras/necesites, y ya está. Si el dispositivo no está enchufado, te va a dar error. Si está enchufado, te va a pedir que lo toques para confirmar la acción.

Copiar la clave a otra computadora

Si querés usar la clave que tenés guardada en tu dispositivo en otra computadora, tenés que copiar el puntero. Podés, por supuesto, copiar el archivo del directorio .ssh, pero también podés extraerlo directamente del dispositivo.

Para eso, usá este comando:

ssh-keygen -K

Eso te va a pedir el PIN, que toques el aparato, y después extrae todas las claves al directorio actual. O sea, las tenés que copiar a mano al directorio .ssh.

Opciones

Hasta acá lo básico. Pero hay varias cosas que podés querer toquetear.

Varias claves

Nitrokey soporta varias claves. Tiene espacio para alrededor de 20 claves “residentes”. Tené en cuenta que estas claves se guardan junto con las claves FIDO2, por lo que si estás usando Nitrokey para autenticarte en sitios web, cada clave SSH y cada passkey FIDO2 cuenta para ese límite. Y es “alrededor de” porque el tamaño no es fijo.

Si corrés el comando de arriba, va a intentar sobreescribir la clave ssh por defecto (te pide confirmación). Si querés más de una clave, le tenés que decir que te la guarde con un nombre diferente. Esto lo hacés con la opción -O application=ssh:nombre. Por ejemplo, si querés hacer una clave específica para usar con git, podés hacer:

ssh-keygen -t ed25519-sk -O resident -O application=ssh:git -f ~/.ssh/id_nk_git

No pedir tocar cada vez

Si estás usando la clave para git, posiblemente la uses también para firmar los commits. Si estás firmando los commits, y te pide que toques el aparato con cada commit, puede ser aburrido. Bueno, le podés pasar una opción para que no te pida tocar: -O no-touch-required. Modificando la clave para git de arriba te queda:

ssh-keygen -t ed25519-sk -O resident -O application=ssh:git -O no-touch-required -f ~/.ssh/id_nk_git

Si usás esa clave, no tenés que tocar tu Nitrokey cada vez. Sólo con tener el aparato enchufado estás.

Pedir PIN cada vez

Esto sería un poco lo opuesto de lo anterior: en lugar de menos interacción, más interacción.

La clave en tu Nitrokey está bastante segura. Sólo podés accederla con el archivo de puntero que tenés en tu directorio .ssh, y para copiar ese puntero a una computadora nueva te va a pedir el PIN. Pero capaz que querés un poco más de seguridad, por las dudas. Podés en ese caso decirle que te pida el PIN cada vez que vas a usar una clave. Para eso, usá la opción -O verify-required. Por ejemplo:

ssh-keygen -t ed25519-sk -O resident -O verify-required -f ~/.ssh/id_nk_pin

Esa sería la opción más segura de todas: no sólo tenés que tener el archivo de puntero y el Nitrokey, sino que tenés que tener el PIN. Obviamente, a cambio de eso tenés que es un poco una tranza, pero bueno.

Usando la opción de arriba para tener varias claves, podés tener diferentes claves con diferentes niveles de seguridad. Yo hice eso.

Listar/borrar claves

Si te aburriste de una clave, o te mandaste una cagada, o lo que sea, podés borrarla del dispositivo. Para eso, usá la utilidad nitropy. Primero, tenés que obtener la lista de claves:

$ nitropy fido2 list-credentials
Command line tool to interact with Nitrokey devices 0.11.4
Please provide pin:
There are 5 registered credentials
-----------------------------------
github.com:
- id: <secreto>
  user: mi-usuario-de-github
-----------------------------------
ssh:nachof-pin:
- id: <secreto>
  user: openssh
-----------------------------------
google.com:
- id: <secreto>
  user: mi-cuenta-de-google
-----------------------------------
ssh:nacho-git:
- id: <secreto> 
  user: openssh
-----------------------------------
ssh::
- id: <secreto>
  user: openssh
-----------------------------------
There is an estimated amount of 12 credential slots left

Ahí podés ver lo que mencionaba arriba, de que las passkeys y las claves SSH están todas mezcladas.

El id de cada clave es un chorizo de hexadecimales. Eso es lo que vas a necesitar para borrarla. De nuevo, nitropy:

$ nitropy fido2 delete-credential
Command line tool to interact with Nitrokey devices 0.11.4
Please provide credential-id: 
Please provide pin: 
Credential was successfully deleted

También podés usar eso para borrar passkeys que ya no necesitás.

Problemas

La primera clave que creé, la por defecto, anda bien, cero problemas. Las otras me dieron algunos problemas, que no termino de entender por qué.

Primero, la clave que requiere PIN: no anda en la computadora en la que la generé. Pero cuando la copié a otra computadora, anduvo bien. Volví a copiar la clave a la computadora original, y ahí funcionó. Sólo un detalle: le había puesto también la opción de no requerir tocar, pero al traer la clave desde el dispositivo, la opción de no requerir tocar desapareció.

Segundo, la clave que creé para git (que no requiere tocar): funciona con Gitlab, pero con Forgejo no (la rechaza). Peor: con Github no funciona, pero tampoco da error, simplemente se queda colgado. Si exporto la clave del dispositivo, ahí sí funciona, pero requiere tocar.

Evidentemente el problema viene por el lado del no-touch-required. La clave privada (el puntero) generada al crear la clave y la que descarga ssh-keygen -K son ligeramente diferentes cuando es una clave que no requiere tocar: claramente hay algo en ese puntero que dice que no requiere tocar, y ese algo no se persiste en el dispositivo.

Por ahora, entonces, no parece ser posible tener una clave que no requiera tocar el dispositivo. Al menos no que funcione en todos lados. Para firmar commits sirve, funciona sin problemas. Pero para conectarme, no siempre. No sé qué diferencia hay entre Forgejo, Gitlab, y Github, que hace que se comporte de maneras tan diferentes.

Conclusiones

Tengo que seguir investigando el tema de no requerir toques. Por lo demás, me sirve esto de tener las claves en el Nitrokey. Y de paso, actualicé mi vieja clave SSH que la venía usando para todo hace más tiempo del que debería.