Julio, miembro de nuestro equipo de trabajo, nos ha hecho el favor de crear este artículo porque controla a la perfección el tema.
Solución:
Utilice una biblioteca de cifrado PHP segura existente
Por lo general, es una mala idea escribir su propia criptografía a menos que tenga experiencia en romper las implementaciones de criptografía de otras personas.
Ninguno de los ejemplos aquí autentica el texto cifrado, lo que los deja vulnerables a los ataques de reescritura de bits.
Si puede instalar extensiones PECL, libsodium es aún mejor
Luego, para probarlo:
Esto se puede usar en cualquier situación en la que esté pasando datos al cliente (por ejemplo, cookies encriptadas para sesiones sin almacenamiento en el lado del servidor, parámetros de URL encriptados, etc.) con un grado razonablemente alto de certeza de que el usuario final no puede descifrar o manipular de manera confiable. con eso.
Dado que libsodium es multiplataforma, esto también facilita la comunicación con PHP desde, por ejemplo, subprogramas Java o aplicaciones móviles nativas.
Nota: Si necesita agregar específicamente cookies encriptadas impulsadas por libsodium a su aplicación, mi empleador Paragon Initiative Enterprises está desarrollando una biblioteca llamada Halite que hace todo esto por usted.
$sDecrypted
y $sEncrypted
no estaban definidos en su código. Ver una solución que funciona (¡pero no es seguro!):
¡PARADA!
Este ejemplo es ¡inseguro! ¡No lo uses!
$Pass = "Passwort";
$Clear = "Klartext";
$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypred: ".$crypted."";
$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypred: ".$newClear."";
function fnEncrypt($sValue, $sSecretKey)
return rtrim(
base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$sSecretKey, $sValue,
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND)
)
), " "
);
function fnDecrypt($sValue, $sSecretKey)
return rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
$sSecretKey,
base64_decode($sValue),
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND
)
), " "
);
Pero hay otros problemas en este código que lo hacen inseguro, en particular el uso de ECB (que no es un cifrado modo, solo un bloque de construcción sobre el cual se pueden definir modos de cifrado). Vea la respuesta de Fab Sa para una solución rápida de los peores problemas y la respuesta de Scott sobre cómo hacer esto correctamente.
Si tu no quiero usar una dependencia pesada para algo que se pueda resolver en 15 líneas de código, use el OpenSSL funciones. La mayoría de las instalaciones de PHP vienen con OpenSSL, que proporciona un cifrado AES rápido, compatible y seguro en PHP. Bueno, es seguro siempre que siga las mejores prácticas.
El siguiente código:
- usa AES256 en modo CBC
- es compatible con otras implementaciones de AES, pero no mcrypt, ya que mcrypt usa PKCS # 5 en lugar de PKCS # 7.
- genera un key de la contraseña proporcionada usando SHA256
- genera un hash hmac de los datos cifrados para comprobar la integridad
- genera un IV aleatorio para cada mensaje
- antepone el IV (16 bytes) y el hash (32 bytes) al texto cifrado
- debería ser bastante seguro
IV es una información pública y debe ser aleatoria para cada mensaje. El hash asegura que los datos no hayan sido manipulados.
function encrypt($plaintext, $password)
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);
return $iv . $hash . $ciphertext;
function decrypt($ivHashCiphertext, $password)
$method = "AES-256-CBC";
$iv = substr($ivHashCiphertext, 0, 16);
$hash = substr($ivHashCiphertext, 16, 32);
$ciphertext = substr($ivHashCiphertext, 48);
$key = hash('sha256', $password, true);
if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;
return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
Uso:
$encrypted = encrypt('Plaintext string.', 'password'); // this yields a binary string
echo decrypt($encrypted, 'password');
// decrypt($encrypted, 'wrong password') === null
editar: actualizado para usar hash_equals
y añadió IV al hachís.