@RqLizard tarafından önerildiği gibi , bunun yerine Rijndael şifrelemesi olarak da bilinen AES (Gelişmiş Şifreleme Standardı) uygulamak için çok daha iyi bir alternatif sağlayan openssl_encrypt
/ openssl_decrypt
PHP işlevlerini kullanabilirsiniz .
Aşağıdaki Scott'ın php.net'teki yorumuna göre :
2015'te verileri şifrelemek / şifrelemek için kod yazıyorsanız, openssl_encrypt()
ve kullanmalısınız openssl_decrypt()
. Temel kitaplık ( libmcrypt
) 2007'den beri terk edilmiş ve OpenSSL'den ( AES-NI
modern işlemcilerden yararlanan ve önbellek zamanlaması güvenli) çok daha kötü performans gösteriyor .
Ayrıca, MCRYPT_RIJNDAEL_256
değil AES-256
, bu Rijndael blok şifresinin farklı bir çeşidi. İsterseniz AES-256
de mcrypt
, kullanmak zorunda MCRYPT_RIJNDAEL_128
32 bayt anahtar ile. OpenSSL, hangi modu kullandığınızı (yani aes-128-cbc
vs aes-256-ctr
) daha belirgin hale getirir .
OpenSSL ayrıca mcrypt'in NULL bayt dolgusu yerine CBC modunda PKCS7 dolgusunu kullanır. Bu nedenle, mcrypt, kodunuzu OpenSSL'den daha fazla oracle saldırılarına karşı savunmasız hale getirir.
Son olarak, şifreli metinlerinizi doğrulamıyorsanız (Sonra Şifrele MAC), yanlış yapıyorsunuz demektir.
Daha fazla okuma:
Kod örnekleri
Örnek 1
PHP 7.1+ için GCM modunda AES Kimlik Doğrulamalı Şifreleme örneği
<?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";
}
?>
Örnek 2
PHP 5.6+ için AES Authenticated Encryption örneği
<?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";
}
?>
Örnek 3
Yukarıdaki örneklere dayanarak, kullanıcının oturum kimliğini şifrelemeyi amaçlayan aşağıdaki kodu değiştirdim:
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());
}
}
içine:
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();
}
}
Açıklığa kavuşturmak gerekirse, iki şifreleme farklı bir blok boyutu ve farklı bir şifrelenmiş veri kullandığından yukarıdaki değişiklik gerçek bir dönüşüm değildir. Ek olarak, varsayılan dolgu farklıdır, MCRYPT_RIJNDAEL
yalnızca standart olmayan boş doldurmayı destekler. @zaph
Ek notlar (@ zaph'ın yorumlarından):
- Rijndael 128 (
MCRYPT_RIJNDAEL_128
) , AES'e eşdeğerdir , ancak Rijndael 256 ( MCRYPT_RIJNDAEL_256
) , 256 bitlik bir blok boyutunu belirlediğinden AES-256 değildir , oysa AES yalnızca bir blok boyutuna sahiptir: 128 bit. Yani temelde 256 bitlik ( MCRYPT_RIJNDAEL_256
) blok boyutuna sahip Rijndael , mcrypt geliştiricilerinin seçimleri nedeniyle yanlışlıkla adlandırılmıştır . @zaph
- 256 blok boyutuna sahip Rijndael, 128 bitlik bir blok boyutuna göre daha az güvenli olabilir, çünkü ikincisi çok daha fazla inceleme ve kullanıma sahipti. İkinci olarak, birlikte çalışabilirlik, AES genel olarak mevcutken, 256 bitlik bir blok boyutuna sahip Rijndael'in olmadığı durumda engellenir.
Rijndael için farklı blok boyutlarıyla şifreleme, farklı şifrelenmiş veriler üretir.
Örneğin, MCRYPT_RIJNDAEL_256
(eşdeğer olmayan AES-256
) 256 bit boyutuna ve anahtar geçirilen göre bir anahtar boyutu Rijndael blok şifreleme farklı bir çeşidini tanımlar, burada aes-256-cbc
Rijndael bir anahtar boyutu 128-bitlik bir blok boyutuna sahip olan 256 bit. Bu nedenle, mcrypt, blok boyutunu belirtmek için sayıyı kullandığından, tamamen farklı şifrelenmiş veriler üreten farklı blok boyutları kullanıyorlar; burada OpenSSL, anahtar boyutunu belirtmek için sayıyı kullandı (AES yalnızca 128 bitlik bir blok boyutuna sahiptir). Yani temelde AES, 128 bitlik blok boyutuna ve 128, 192 ve 256 bitlik anahtar boyutlarına sahip Rijndael'dir. Bu nedenle OpenSSL'de Rijndael 128 olarak adlandırılan AES kullanmak daha iyidir.
password_hash
doğrulamıyorsunuzpassword_verify
?