Cuaderno de GNUtas

Cómo ocultar contraseñas en nuestro código Elisp con auth.el

La situación hipotética es la siguiente. Imaginemos que estamos escribiendo alguna función en Emacs Lisp que incluye como cadena de texto cierta información que nos conviene ofuscar de alguna manera, tal un nombre de usuario y una contraseña, bien porque queremos publicar ese código en la web o lo tenemos en la nube y (por muy segura que sea nuestra nube) queremos curarnos en salud. La solución en GNU Emacs es muy sencilla gracias a la biblioteca auth.el, que nos resultará muy útil a la hora de extraer información contenida en el archivo ~/.authinfo y aplicarla a nuestra función como variables locales, de forma que no tengamos que poner una contraseña de manera literal.

El archivo .authinfo

Si ya somos habituales usuarios del cliente emacsiano de correo y noticias Gnus, estaremos familiarizados con el fichero .authinfo que reside en nuestro directorio local. Si no, aquí sigue un breve recordatorio. authinfo se emplea para almacenar todo tipo de usuarios y contraseñas (incluso nuestro usuario y contraseña de administrador del equipo donde estamos), si bien aquí nos centraremos (siguiendo con nuestro caso hipotético) en una imaginaria cuenta de correo correofeten.xyz donde el usuario imaginario es «donnadie» y su contraseña «pi_31416». La sintaxis de authinfo está muy definida y requiere un campo para cada uno de esos elementos y otros necesarios a la hora de identificarse. En este caso concreto, la línea que tendríamos que añadir para ese usuario sería algo así como:

machine correofeten.xyz login donnadie password pi_31416 port 993

Y lo que necesitamos añadir a nuestra función como cadena de texto son precisamente los campos login y password. ¿Cómo lo logramos? Bien, con la biblioteca auth.el, incluída de fábrica en Emacs, resulta bastante simple, y así lo veremos a continuación.

auth.el al rescate

La biblioteca auth.el nos proporciona la utilísima función auth-source-search, que buscará en nuestro documento authinfo aquella línea que contenga la propiedad requerida, y nos devolverá una lista cuyo primer elemento es una «plist», es decir, una «lista de propiedades» en la jerga elispiana.

Si queremos pasar a nuestra función el usuario y la contraseña como variables locales, podemos empezar definiendo (recuérdese que ponemos la expresión let con asterisco para que se respete el orden de variables):

(let*
    ((autent
      (car
       (auth-source-search :host "correofeten.xyz"
                           :requires '(user secret))))

Es decir, la primera variable, que hemos llamado autent nos devolverá una lista de propiedades a partir de la línea de nuestro authinfo que contenga el :host «correofeten.xyz». Ya sólo nos quedaría (las dos siguientes variables) extraer de esa lista la propiedad :user para el usuario y la propiedad :secret, que almacena la cadena de la contraseña, teniendo en cuenta que ésta última será una función lambda que debe evaluarse para obtener dicha cadena:

(mi-usuario (plist-get autent :user))
 (mi-password (funcall (plist-get autent :secret))))

Y para comprobar que ambas variables recogen la información correcta, cerramos nuestra expresión let con un mensaje. Evaluamos toda la expresión.

  (let*
      ((autent
        (car
         (auth-source-search :host "correofeten.xyz"
                           :requires '(user secret))))
  (mi-usuario (plist-get autent :user))
   (mi-password (funcall (plist-get autent :secret))))
(message "El usuario es %s y la contraseña es %s" mi-usuario mi-password))
"El usuario es donnadie y la contraseña es pi_31416"

Una vez que hemos comprobado que las variables almacenan bien ambos datos sensibles, ya podemos extender a conveniencia nuestra función o código que necesiten incluirlos, sin temor de que estén al alcance de ojos maliciosos, puesto que los tenemos guardados en nuestro archivo authinfo.

Publicado: 12/11/20

Última actualización: 16/08/23


Índice general

Acerca de...

Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.

© Juan Manuel Macías
Creado con esmero en
GNU Emacs