Encriptar y desencriptar información con JavaScript usando AES

Encriptación con JavaScript del lado del cliente usando la Web Crypto API

En este post de programación con JavaScript en el navegador veremos cómo encriptar y desencriptar datos usando una API nativa, segura y confiable.

Encriptar y desencriptar información con JavaScript usando AES
Encriptar y desencriptar información con JavaScript usando AES

Vamos a usar la interfaz Crypto a través de window.crypto. Al final podremos encriptar y desencriptar archivos usando una contraseña, derivando una clave de la misma y usando AES para el cifrado de datos.

Nota: voy a usar cifrado y encriptado como sinónimos para referirme a la encriptación de información.

Por cierto, usaremos la encriptación simétrica aunque también es posible usar la asimétrica con claves públicas y privadas.

Demostración

Aquí te dejo una demostración que puedes usar para cifrar y descifrar información ya lista para producción: https://parzibyte.github.io/ejemplos-javascript/encriptacion-js/

Siempre puedes ver el código fuente para que veas que es totalmente del lado del cliente y seguro.

Una vez que hayas cifrado la información ya puedes guardarla en cualquier lugar, y podrás confiar en que nadie la podrá desencriptar aunque la tengan.

Explicación

Esto no es un post donde te explico los métodos de encriptación, lo que es un vector de inicialización, sal o una clave derivada de una contraseña. Si quieres aprender más de eso puedes ir a investigarlo y después volver al post.

Lo que vamos a hacer es generar una clave a partir de una contraseña del usuario (derivación de clave basada en contraseña o PBKDF2), y cada vez que encriptemos la información vamos a usar esa clave y una sal aleatoria.

Al momento de generar la información encriptada vamos a generar un vector de inicialización aleatorio (iv) y más tarde vamos a almacenar el vector y la sal junto con la información cifrada para que se puedan recuperar al momento de desencriptar.

Generando clave criptográfica a partir de contraseña

Al momento de encriptar y desencriptar con JavaScript vamos a necesitar la clave, y esa clave se generará desde la contraseña.

Con esta función obtenemos la key para cifrar y descifrar la información. En este caso el algoritmo usado por defecto es AES-CBC.

Encriptando información

Ahora veamos como cifrar con AES usando JavaScript. Hasta este punto ya tendremos la clave, entonces creamos una función que recibe la contraseña y el texto plano a cifrar.

Primero creamos la clave en la línea 6, con una sal aleatoria obtenida con getRandomValues que es una función criptográficamente segura; hacemos lo mismo con el vector de inicialización.

Después invocamos a crypto.subtle.encrypt  pasándole el algoritmo, la clave derivada de la contraseña y un búfer a partir del texto plano.

Finalmente regresamos ese búfer convertido a base64, ya que recuerda que al final la encriptación no distingue texto o archivos, simplemente ve una colección de bits.

Convertimos a base64 porque es una forma sencilla de codificar la información de un búfer; y ya esta cadena podemos almacenarla en cualquier lugar o transportarla.

Codificando y decodificando en Base64

Estas funciones son opcionales. Tú podrías almacenar el búfer de la manera que prefieras (como un blob, tomando los enteros y separándolos por coma, etcétera).

Solo recuerda que al momento de desencriptar debes recuperar el búfer original.

Por ello es que existen estas funciones que permiten codificar y decodificar el búfer. Nota que aquí no estamos haciendo nada de encriptación o cosas de seguridad, simplemente convertimos el búfer a una cadena amigable.

Desencriptar con JavaScript

Llegados a este punto veremos la función para desencriptar, que igualmente necesita la contraseña (luego vamos a sacar la clave derivada) y la cadena en base64.

Te repito que no es necesario el paso de la base64 pero es una manera fácil de guardar y mostrar cadenas.

Nota: recuerda que la sal y el iv están en la información, por ello es que los recuperamos en la línea 4 y 5. La verdadera información está después de esos dos parámetros.

Poniendo todo junto

Entonces básicamente podemos cifrar y descifrar información con JavaScript de una manera sencilla para el usuario. Lo único que necesitamos es…

  • Para cifrar necesitamos la contraseña como string y la información que vamos a proteger como string.
  • Para descifrar necesitamos la contraseña como string y la información cifrada como string en base64.

El código fuente de la demostración está aquí.

Conclusión

Asegurar la información confidencial es importante. Con esta API moderna y segura de JavaScript podemos encriptar información usando AES, y después guardarla en el navegador, en Firebase, en un servidor, etcétera.

Podemos estar seguros de que nadie más podrá acceder a la información descifrada al menos que cuenten con la contraseña.

Se me ocurre que podrías usar esto para cosas confidenciales como un gestor de contraseñas, un diario personal, notas seguras, etcétera.

A ver si después hago algunos posts usando esta API. Mientras tanto basta con la demostración que ya dejé al inicio del post.

Por aquí te dejo más tutoriales de JavaScript en mi blog.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

4 comentarios en “Encriptación con JavaScript del lado del cliente usando la Web Crypto API”

  1. Hola, gracias por tu post, tengo una duda; teniendo en cuenta que el js se ejecuta del lado de cliente que mecanismos de seguridad se pueden implementar para que una persona no replique el mismo código y finalemente poder desencriptar el mensaje. Gracias.

Dejar un comentario