
Piet
Die mcrypt-Erweiterung ist veraltet wird gemäß dem geposteten Kommentar in PHP 7.2 entfernt Hier. Also suche ich nach einer alternativen Möglichkeit, Passwörter zu verschlüsseln.
Im Moment benutze ich so etwas wie
mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)
Ich brauche Ihre Meinung für die beste/stärkste Methode zum Verschlüsseln von Passwörtern. Das verschlüsselte Passwort sollte natürlich von PHP 7.xx unterstützt werden und auch entschlüsselbar sein, da meine Kunden die Möglichkeit haben möchten, ihre Passwörter wiederherzustellen, ohne ein neues zu generieren ein.
Es hat sich bewährt, Kennwörter zu hashen, damit sie nicht entschlüsselbar sind. Dies erschwert Angreifern, die möglicherweise Zugriff auf Ihre Datenbank oder Dateien haben, die Arbeit etwas.
Wenn Sie Ihre Daten verschlüsseln und entschlüsseln müssen, finden Sie eine Anleitung zur sicheren Verschlüsselung/Entschlüsselung unter https://paragonie.com/white-paper/2015-secure-php-data-encryption. Um diesen Link zusammenzufassen:
- Verwenden Libnatrium – Eine PHP-Erweiterung
- Wenn Sie Libsodium nicht verwenden können, verwenden Sie es entschärfen/php-verschlüsselung – Reiner PHP-Code
- Wenn Sie Libsodium oder defuse/php-encryption nicht verwenden können, verwenden Sie OpenSSL – Auf vielen Servern ist dies bereits installiert. Wenn nicht, kann es mit –with-openssl kompiliert werden[=DIR]

kenorb
Wie von @rqLizard vorgeschlagen, können Sie verwenden openssl_encrypt
/openssl_decrypt
PHP-Funktionen stattdessen, was eine viel bessere Alternative zum Implementieren bietet AES (The Advanced Encryption Standard), auch bekannt als Rijndael-Verschlüsselung.
Wie im Folgenden Scotts Kommentar auf php.net:
Wenn Sie 2015 Code zum Verschlüsseln/Verschlüsseln von Daten schreiben, sollten Sie verwenden openssl_encrypt()
und openssl_decrypt()
. Die zugrunde liegende Bibliothek (libmcrypt
) wird seit 2007 aufgegeben und ist weitaus schlechter als OpenSSL (das AES-NI
auf modernen Prozessoren und ist Cache-Timing-sicher).
Ebenfalls, MCRYPT_RIJNDAEL_256
ist nicht AES-256
, es ist eine andere Variante der Rijndael-Blockchiffre. Falls Sie es wollen AES-256
in mcrypt
müssen Sie verwenden MCRYPT_RIJNDAEL_128
mit einem 32-Byte-Schlüssel. OpenSSL macht deutlicher, welchen Modus Sie verwenden (z aes-128-cbc
vs aes-256-ctr
).
OpenSSL verwendet auch PKCS7-Padding mit CBC-Modus anstelle des NULL-Byte-Padding von mcrypt. Daher ist es wahrscheinlicher, dass mcrypt Ihren Code anfälliger für Padding-Oracle-Angriffe macht als OpenSSL.
Wenn Sie Ihre Chiffretexte nicht authentifizieren (Encrypt Then MAC), machen Sie schließlich etwas falsch.
Weiterlesen:
Codebeispiele
Beispiel 1
Beispiel für AES-authentifizierte Verschlüsselung im GCM-Modus für PHP 7.1+
<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
//store $cipher, $iv, and $tag for decryption later
$original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
echo $original_plaintext."\n";
}
?>
Beispiel #2
AES-authentifiziertes Verschlüsselungsbeispiel für PHP 5.6+
<?php
//$key previously generated safely, ie: openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
//decrypt later....
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
{
echo $original_plaintext."\n";
}
?>
Beispiel #3
Basierend auf den obigen Beispielen habe ich den folgenden Code geändert, der darauf abzielt, die Sitzungs-ID des Benutzers zu verschlüsseln:
class Session {
/**
* Encrypts the session ID and returns it as a base 64 encoded string.
*
* @param $session_id
* @return string
*/
public function encrypt($session_id) {
// Get the MD5 hash salt as a key.
$key = $this->_getSalt();
// For an easy iv, MD5 the salt again.
$iv = $this->_getIv();
// Encrypt the session ID.
$encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
// Base 64 encode the encrypted session ID.
$encryptedSessionId = base64_encode($encrypt);
// Return it.
return $encryptedSessionId;
}
/**
* Decrypts a base 64 encoded encrypted session ID back to its original form.
*
* @param $encryptedSessionId
* @return string
*/
public function decrypt($encryptedSessionId) {
// Get the MD5 hash salt as a key.
$key = $this->_getSalt();
// For an easy iv, MD5 the salt again.
$iv = $this->_getIv();
// Decode the encrypted session ID from base 64.
$decoded = base64_decode($encryptedSessionId);
// Decrypt the string.
$decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
// Trim the whitespace from the end.
$session_id = rtrim($decryptedSessionId, "\0");
// Return it.
return $session_id;
}
public function _getIv() {
return md5($this->_getSalt());
}
public function _getSalt() {
return md5($this->drupal->drupalGetHashSalt());
}
}
hinein:
class Session {
const SESS_CIPHER = 'aes-128-cbc';
/**
* Encrypts the session ID and returns it as a base 64 encoded string.
*
* @param $session_id
* @return string
*/
public function encrypt($session_id) {
// Get the MD5 hash salt as a key.
$key = $this->_getSalt();
// For an easy iv, MD5 the salt again.
$iv = $this->_getIv();
// Encrypt the session ID.
$ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
// Base 64 encode the encrypted session ID.
$encryptedSessionId = base64_encode($ciphertext);
// Return it.
return $encryptedSessionId;
}
/**
* Decrypts a base 64 encoded encrypted session ID back to its original form.
*
* @param $encryptedSessionId
* @return string
*/
public function decrypt($encryptedSessionId) {
// Get the Drupal hash salt as a key.
$key = $this->_getSalt();
// Get the iv.
$iv = $this->_getIv();
// Decode the encrypted session ID from base 64.
$decoded = base64_decode($encryptedSessionId, TRUE);
// Decrypt the string.
$decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
// Trim the whitespace from the end.
$session_id = rtrim($decryptedSessionId, '\0');
// Return it.
return $session_id;
}
public function _getIv() {
$ivlen = openssl_cipher_iv_length(self::SESS_CIPHER);
return substr(md5($this->_getSalt()), 0, $ivlen);
}
public function _getSalt() {
return $this->drupal->drupalGetHashSalt();
}
}
Zur Verdeutlichung ist die obige Änderung keine echte Konvertierung, da die beiden Verschlüsselungen eine unterschiedliche Blockgröße und unterschiedliche verschlüsselte Daten verwenden. Außerdem ist die Standardauffüllung anders, MCRYPT_RIJNDAEL
unterstützt nur Nicht-Standard-Null-Padding. @zaf
Zusätzliche Anmerkungen (aus den Kommentaren von @zaph):
- Rijndael 128 (
MCRYPT_RIJNDAEL_128
) ist gleichwertig AESaber Rijndael 256 (MCRYPT_RIJNDAEL_256
) ist nicht AES-256 da 256 eine Blockgröße von 256 Bit angibt, wohingegen AES hat nur eine Blockgröße: 128 Bit. Also im Grunde Rijndael mit einer Blockgröße von 256 Bit (MCRYPT_RIJNDAEL_256
) wurde aufgrund der Auswahl durch die fälschlicherweise benannt mcrypt Entwickler. @zaf
- Rijndael mit einer Blockgröße von 256 ist möglicherweise weniger sicher als mit einer Blockgröße von 128 Bit, da letztere viel mehr Überprüfungen und Verwendungen hatte. Zweitens wird die Interoperabilität dadurch behindert, dass AES zwar allgemein verfügbar ist, Rijndael mit einer Blockgröße von 256 Bit jedoch nicht.
-
Die Verschlüsselung mit unterschiedlichen Blockgrößen für Rijndael erzeugt unterschiedliche verschlüsselte Daten.
Zum Beispiel, MCRYPT_RIJNDAEL_256
(nicht gleichbedeutend mit AES-256
) definiert eine andere Variante der Rijndael-Blockchiffre mit einer Größe von 256 Bit und einer Schlüsselgröße, die auf dem übergebenen Schlüssel basiert, wobei aes-256-cbc
ist Rijndael mit einer Blockgröße von 128 Bit bei einer Schlüsselgröße von 256 Bit. Daher verwenden sie unterschiedliche Blockgrößen, die völlig unterschiedliche verschlüsselte Daten erzeugen, da mcrypt die Zahl verwendet, um die Blockgröße anzugeben, wo OpenSSL die Zahl verwendet, um die Schlüsselgröße anzugeben (AES hat nur eine Blockgröße von 128 Bit). Im Grunde ist AES also Rijndael mit einer Blockgröße von 128 Bit und Schlüsselgrößen von 128, 192 und 256 Bit. Daher ist es besser, AES zu verwenden, das in OpenSSL Rijndael 128 heißt.
Wie in anderen Antworten hier beschrieben, ist die beste Lösung, die ich gefunden habe, die Verwendung von OpenSSL. Es ist in PHP integriert und Sie benötigen keine externe Bibliothek. Hier sind einfache Beispiele:
Zum Verschlüsseln:
function encrypt($key, $payload) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv);
return base64_encode($encrypted . '::' . $iv);
}
Zum Entschlüsseln:
function decrypt($key, $garble) {
list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}
Referenzlink: https://www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/
Eine reine PHP-Implementierung von Rijndael existiert mit phpseclib als Composer-Paket verfügbar und funktioniert auf PHP 7.3 (von mir getestet).
Es gibt eine Seite in den phpseclib-Dokumenten, die generiert Beispielcode nachdem Sie die grundlegenden Variablen (Verschlüsselung, Modus, Schlüsselgröße, Bitgröße) eingegeben haben. Es gibt Folgendes für Rijndael, ECB, 256, 256 aus:
ein Code mit mycrypt
$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);
funktioniert so mit der Bibliothek
$rijndael = new \phpseclib\Crypt\Rijndael(\phpseclib\Crypt\Rijndael::MODE_ECB);
$rijndael->setKey(ENCRYPT_KEY);
$rijndael->setKeyLength(256);
$rijndael->disablePadding();
$rijndael->setBlockLength(256);
$decoded = $rijndael->decrypt($term);
* $term
war base64_decoded
Sie können verwenden phpseclib Pollyfill-Paket. Sie können Open SSL oder Libsodium nicht zum Verschlüsseln/Entschlüsseln mit rijndael 256 verwenden. Ein weiteres Problem ist, dass Sie keinen Code ersetzen müssen.

kenorb
Sie sollten OpenSSL verwenden mcrypt
da es aktiv entwickelt und gepflegt wird. Es bietet eine bessere Sicherheit, Wartbarkeit und Portabilität. Zweitens führt es die AES-Verschlüsselung/Entschlüsselung viel schneller durch. Es verwendet standardmäßig PKCS7-Padding, aber Sie können es angeben OPENSSL_ZERO_PADDING
wenn du es brauchst. Zur Verwendung mit einem 32-Byte-Binärschlüssel können Sie angeben aes-256-cbc
was viel offensichtlicher ist als MCRYPT_RIJNDAEL_128
.
Hier ist das Codebeispiel mit Mcrypt:
Nicht authentifizierte AES-256-CBC-Verschlüsselungsbibliothek, geschrieben in Mcrypt mit PKCS7-Padding.
/**
* This library is unsafe because it does not MAC after encrypting
*/
class UnsafeMcryptAES
{
const CIPHER = MCRYPT_RIJNDAEL_128;
public static function encrypt($message, $key)
{
if (mb_strlen($key, '8bit') !== 32) {
throw new Exception("Needs a 256-bit key!");
}
$ivsize = mcrypt_get_iv_size(self::CIPHER);
$iv = mcrypt_create_iv($ivsize, MCRYPT_DEV_URANDOM);
// Add PKCS7 Padding
$block = mcrypt_get_block_size(self::CIPHER);
$pad = $block - (mb_strlen($message, '8bit') % $block, '8bit');
$message .= str_repeat(chr($pad), $pad);
$ciphertext = mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$key,
$message,
MCRYPT_MODE_CBC,
$iv
);
return $iv . $ciphertext;
}
public static function decrypt($message, $key)
{
if (mb_strlen($key, '8bit') !== 32) {
throw new Exception("Needs a 256-bit key!");
}
$ivsize = mcrypt_get_iv_size(self::CIPHER);
$iv = mb_substr($message, 0, $ivsize, '8bit');
$ciphertext = mb_substr($message, $ivsize, null, '8bit');
$plaintext = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$key,
$ciphertext,
MCRYPT_MODE_CBC,
$iv
);
$len = mb_strlen($plaintext, '8bit');
$pad = ord($plaintext[$len - 1]);
if ($pad <= 0 || $pad > $block) {
// Padding error!
return false;
}
return mb_substr($plaintext, 0, $len - $pad, '8bit');
}
}
Und hier ist die Version, die mit OpenSSL geschrieben wurde:
/**
* This library is unsafe because it does not MAC after encrypting
*/
class UnsafeOpensslAES
{
const METHOD = 'aes-256-cbc';
public static function encrypt($message, $key)
{
if (mb_strlen($key, '8bit') !== 32) {
throw new Exception("Needs a 256-bit key!");
}
$ivsize = openssl_cipher_iv_length(self::METHOD);
$iv = openssl_random_pseudo_bytes($ivsize);
$ciphertext = openssl_encrypt(
$message,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$iv
);
return $iv . $ciphertext;
}
public static function decrypt($message, $key)
{
if (mb_strlen($key, '8bit') !== 32) {
throw new Exception("Needs a 256-bit key!");
}
$ivsize = openssl_cipher_iv_length(self::METHOD);
$iv = mb_substr($message, 0, $ivsize, '8bit');
$ciphertext = mb_substr($message, $ivsize, null, '8bit');
return openssl_decrypt(
$ciphertext,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$iv
);
}
}
Quelle: Wenn Sie das Wort MCRYPT in Ihren PHP-Code eingeben, machen Sie es falsch.

halber
Ich verwende dies auf PHP 7.2.x, es funktioniert gut für mich:
public function make_hash($userStr){
try{
/**
* Used and tested on PHP 7.2x, Salt has been removed manually, it is now added by PHP
*/
return password_hash($userStr, PASSWORD_BCRYPT);
}catch(Exception $exc){
$this->tempVar = $exc->getMessage();
return false;
}
}
und authentifizieren Sie dann den Hash mit der folgenden Funktion:
public function varify_user($userStr,$hash){
try{
if (password_verify($userStr, $hash)) {
return true;
}
else {
return false;
}
}catch(Exception $exc){
$this->tempVar = $exc->getMessage();
return false;
}
}
Beispiel:
//create hash from user string
$user_password = $obj->make_hash2($user_key);
und um diesen Hash zu authentifizieren, verwenden Sie den folgenden Code:
if($obj->varify_user($key, $user_key)){
//this is correct, you can proceed with
}
Das ist alles.
9866500cookie-checkmcrypt ist veraltet, was ist die Alternative?yes
Warum müssen Sie Passwörter verschlüsseln/entschlüsseln? Warum nicht einfach mit hashen
password_hash
und verifiziere sie mitpassword_verify
?– Keine Panik
21. Dezember 2016 um 21:36 Uhr
„Das verschlüsselte Passwort sollte auch entschlüsselbar sein“ – warum? klingt nicht allzu sicher. Irgendein besonderer Grund?
– Funk Forty-Niner
21. Dezember 2016 um 21:37 Uhr
“weil meine Kunden die Möglichkeit haben möchten, ihre Passwörter wiederherzustellen, ohne ein neues zu generieren.” – Das ist nicht sicher und sie sollten stattdessen die Möglichkeit haben, ihre Passwörter zurückzusetzen.
– Funk Forty-Niner
21. Dezember 2016 um 22:04 Uhr
Passwörter nicht verschlüsseln, wenn der Angreifer die DB erhält, erhält er auch den Verschlüsselungsschlüssel. Iterieren Sie über einen HMAC mit einem zufälligen Salz für etwa 100 ms und speichern Sie das Salz mit dem Hash. Verwenden Sie Funktionen wie password_hash, PBKDF2, Bcrypt und ähnliche Funktionen. Der Punkt ist, den Angreifer dazu zu bringen, viel Zeit damit zu verbringen, Passwörter durch Brute Force zu finden.
– zaph
8. März 2017 um 16:32 Uhr
Aus dem PHP-Handbuch -> Diese Funktion ist seit PHP 7.1.0 VERALTET. Es wird dringend davon abgeraten, sich auf diese Funktion zu verlassen. Alternative ist Natrium -> php.net/manual/en/book.sodium.php
– MarcoZen
19. Juli 2018 um 6:09 Uhr