Dos funciones para encriptar y desencriptar un texto mediante el algoritmo AES 256, con modo de encadenamiento CBC y con vector de inicialización.
- Función PHP para encriptar/cifrar texto en AES 256 CBC.
- Función PHP para desencriptar/descifrar texto en AES 256 CBC.
- Ejemplo de uso de las funciones PHP de encriptar y desencriptar texto en AES 256.
- Configuración de PHP para usar las funciones openssl_decrypt y openssl_encrypt.
Función PHP para encriptar/cifrar texto en AES 256 CBC
A continuación, mostramos un ejemplo de función PHP a la que se le pasa por argumento un texto y una clave (de 16 bytes) y devuelve un string con la cadena de texto cifrada más un vector de inicialización aleatorio, usando el algoritmo AES 256 y el modo de encadenamiento CBC:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Función para cifrar un texto en AES 256 CBC con clave y vector de inicialización function cifrarAES($texto, $clave) { // Generamos un IV (Vector de Inicialización o VI) aleatorio $vi = openssl_random_pseudo_bytes(16); // Cifrar el texto $texto= openssl_encrypt( $texto, 'AES-256-CBC', $clave, OPENSSL_RAW_DATA, $vi ); // Unimos el vector de inicialización y el texto cifrado y lo codificamos en base64 return base64_encode($vi . $texto); } |
Función PHP para desencriptar/descifrar texto en AES 256 CBC
A continuación, mostramos un ejemplo de función PHP a la que se le pasa por argumento un texto cifrado (cuyos primeros 16 bytes con el vector de inialización) y una clave (de 16 bytes) con la que se cifró y devuelve un string con la cadena de texto descifrada/desencriptada:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Función para descifrar un texto cifrado en AES 256 CBC con clave y vector de inicialización function descifrarAES($textoCifrado, $clave) { // Decodificar el texto cifrado (que incluye el vector de inicialización) $datos = base64_decode($textoCifrado); // Extraer el vector de inicialización (primeros 16 bytes) $vi = substr($datos, 0, 16); // Extraer el texto cifrado (resto del string) $textoCifrado = substr($datos, 16); // Descifrar return openssl_decrypt( $textoCifrado, 'AES-256-CBC', $clave, OPENSSL_RAW_DATA, $vi ); } |
Ejemplo de uso de las funciones PHP de encriptar y desencriptar texto en AES 256
Un ejemplo de uso de la función de encriptar texto, usando una clave de 32 bytes generada aleatoriamente para mayor seguridad que, por supuesto, deberemos conocer para su posterior descifrado:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
function generarGuardarTokenUsuario ($codigoUsuario, $bdConexion) { try { $token = generarToken(); $expiracion = time() + (3600 * 24 * 7 * 4); // 1 mes de validez $sqlPreparada = $bdConexion->prepare("UPDATE usuarios SET token=?, token_expiracion=? where codigo = ?"); $fecha = date('Y-m-d H:i:s', $expiracion); $sqlPreparada->bind_param("ssi", $token, $fecha, $codigoUsuario); $resultado = $sqlPreparada->execute(); if ($resultado) { // Generamos una clave de cifrado aleatoria de 32 bytes // Que es lo recomendado para AES 256 $clave = random_bytes(32); $token = cifrarAES($token, $clave); return [ 'error' => 'No', 'mensaje' => 'Token generado correctamente.', 'token' => $token, 'expiracion' => $expiracion ]; } else { //Para depuración, mostrar error return [ 'error' => 'Sí', 'mensaje' => $sqlPreparada->error, 'token' => '', 'expiracion' => '' ]; } } catch (Throwable $err) { //Para depuración, mostrar error return [ 'error' => 'Sí', 'mensaje' => $err->getMessage(), 'token' => '', 'expiracion' => '' ]; } } |
Para el caso del descifrado de un texto cifrado, un ejemplo de uso podría ser:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
function verificarToken($token, $codigoUsuario, $clave, $bdConexion) { $error = 'Sí'; $mensaje = 'Error al verificar el token.'; try { // Si no se ha pasado el token y el código de usuario devolvemos error if ($token == '' or $codigoUsuario == '' or $token == '.' or $codigoUsuario == '.') { $mensaje = 'Credenciales no proporcionadas.'; $error = 'Sí'; } else { // Desciframos el token que viene cifrado en AES $token = descifrarAES($token, $clave); // Verificar en base de datos $sqlPreparada = $bdConexion->prepare(" SELECT token, token_expiracion, activo FROM usuarios WHERE token = ? AND codigo = ? "); if ($sqlPreparada) { $sqlPreparada->bind_param("si", $token, $codigoUsuario); if ($sqlPreparada) { $resultado = $sqlPreparada->execute(); if ($resultado) { //$resultado = $sqlPreparada->get_result(); if ($resultado) { $resultado = $sqlPreparada->get_result(); $datos = $resultado->fetch_assoc(); if ($datos) { if ($datos['activo'] == 'S') { if (new DateTime() <= new DateTime($datos['expiracion'])) { // Si el usuario está activo y el token no está expirado // Devolvemos resultado correcto $mensaje = 'Inicio de sesión correcto.'; $error = 'No'; } else { $mensaje = 'Token expirado.'; } } else { $mensaje = 'Usuario no activo.'; } } else { $mensaje = 'No existe el token o el usuario.'; } } else { $mensaje = 'Error en el SQL'; } } else { $mensaje = 'Error al ejecutar el SQL.'; } } else { $mensaje = 'Error en los parámetros del SQL.'; } } else { $mensaje = 'Error al preparar el SQL.'; } } // Devolver los datos de la validación return [ 'error' => $error, 'mensaje' => $mensaje, 'codigoUsuario' => $codigoUsuario, 'token' => $token ]; } catch (Throwable $err) { //Para depuración, mostrar error return [ 'error' => 'Sí', 'mensaje' => $err->getMessage(), 'codigoUsuario' => $codigoUsuario, 'token' => $token ]; } } |
Configuración de PHP para usar las funciones openssl_decrypt y openssl_encrypt
Si usamos las funciones anteriores para cifrar/descifrar y recibimos estos errores:
Call to undefined function openssl_decrypt()
Call to undefined function openssl_encrypt()
El motivo es que no tenemos habilitada la extensión openssl en PHP. Para habilitarla, editaremos el fichero php.ini (o el que corresponda según la versión de PHP y el sistema operativo donde resida Apache o Nginx y descomentaremos esta línea:
;extension=openssl
Quitándole el punto y coma del principio y guardaremos los cambios en el fichero php.ini:

Reiniciaremos el servicio de Apache o Nginx y, con esto, se solucionará el problema y podremos usar las librerías openssl de PHP para cifrar/descifrar sin errores.