Casi todo lo que sé sobre claves

Todos tenemos al menos media docena de claves que nos dan acceso a innumerables contenidos y servicios pero qué hay detrás de esos formularios de acceso, cómo se almacenan o cómo deberían almacenarse estas credenciales y cómo se verifican o cómo se deberían verificar. En este artículo nos adentraremos en mis conocimientos sobre claves.

Empecemos por cómo se almacenan las credenciales.

Esencialmente existen tres formas de almacenar tu clave: sin cifrar, cifrado simétrico y cifrado asimétrico. No te asustes por los términos porque lo vamos a explicar con sencillez.

Almacenar la clave sin cifrado es el método más sencillo y vulnerable además de ser ilegal en España porque no cumple los requisitos de Ley de Protección de Datos de Caracter Personal. Sin embargo, sea por pereza o desconocimiento del programador, sigue utilizándose en algunas ocasiones.

Como parte del registro, la web sencillamente almacena en base de datos el nombre la clave tan cual fue escrita por el usuario. Lo representaremos así:

Usuario Clave
------- ---------
yo      lamia

Ni qué decir que si alguien roba esta información, inmediatamente dispone de las claves de todos los usuarios, sin más esfuerzo, lo que no significa que sea fácil de robar.

Posteriormente al registro, cuando el usuario se identifica, el sistema tiene dos formas de comprobar si el usuario ha escrito su clave, la correcta y la aún-más-vulnerable.

En la forma que correcta, o digamos que al menos no empeora la situación, el lenguaje de programación le dice al lenguage de base de datos (SQL) algo que traduciremos al español como «dame el registro de la tabla de usuarios cuyo campo nombre_usuario es ‘yo’» y después [el lenguaje de programación] comprueba si el campo clave_usuario contiene el mismo texto que el usuario ha escrito en el formulario de acceso. Para los flipadetes escribiré algo de pseudo código:

si registro[clave_usuario] igual a formulario[clave_usuario] entonces
login es cierto
sino
login es falso

En la forma incorrecta, la negligencia permite al atacante identificarse como cualquier usuario sin saber su clave. También se puede aplicar cuando la clave fue almacenada cifrada, pero la explico ahora que estamos inmersos en el peor escenario.

En este caso el lenguaje de programación le dice al lenguaje de base de datos (SQL) algo que traduciremos al español como «dame el registro de la tabla de usuarios cuyo campo nombre_usuario es ‘yo’ y su clave es ‘lamia’». El problema aquí es que estamos pasando la presunta clave del usuario a la base de datos sin ninguna comprobación. Entonces qué pasa si yo digo que mi clave es la siguiente «’ o 1=1» pues que el lenguaje de programación le dice al lenguaje de base de datos (SQL) algo que traduciremos al español como «dame el registro de la tabla de usuarios cuyo campo nombre_usuario es ‘yo’ y su clave es » o 1=1» (hemos cambiado donde ponía ‘lamia’ por esa clave tan retorcida y malintencionadamente escrita) lo cual siempre es cierto porque aunque su clave no esté vacía, 1 siempre es igual a 1, así que el lenguaje de programación obtiene su registro y cree que la identificación ha sido legítima.

Una manera de identificar si la web es así de cutre, digo insegura, es pulsar en ‘recordar contraseña’. Si te la envían por correo, es decir, si saben cuál es tu clave, cancela tu cuenta inmediatamente.

Almacenar la clave con cifrado simétrico es un método bastante fiable pero creo que casi nadie lo utiliza porque si alguien se plantea utilizar cifrado, directamente utiliza el cifrado asimétrico, salvo que exista un verdadero motivo para poder querer saber tu clave.

Durante el registro, la web apunta el nombre del usuario y el resultado de aplicar un algoritmo de cifrado sobre la clave que eligió el usuario. El algoritmo simétrico se llama así porque se puede encriptar pero también desencriptar si sabes la clave con la cuál fue encriptado. Lo representaremos así:

ClaveCifrada = encripta_simetrico(clave_usuario, clave_web)
ClaveUsuario = desencripta_simetrico(ClaveCifrada, clave_web)

Para simplificar, suponemos que el encriptado simétrico simplemente cambia cada letra con una posterior, y que clave web es +1, es decir que cambiamos cada letra por la letra siguiente, así el resultado sería ‘mbnjb’ (la siguiente a la ‘l’ es la ‘m’, la siguiente a la ‘a’ es la ‘b’, la siguiente a la ‘m’ es la ‘n’, etc.)

Usuario Clave
------- ---------
yo      mbnjb

Ahora, si alguien roba esta tabla, no sabe cuáles son las claves, para ésto necesitaría dos cosas más: saber cuál es el algoritmo de encriptación y saber cuál es la clave de la web. Así que es bastante más seguro porque habría que robar datos pero también código. Aunque si el algoritmo fuera así de chorra, sabiendo una (la propia del atacante) se podría inferir tanto el algoritmo como la clave de encriptación. Por suerte los hay bastante más efectivos.

Durante la identificación posterior, a la hora de comprobar si el usuario ha escrito su clave, lo más probable es se opte por el método seguro que hemos explicado antes, donde el lenguaje de programación le dice al lenguaje de base de datos (SQL) algo que traduciremos al español como «dame el registro de la tabla de usuarios cuyo campo nombre_usuario es ‘yo’» y después puede hacer dos cosas: o bien desencriptar la clave que guardó para compararla con la clave que ha introducido el usuario, o bien encriptar la clave que ha introducido el usuario y comprobar si coincide con la que guardó en su día. Para los flipadetes escribiré algo de pseudo código del primer caso:

si desencripta_simetrico(registro[clave_usuario], clave_web) igual a formulario[clave_usuario] entonces
login es cierto
sino
login es falso

En este escenario también podría suceder que al pulsar ‘recordar contraseña’ te la envíen por correo y puedas creer que estás en la situación anterior. Sería un poco injusto para ellos pero no podemos estar seguros.

Almacenar la clave con cifrado asimétrico es el método más fiable que abarcaremos.

Durante el registro, la web almacena el nombre del usuario y el resultado de aplicar un algoritmo de cifrado sobre la clave que eligió el usuario. El algoritmo asimétrico se llama así porque se puede encriptar pero no desencriptar. Lo representaremos así:

ClaveCifrada = encripta_asimetrico(clave_usuario)

El cifrado asimétrico genera un resultado que, sin ser único, es altamente improbable que coincida con otro. Si por ejemplo se utiliza el algoritmo MD5 el número de posibles combinaciones son 680 sextrillones de resultado posibles. Claro que el número de claves posibles es infinito así que alguna colisión puede haber, pero en la práctica no es vital.

Usuario Clave
------- --------------------------------
yo      04fc6d58f3a7f1968dd8a89d1f44e511

Si no se puede desencriptar, cómo es posible comprobar si la clave que ha introducido el usuario es verdaderamente su clave, pues ya sabes la respuesta porque la solución es una de las opciones que vimos en el caso anterior y por eso ejemplifiqué la contraria, para ejemplificar aquí ésta.

Durante la identificación posterior, a la hora de comprobar si el usuario ha escrito su clave, el lenguaje de programación le dice al lenguaje de base de datos (SQL) algo que traduciremos al español como «dame el registro de la tabla de usuarios cuyo campo nombre_usuario es ‘yo’» y después se vuelve a encriptar la clave del usuario y se comprueba si coincide con el valor almacenado. Para los flipadetes escribiré algo de pseudo código:

si registro[clave_usuario] igual a encripta_asimetrico(formulario[clave_usuario]) entonces
login es cierto
sino
login es falso

Vías de ataque

La vía más vulgar es que una persona se ponga a hacer combinaciones razonables de tus datos. Si por ejemplo te llamas Ainara y naciste el 1 de Diciembre de 1980 pues seria razonable pensar que tu clave es ainara80 o 011280 o tonterías más grandes. No voy a gastar más palabras, si sueles hacer cosas así, léete el apartado ‘Contraseñas saludables’.

Una vía clásica es la llamada fuerza bruta. Circulan por internet inmensos listados de palabras comunes en contraseñas. Esencialmente consiste en ponerse a probarlas todas hasta que una coincide, si es que coincide alguna.

Actualmente se utiliza mucho la vía del phising, que consiste en hacerte creer que estás donde no estás. De algún modo, generalmente por e-mail, se te induce a visitar una web, generalmente un banco, pero realmente el enlace que pulsas va a un servidor donde se aloja una web extremadamente parecida que espera que ingenuamente introduzcas tus datos reales de identificación. Tras guardarlos, te informan de algún problema indeterminado por el cual no puedes continuar.

La vía más compleja la llamaríamos ‘hombre en medio’ porque consiste en espiar la comunicación entre tu ordenador y el servidor de destino para ‘ver pasar’ tu clave. En principio ésto se soluciona cuando el formulario está en un entorno protegido por un certificado de seguridad que hace que los datos en la comunicación viajen encriptados; pero yo no pondría la mano en el fuego afirmando que ésto no pueda ser violado, en todo caso, es la mejor solución que tenemos.

Qué significa que han robado las claves una web

Ya puedes hacerte una idea por tí mismo de qué significa que hayan robado las claves una web. Puede que tengan un montón de claves sin cifrar, ya sea porque se almacenaron así o porque se han interceptado, en cuyo caso ya pueden preocuparse todos los usuarios; puede que tengan un montón de claves cifradas y el método para descrifrarlas, en cuyo caso ya pueden preocuparse todos los usuarios; puede que tengan un montón de claves cifradas sin manera de descrifrarlas, cuyo caso veremos ahora.

Muchos sitios ponen algunas barreras adicionales para mejorar la seguridad como por ejemplo un numero máximo de intentos fallidos de identifcarse, tras los cuales no puedes intentarlo hasta cierto tiempo después o adicionalmente has de resolver un captcha. Entonces para qué sirve tener un monton de claves cifradas, pues para probar en un ordenador externo un ataque de fuerza bruta saltándose esas limitaciones y una vez tienen la clave correcta, ya pueden usarla.

Encriptación de datos

Sólo porque he prometido contar todo lo que sé, voy a adentrarme también en ésto pero si no estoy siendo apasionante, puedes saltar al siguiente bloque.

Puestos a ser puristas habría que encriptar algo más que tu clave, también todos tus datos no públicos. Ésto debería ser obligatorio en toda web que contenga información sensible como pudieran ser datos médicos. Obviamente, aquí habría que utilizar algoritmos simétricos, cuya clave de encriptación sería tu clave de identificación y por tanto se comprometerían a tener acceso a esa información sólo mientras tu estás usando la web y la clave está temporalmente almacenada en memoria sin encriptación.

Supongamos un campo con información sobre dolencias con un valor como ‘arritmia cardíaca’, esto quedaría almacenado encriptado con tu clave (‘lamia’) y por tanto su valor sería diferente al valor de la misma dolencia con la clave de otro usuario (‘lasuya’). De esta manera, no sólo quedas protegido de ataques (no quieres que alguien sepa tu clave, pero tampoco quieres que alguien sepa tus dolencias si se roba la información), con esta protección también estás a salvo del uso estadístico de tus datos, impidiendo que -por ejemplo- alguien liste cuántas personas que coinciden con un apellido, tienen también dolencias en común. Ésto no sería posible ya que las dolencias tendrían valores diferentes dependiendo de las claves de cada usuario y no se podría saber si son la misma.

Usuario: yo
Clave: 04fc6d58f3a7f1968dd8a89d1f44e511 ('lamia' algoritmo MD5)
Dolencias: Gko7dOAmH9xiB59PJQMJk9n0aLHkWRnyo38H0IpEyticyNZzDmWm1iIvb3hvLgtkpA3r6KLs9hQ
('arritmia cardíaca' algoritmo XTEA usando 'lamia' como clave de encriptación)
Usuario: el
Clave: fd2819e43489d1f419464b1a1e27d8eb ('lasuya' algoritmo MD5)
Dolencias: wBIF5aTKPwHvQxNbPOcPo8ujGyd6LBYzX3IwJMzBArJYg+nTUZmYMaVnFAbE6VRdbyppIUqYuLU
('arritmia cardíaca' algoritmo XTEA usando 'lasuya' como clave)

Aunque se sepa que tus dolencias están cifradas con tu clave, como no saben tu clave, no pueden saber tus dolencias, salvo el tiempo que estás usando la web, que es el tiempo que consientes que recuerden tu clave.

Esta capa de protección tiene un sobrecoste para la web ya que cuando cambias tu clave, se ha de desencriptar y reencriptar todos tus datos.

Contraseñas saludables

Muchas webs te obligan a tener una longitud mínima y cierto nivel de ‘caos’ mezclando letras y números, mayúsculas y minúsculas, … La creatividad en cuanto a las reglas puede ser tan grande que sea un suplicio encontrar una clave razonablemente fácil de recordar y que cumpla todos los requisitos, asi que algunas páginas te dejan cierta libertad y simplemente te informan de cuánto segura les parece tu clave, aunque si el día de mañana se produce un robo parcial, ellos serán quienes se lleven toda la ignominia.

Aquel brote de originalidad de c4mb14r l3tr4s p0r núm3r0s fue una estupenda manera de que muchas personas adoptasen una buena práctica. Sin duda ésto hace crecer exponencialmente las combinaciones a comprobar, ya sea por la vía vulgar o la fuerza bruta.

Un error habitual es utilizar la misma clave para todo porque obviamente una vez te han cazado la clave en un sitio tienen acceso a un montón de sitios más. Claro, no podemos recordar una clave diferente para cada web, o sí podemos … La solución de ir por casa para este problema es tener claves con una parte fija una parte variable. La parte fija es esa parte común que nos resulta fácil recordar y la parte variable es algo que nos parece significativo de esa web, si por ejemplo nuestra parte fija es ainara80, nuestra clave para gmail podría ser ainara80ggl (ggl es abreviación de google), ainara80gml (gml es abreviación de gmail) o … con lo cual no sólo han de saber la parte fija sino intuir qué destacaste y cómo abreviaste la parte variable. No es infalible pero toca las narices al atacante.