Introducción
A veces necesitamos generar un token en PHP o una cadena aleatoria. Por ejemplo, es muy común que cuando queremos restablecer nuestra contraseña se nos mande un mensaje al correo electrónico que teníamos registrado.
El mensaje probablemente tendrá un link como:
sitio.com/restablecer-pass?token=123
En donde 123 es el token. Hoy veremos cómo generar un token de esos pero sin depender del tiempo, haciéndolo criptográficamente seguro.
Ya que, como sabemos, si generamos un token aleatorio la mayoría de veces se basa en el tiempo Unix, cosa que puede ser (con cierta dificultad pero no por ello imposible) adivinada.
En este caso vamos a generar un token criptográficamente seguro, que de igual manera podríamos usar como contraseña, clave de cifrado, entre otros. Desde los usos más simples hasta los más complejos, y todo ello con la seguridad que se merece.
Esto funciona tanto para PHP 5 como para la versión 7.
Generar un token en PHP de forma que este sea seguro
Vamos a ver cómo generar un token en PHP, que no es más que un conjunto de caracteres que no deben ser adivinados de ninguna manera (excepto por fuerza bruta, pero eso es otra historia). Hay 2 versiones de este script, la primera para PHP 5 y la segunda para PHP 7.
Esto es porque PHP 7 incorpora nuevas funciones que no están presentes en las otras versiones, por lo que debemos buscar alternativas.
En PHP 5
Si usamos PHP en su versión 5 (aunque deberíamos actualizarnos) esto generará un token seguro:
#<?php
function generar_token_seguro($longitud)
{
if ($longitud < 4) {
$longitud = 4;
}
return bin2hex(openssl_random_pseudo_bytes(($longitud - ($longitud % 2)) / 2));
}
Dividimos la longitud entre 2, ya que al representar cada byte en formato hexadecimal estos se convierten en 2 dígitos.
Por ejemplo, “Hello” en hexadecimal es 48656c6c6f.
Y para llamarla la llamamos con un argumento: la longitud. Es decir, cuántos caracteres queremos o la longitud esperada de la cadena.
Ejemplos:
generar_token_seguro(4) => 6149
generar_token_seguro(20) => e7e1f6ba640e3069cf84
generar_token_seguro(16) => b46ce8aac0e4460d
generar_token_seguro(7) => b7dbbf
Es importante notar que cuando pasamos 7 devuelve en realidad una cadena de longitud 6, así que mejor pasamos números pares y mayores a 4.
En PHP 7
Modificaríamos la función y llamaríamos a random_bytes en lugar de openssl_random_pseudo_bytes. Queda así:
#<?php
function generar_token_seguro($longitud)
{
if ($longitud < 4) {
$longitud = 4;
}
return bin2hex(random_bytes(($longitud - ($longitud % 2)) / 2));
}
Ejemplos
Podemos llamar a la función y devolverá una cadena aleatoria, así:
generar_token_seguro(4) => 49ac
generar_token_seguro(20) => e613db7e8b4f50aaee0f
generar_token_seguro(16) => fd0e597e0639a401
generar_token_seguro(7) => 398896
Justo como se ve en la siguiente imagen: