Gestión ordenada de claves pública y privada para acceso por SSH
Tags: ssh, linux, productividad, buenaspracticas
Published: 2021-12-03 10:12:35

¿Cómo crear y gestionar claves SSH de manera ordenada? (Versión GNU/Linux)

Tras el anuncio en julio de 2020 en el que GitHub [anunciaba la desactivación del acceso](https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations/) a los repositorios mediante user/pass, la mejor opción y más segura es usar claves SSH. Esta forma de acceso y autenticación no es nueva, seguramente tengas más de una clave ya configurada con cifrado antiguo y guardadas de aquella manera. ¿Qué mejor momento que ordenarlas, eliminar las que no uses y actualizarlas? En este breve tutorial vamos a crear nuevas claves con cifrado ed22519 para 3 plataformas: GitLab, GitHub y Bitbucket.

Renovación de pares de claves al cifrado ed25519 y ordenación para autenticación en múltiples plataformas.

> **Importante:**Importante: si no tienes ninguna clave creada, ve directamente al punto 2. El 1 está dedicado a mostrar cómo podemos tener de desordenado el acceso a servidores remotos mediante claves si ya se han creado anteriormente.

## 1. Localizar las claves y mostrar el directorio

Dentro de nuestra carpeta  /home/$USER, existen dos tipos de archivos, los que están sin ocultar que se visualizan con normalidad y los ocultos que tienen un punto delante. Para poder listar los segundos, debemos añadir la opción -a a la orden:

Listado de archivos sin ocultar

```
ls -l
```

Listado de archivos sin ocultar y ocultos

```
ls -la
```

Si observamos entre las carpetas ocultas, tendremos .ssh que será en la que organizaremos las claves públicas y privadas.

```
$ cd ~/.ssh && ls -l
```

> **Importante:** Este punto, como he comentado anteriormente, es orientativo, solo sirve para comprobar si tenemos claves sin usar y/o antiguas ya creadas.


Probablemente, tengas una estructura similar a esta


    -rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 2016 clavessh
    -rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 2016 clavessh.pub
    -rw-rw-r-- 1 [USER] [GROUP]  378 jun 21 2018 clave1.pub
    -rw-rw-r-- 1 [USER] [GROUP]  380 jun 21 2018 clave1
    -rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 17:37 claveprivada.pub
    -rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
    -rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old

Sabes que el par de claves **clavessh** accede a algo pero no a qué, y mucho menos **clave1**. Por otro lado, claveprivada.pub, que no tiene sentido, tiene perdida su parte privada. En definitiva, un lío que es mejor eliminar.

## 2. La casa por la ventana y muebles nuevos, aplicamos algoritmo de cifrado ed22519

Sin posibilidad de recordar qué tipo de cifrado tenemos (lo veremos posteriormente), es posible que se trate de **RSA** con una longitud de bits entre 1024 y 2048. Introducido en la versión 6.5 (2014) de OpenSSH, **ed22519** presenta mejor robustez y, además, está recomendado por plataformas como GitLab.

[GitLab and SSH keys](https://docs.gitlab.com/ee/ssh/index.html)

### 2.1 Eliminamos los archivos que tenemos desperdigados en la carpeta .ssh

Procedemos a identificar qué archivos son. Presumiblemente, los que tienen la extensión .pub son la par pública y los que no tienen extensión, la privada. Recuerda que hemos de estar en la carpeta oculta .ssh tal como hicimos en el primer comando, es decir

```
$ cd ~/.ssh
```
Realizamos la siguiente operación en uno de los archivos arriba expuestos

```
$ cat clavessh
```

mostrando lo siguiente


    -----BEGIN OPENSSH PRIVATE KEY-----
    [Filas de caracteres aleatorios]
    -----END OPENSSH PRIVATE KEY-----


Nos aseguramos de que este archivo sí es una clave privada. Si realizamos

```
$ cat ~/.ssh/clavessh.pub
```

nos muestra una información con la siguiente estructura


    ssh-rsa [caracteres aleatorios] -C [e-mail]


Ya hemos descubierto que se trata de un algoritmo RSA. Visto esto, e identificando cuáles son los archivos de claves, los eliminaremos y crearemos nuevos con el siguiente comando 

```
$ rm clavessh* clave1 claveprivada*
```

o bien, teniendo en cuenta que todos empiezan por la cadena "clave"

```
$ rm clave*
```

### 2.2 Crear carpetas para las claves privadas y públicas

Con el objetivo de tener las claves ordenadas, creamos dos carpetas dentro de .ssh

```
$ mkdir clavesprivadas
```

y

```
$ mkdir clavespublicas
```

## 3. Creación de claves

Si nos hemos movido, volvemos a la carpeta .ssh

```
$ cd ~/.ssh
```

Generamos las claves con

```
$ ssh-keygen -t ed25519 -C "[inserta tu e-mail]"
```

Y obtenemos lo siguiente.

    Generating public/private ed25519 key pair.

En la siguiente pregunta, escribe, por ejemplo, la plataforma en la que vas a usar esta clave. En este caso, he indicado `gitlab`

    Enter file in which to save the key (/home/[USER]/.ssh/id_ed25519): gitlab

Puedes incluir, o no, una capa extra que sería la contraseña:

    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 

Ya tenemos los datos guardados en la carpeta .ssh, dos archivos llamados gitlab (clave privada) y gitlab.pub (clave pública)

    Your identification has been saved in gitlab
    Your public key has been saved in gitlab.pub
    The key fingerprint is:
    SHA256:[Códigos aleatorios] [el e-mail que incluiste]
    The key's randomart image is:
    +--[ED25519 256]--+
    |            * *O=|
    |         E + *=**|
    |        . = .E==*|
    |         + . ..+*|
    |        s o   .o*|
    |       . o + .  *|
    |        . . = o.+|
    |             = +o|
    |              =++|
    +----[SHA256]-----+

Si listamos la carpeta .ssh, nos encontramos con los dos archivos recientemente creados y las carpetas donde guardaremos las claves


    $ ls -l ~/.ssh
    total 24
    -rw-rw-r-- 1 [USER] [GROUP]  411 jul 29 12:00 gitlab
    -rw-rw-r-- 1 [USER] [GROUP]   99 jul 29 12:00 gitlab.pub
    -rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
    -rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
    drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
    drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas



De la misma manera, podemos crear nuevas claves para cualquier plataforma. Como recordatorio, no es obligatorio poner el nombre de la plataforma, pero así quedaría mejor organizado.

### 3.1 Agregar clave ssh al ssh-agent

Iniciamos el agente ssh en un segundo plano

```
$ eval "$(ssh-agent -s)"
```
Arrojando un PID (Process ID) garantizando que ha sido arrancado correctamente

    Agent pid XXXXX

Siendo XXXXX un número diferente cada vez. Agregamos la clave privada al agente SSH

```
$ ssh-add ~/.ssh/gitlab
```
Repetimos este último paso de agregar la clave privada con el resto que hayamos creado.

## 4. Guardado de claves

Simplemente, se trata de mover cada clave a su carpeta

```
$ mv gitlab clavesprivadas/
```

y

```
$ mv gitlab.pub clavespublicas/
```

Si hemos creado otras claves, realizamos el mismo proceso modificando el nombre del archivo en la orden de arriba.

## 5. Copia de clave pública en plataformas

Para que GitLab, en este caso, nos reconozca la clave, hay que agregar la clave en la sección correspondiente. Como primer paso, hay que acceder a la carpeta donde está almacenada

```
$ cd clavespublicas
```

vemos el contenido

```
$ cat gitlab.pub
```

Nos aparecerá una línea similar a esta

    ssh-rsa [caracteres aleatorios] [e-mail]

Seleccionamos la línea completa y copiamos su contenido.

### 5.1 Registro en plataforma

Siguiendo con el ejemplo de GitLab, seguimos los pasos para llegar al lugar donde se registran tras acceder a nuestro perfil

- (Opción 1) [Acceso directo a la sección Claves SSH de Preferencias](https://gitlab.com/-/profile/keys)
- (Opción 2) Esquina superior derecha **Preferences** -> Columna izquierda **Claves SSH**

Una vez dentro

1. En "Clave", copiamos el contenido de nuestra clave pública. Asegúrate que empieza por `ssh-ed25519` y que termine con el correo electrónico que anotamos cuando la creamos.
2. En el cajón "Título", elige una definición descriptiva. Por ejemplo, el equipo que usa esa clave.
3. Como medida opcional de seguridad, puedes agregar una fecha de caducidad.

Ya tendríamos la clave registrada. La siguiente tarea consistirá en probar que funciona. Vamos al terminal y, dentro de la subcarpeta clavesprivadas de .ssh, escribimos

```
$ ssh -T -i gitlab git@gitlab.com
```

Y obtendrías el siguiente mensaje en caso de haber configurado correctamente la clave SSH

    Welcome to GitLab, @[GitLab_User]!

Si quieres ver cómo funciona el test de conexión o mirar qué puede haber fallado (ruta mal escrita, archivo desubicado,...), puedes probar añadiendo el parámetro -v de "verbose"

```
$ ssh -T -v -i gitlab git@gitlab.com
```

Tras mostrar por pantalla las conexiones establecidas, las 4 últimas líneas serían

    Welcome to GitLab, @[GitLab_User]!
    debug1: channel 0: free: client-session, nchannels 1
    Transferred: sent 2084, received 2400 bytes, in 0.6 seconds
    Bytes per second: sent 3568.5, received 4109.6

## 6. Creación del archivo config de SSH

Una vez guardadas las claves en carpetas, creamos el archivo de configuración que servirá para dos objetivos básicos: 

1. Identificar las claves con la plataforma en donde las estamos usando.
2. Crear un índice para identificar las que no estamos usando y, por seguridad, podemos borrar.

Para crear el archivo, debemos llamarlo "config" y ubicarlo dentro de la carpeta .ssh. Con el comando `nano` creamos y abrimos directamente el nuevo archivo:

```
$ nano ~/.ssh/config
```

Una vez que nos encontramos con el archivo recién creado, identificamos cada clave de la siguiente manera:

    # Texto informativo que identifique cada plataforma
    Host ejemplo.ltd
    HostName ejemplo.ltf
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/clavesprivadas/claveprivada

Aplicando el ejemplo de GitLab, quedaría así:

    # GitLab
    Host gitlab.com
    HostName gitlab.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/clavesprivadas/gitlab

Podemos crear en el mismo archivo, manteniendo la misma estructura, todas las claves privadas. A continuación, un supuesto caso de que tuviésemos las claves en GitLab, GitHub y Bitbucket:


    # GitHub
    Host github.com
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/clavesprivadas/github

    # GitLab
    Host gitlab.com
    HostName gitlab.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/clavesprivadas/gitlab

    # Bitbucket
    Host bitbucket.org
    HostName bitbucket.org
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/clavesprivadas/bitbucket


Si queremos probar la conexión, copiamos el siguiente comando en el caso de GitLab.

```
$ ssh -T -v -i gitlab git@gitlab.com
```

Teniendo en cuenta que hemos añadido la opción *verbose* con `-v`, podemos observar que entre las líneas de respuesta encontramos un fragmento similar a este:

    debug1: Trying private key: /home/[USER]/.ssh/clavesprivadas/gitlab
    debug1: Authentication succeeded (publickey).
    Authenticated to gitlab.com ([IP]:[PUERTO (normalmente, 22)]).

Con este resultado, comprobamos que la conexión de la clave privada con nuestro repositorio es exitosa.

---

## Extra

### Actualizar URI de repositorio de https a SSH

¿Qué ocurre si ya teníamos un repositorio que se identificase a través de https y lo que queremos es a través de las claves? Probablemente, una vez configuradas las claves, hayas intentado realizar un commit y siga solicitando user/pass. Para ello, debemos realizar, dentro de la carpeta del repositorio, el siguiente comando:

```
$ git remote set-url git@gitlab.com:USERNAME/REPOSITORY.git
```

Más información en [*How to change Git Remote Origin*](https://devconnected.com/how-to-change-git-remote-origin/)

### Protección extra de la carpeta de claves privadas

Si realizamos un listado de la carpeta con el siguiente comando:

```
$ ls ~/.ssh/
```

Obtenemos un resultado similar:

    total 24
    -rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
    -rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
    drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
    drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas

Normalmente, los archivos tienen permisos 644, es decir:

- 6 como permisos de lectura y escritura con nuestro propio *user*.
- 4 como permisos de lectura para quienes estén en el mismo grupo asociado.
- 4 como permisos de lectura para otras personas que estén en nuestro sistema.

Y los directorios, 755. Para profundizar en este tema, recomiendo este enlace de *atareao* [Propietarios y permisos](https://atareao.es/tutorial/terminal/propietarios-y-permisos/).  

¿Qué podemos hacer al respecto? Cambiar los permisos a 600 para que nadie puede acceder ni leer los archivos de las claves privadas si no es con nuestro propio *user*.

```
$ chmod 700 ~/.ssh/clavesprivadas
```

Así, si volvemos a hacer `ls -l` obtenemos el mismo listado pero con una ligera diferencia:

    total 24
    -rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
    -rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
    drwx------ 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
    drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas

En la línea del directorio **clavesprivadas** han desaparecido los permisos para el mismo grupo y "otros". De esta manera, una persona que no sea yo no tiene acceso ni permisos de lectura de una carpeta con un contenido tan sensible como es la que contiene nuestras claves privadas.


Foto: "[Engranaje](https://search.creativecommons.org/photos/07a7f9fe-3b41-424c-990a-3499bd07a792)" por J4R está licenciada con [CC BY-SA 2.0](https://creativecommons.org/licenses/by-sa/2.0/ ).