Pie*_*iet 87 php encryption passwords mcrypt php-7
不推荐使用的mcrypt-extension 将根据此处发布的评论在PHP 7.2中删除.所以我正在寻找一种加密密码的替代方法.
现在我正在使用类似的东西
mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)
Run Code Online (Sandbox Code Playgroud)
我需要您对加密密码的最佳/最强方式的意见,加密密码当然应该由PHP 7.xx支持,并且还应该是可解密的,因为我的客户确实想要选择"恢复"他们的密码而不生成新的密码一.
Phi*_*hil 40
散列密码是最佳做法,因此它们不可解密.这使得可能获得对您的数据库或文件的访问权的攻击者更加困难.
如果您必须加密数据并使其可解密,请访问https://paragonie.com/white-paper/2015-secure-php-data-encryption获取安全加密/解密指南.总结一下这个链接:
ken*_*orb 24
正如@rqLizard建议的那样,您可以使用openssl_encrypt
/ openssl_decrypt
PHP函数,它提供了更好的替代方法来实现AES(高级加密标准),也称为Rijndael加密.
根据以下Scott在php.net上的评论:
如果您在2015年编写代码来加密/加密数据,则应使用
openssl_encrypt()
和openssl_decrypt()
.底层库(libmcrypt
)自2007年以来就已被放弃,其性能远远超过OpenSSL(它利用AES-NI
现代处理器并且是高速缓存定时安全的).此外,
MCRYPT_RIJNDAEL_256
它不是AES-256
,它是Rijndael分组密码的不同变体.如果你想AES-256
在mcrypt
,你必须使用MCRYPT_RIJNDAEL_128
一个32字节的密钥.OpenSSL使您更明显地使用哪种模式(即aes-128-cbc
vsaes-256-ctr
).OpenSSL还使用带有CBC模式的PKCS7填充而不是mcrypt的NULL字节填充.因此,mcrypt更有可能使您的代码容易受到填充oracle攻击而不是OpenSSL.
最后,如果您没有验证您的密文(加密然后MAC),那么您做错了.
进一步阅读:
适用于PHP 7.1+的GCM模式示例中的AES认证加密
<?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";
}
?>
Run Code Online (Sandbox Code Playgroud)
适用于PHP 5.6+的AES认证加密示例
<?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";
}
?>
Run Code Online (Sandbox Code Playgroud)
基于以上示例,我更改了以下用于加密用户会话ID的代码:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
成:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
为了澄清,上面的更改不是真正的转换,因为两个加密使用不同的块大小和不同的加密数据.此外,默认填充不同,MCRYPT_RIJNDAEL
仅支持非标准空填充.@zaph
附加说明(来自@ zaph的评论):
MCRYPT_RIJNDAEL_128
)是等同于AES,但是Rijndael算法256(MCRYPT_RIJNDAEL_256
)是不 AES-256作为256指定的256位的块尺寸,而AES仅具有一个块大小:128比特.因此,MCRYPT_RIJNDAEL_256
由于mcrypt开发人员的选择,基本上Rijndael的块大小为256位()被错误地命名.@zaphRijndael使用不同块大小的加密产生不同的加密数据.
例如,MCRYPT_RIJNDAEL_256
(不等效于AES-256
)定义了Rijndael分组密码的不同变体,其大小为256位,密钥大小基于传入密钥,其中aes-256-cbc
Rijndael的块大小为128位,密钥大小为256位.因此,他们使用不同的块大小产生完全不同的加密数据,因为mcrypt使用该数字来指定块大小,其中OpenSSL使用该数字来指定密钥大小(AES只有一个块大小为128位).所以基本上AES是Rijndael,块大小为128位,密钥大小为128,192和256位.因此,最好使用AES,在OpenSSL中称为Rijndael 128.
Rijndael的纯PHP实现与phpseclib一起存在,可以作为作曲家软件包使用,并且可以在PHP 7.3上运行(由我测试)。
phpseclib文档上有一个页面,在您输入基本变量(密码,模式,密钥大小,位大小)之后,该页面会生成示例代码。它为Rijndael,ECB,256、256输出以下内容:
用mycrypt编写的代码
$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);
Run Code Online (Sandbox Code Playgroud)
在图书馆这样工作
$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);
Run Code Online (Sandbox Code Playgroud)
*原$term
为base64_decoded
小智 5
如此处其他答案所详述,我发现的最佳解决方案是使用OpenSSL。它内置在PHP中,您不需要任何外部库。以下是简单的示例:
加密:
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);
}
Run Code Online (Sandbox Code Playgroud)
解密:
function decrypt($key, $garble) {
list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}
Run Code Online (Sandbox Code Playgroud)
参考链接:https : //www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/