mcrypt는 권장되지 않습니다.대안은 무엇입니까?
mcrypt-extension은 권장되지 않습니다.여기에 게재된 코멘트에 따라 PHP 7.2에서 삭제됩니다.그래서 비밀번호를 암호화할 다른 방법을 찾고 있습니다.
저는 지금 이렇게 쓰고 있어요
mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)
패스워드를 암호화하는 최선의/강력한 방법이 필요합니다.암호화된 패스워드는 물론 PHP 7.xx에서 지원되어야 하며, 고객이 새로운 패스워드를 생성하지 않고 '복구'하는 옵션을 원하기 때문에 복호화도 가능해야 합니다.
암호를 해독할 수 없도록 암호를 해시하는 것이 가장 좋습니다.이로 인해 데이터베이스 또는 파일에 대한 액세스 권한을 얻은 공격자가 문제를 약간 더 어렵게 만들 수 있습니다.
데이터를 암호화하여 복호화할 필요가 있는 경우, 암호화/암호화를 보호하기 위한 가이드는 https://paragonie.com/white-paper/2015-secure-php-data-encryption 에서 구할 수 있습니다.링크를 요약하면:
- 립소듐 사용 - PHP 확장자
- Libsodium을 사용할 수 없다면 디퓨즈/php-encryption 사용 - 스트레이트 PHP 코드
- Libsodium 또는 defuse/php-encryption을 사용할 수 없는 경우 OpenSSL을 사용하십시오.많은 서버에 이미 설치되어 있습니다.그렇지 않은 경우 --with-sl[=]로 컴파일할 수 있습니다.DIR]
@rqLizard가 제안하는 바와 같이 / PHP 함수를 openssl_decrypt
사용하면 Rijndael 암호화로도 알려진 AES(Advanced Encryption Standard)를 구현하는 데 더 나은 대안을 제공할 수 있습니다.
php.net에서 Scott의 코멘트는 다음과 같습니다.
2015년를 위한 2015년 데이터 암호화/암호화 코드를 .
openssl_encrypt()
★★★★★★★★★★★★★★★★★」openssl_decrypt()
. 기반이 되는 라이브러리(libmcrypt
는 2007년OpenSSL( OpenSSL을 활용)보다 저하되었습니다.AES-NI
최신 프로세서에 탑재되어 있으며 캐시 캐시 스위칭이 안전합니다).ㅇㅇㅇㅇ.
MCRYPT_RIJNDAEL_256
AES-256
리젠다엘네가 원한다면AES-256
mcrypt
, 을.MCRYPT_RIJNDAEL_128
32살OpenSSL을 모드를 하게 알 수 OpenSSL).aes-128-cbc
»aes-256-ctr
를 참조해 주세요.OpenSSL은 또한 mcrypt의 NULL 바이트 패딩 대신 CBC 모드를 사용한 PKCS7 패딩을 사용합니다.따라서 mcrypt는 OpenSSL보다 코드를 패딩 오라클 공격에 취약하게 만들 가능성이 높습니다.
마지막으로 암호문(암호화 후 MAC)을 인증하지 않으면 잘못된 것입니다.
추가 정보:
코드 예시
예 #1
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";
}
?>
예 #2
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";
}
?>
예 3
위의 예에 따라 사용자의 세션 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());
}
}
다음과 같이 입력합니다.
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();
}
}
명확히 하자면, 위의 변경은 진정한 변환이 아닙니다.두 가지 암호화에서는 다른 블록 크기와 다른 암호화된 데이터가 사용되기 때문입니다. 패딩은 패딩은 디폴트 패딩이 다릅니다.MCRYPT_RIJNDAEL
는 비표준 늘패딩만 지원합니다.@zaph
기타 주의사항(@zaph 댓글 참조):
- Rijndael 128 (
MCRYPT_RIJNDAEL_128
)는 AES와 동등하지만 Rijndael 256(단,MCRYPT_RIJNDAEL_256
)는 256은 256비트의 블록사이즈를 나타내므로 AES-256이 아닙니다만, AES에는 128비트라는1개의 블록사이즈밖에 없습니다.즉, 기본적으로 블록사이즈가 256비트인 Rijndael(MCRYPT_RIJNDAEL_256
mcrypt 개발자의 선택으로 인해 이름이 잘못 지정되었습니다.@zaph - 블록 사이즈가 256인 Rijndael은 128비트의 블록사이즈보다 안전성이 떨어집니다.이는 128비트가 리뷰와 사용이 훨씬 많기 때문입니다.둘째, AES는 일반적으로 사용할 수 있지만 256비트 블록사이즈의 Rijndael은 사용할 수 없다는 점에서 상호운용성이 저해됩니다.
Rijndael의 블록 사이즈가 다른 암호화에서는 다른 암호화된 데이터가 생성됩니다.
를 들어, 「」라고 하는 것은,
MCRYPT_RIJNDAEL_256
하지 않다)AES-256
된 키에키서 Rijndael은 256비트입니다.aes-256-cbc
【리젠다엘】128년, 【256년】따라서 mcrypt가 이 숫자를 사용하여 블록 크기를 지정하고 OpenSSL은 이 숫자를 사용하여 키 크기를 지정하므로 완전히 다른 암호화된 데이터를 생성하는 블록 크기를 사용합니다(AES는 128비트 블록 크기가 1개뿐).따라서 기본적으로 AES는 Rijndael이며 블록 크기는 128비트, 키 크기는 128비트, 192비트 및 256비트입니다.OpenSSL의 Rijndael 128의 AES입니다.
다른 답변에서도 알 수 있듯이 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);
}
복호화 방법:
function decrypt($key, $garble) {
list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}
레퍼런스 링크: https://www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/
Rijndael의 순수 PHP 구현은 작곡가 패키지로 사용 가능한 phpseclib와 함께 존재하며 PHP 7.3에서 작동합니다(제가 테스트했습니다).
phpseclib 문서에는 기본 변수(암호화, 모드, 키 크기, 비트 크기)를 입력한 후 샘플 코드를 생성하는 페이지가 있습니다.Rijndael, ECB, 256, 256에 대해 다음을 출력합니다.
내 암호로 된 암호
$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);
도서관에서는 이렇게 작업합니다.
$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
base64_decoded
phpseclib pollyfill 패키지를 사용할 수 있습니다.rijndael 256을 사용한 암호화/복호화에는 open ssl 또는 libsodium을 사용할 수 없습니다.또 다른 문제는 코드를 교체할 필요가 없다는 것입니다.
OpenSSL over OpenSSL을 .mcrypt
활발하게 개발되고 유지되고 있기 때문입니다.보안, 유지보수성 및 휴대성이 향상됩니다.둘째, AES 암호화/복호화를 훨씬 빠르게 수행합니다.하지만 PKCS7 패딩을 지정할 수 .OPENSSL_ZERO_PADDING
요하필키와 하려면 , 32 바이트의 바이너리 키를 지정할 수 있습니다.aes-256-cbc
더 명백함MCRYPT_RIJNDAEL_128
.
다음은 Mcrypt를 사용한 코드 예시입니다.
인증되지 않은 AES-256-CBC 암호화 라이브러리는 PKCS7 패딩으로 Mcrypt로 작성되었습니다.
/**
* 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');
}
}
다음은 Open을 사용하여 작성된 버전입니다.SSL:
/**
* 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
);
}
}
출처: PHP 코드에 MCRYPT라는 단어를 입력하는 것은 잘못된 것입니다.
저는 이것을 PHP 7.2.x에서 사용하고 있습니다만, 저는 정상적으로 동작하고 있습니다.
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;
}
}
다음 함수를 사용하여 해시를 인증합니다.
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;
}
}
예:
//create hash from user string
$user_password = $obj->make_hash2($user_key);
이 해시를 인증하려면 다음 코드를 사용합니다.
if($obj->varify_user($key, $user_key)){
//this is correct, you can proceed with
}
그게 다예요.
지적했듯이 사용자의 비밀번호를 복호화 가능한 형식으로 저장해서는 안 됩니다.리버서블 암호화는 해커가 사용자의 비밀번호를 쉽게 알아낼 수 있도록 합니다.이는 사용자의 계정이 다른 사이트에서 동일한 비밀번호를 사용할 경우 사용자의 계정을 위험에 빠뜨리는 것으로 확장됩니다.
는 랜덤 해시를 위한 합니다. - PHP는 단방향 해시 암호화입니다.password_hash()
★★★★★★★★★★★★★★★★★」password_verify()
해시는 자동으로 랜덤으로 판매되기 때문에 해커가 패스워드를 리버스 엔지니어링하기 위해 미리 컴파일된 패스워드 해시 테이블을 이용할 수 있는 방법은 없습니다.를 합니다.PASSWORD_DEFAULT
옵션과 향후 버전의 PHP는 코드를 업데이트하지 않고도 패스워드 해시를 생성하기 위해 보다 강력한 알고리즘을 자동으로 사용합니다.
Crypto 오브젝트를 번역할 수 있었습니다.
이전 데이터를 해독하려면 mcrypt를 사용하여 php 복사본을 가져옵니다.http://php.net/get/php-7.1.12.tar.gz/from/a/mirror,에 접속하여 컴파일한 후 ext/mcrypt 확장자(configure;make;make install)를 추가했습니다.php.ini에도 exponstion=mcrypt.so 행을 추가해야 할 것 같습니다.모든 데이터를 암호화하지 않고 중간 버전의 데이터를 구축하는 일련의 스크립트입니다.
openssl용 공용 키 및 개인 키 구축
openssl genrsa -des3 -out pkey.pem 2048 (set a password) openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout
(공개 키를 사용하여) 암호화하려면 openssl_seal을 사용합니다.제가 읽은 바로는 RSA 키를 사용하는 openssl_module은 키 길이보다 11바이트 적게 제한됩니다(http://php.net/manual/en/function.openssl-public-encrypt.php의 Thomas Horsten 코멘트 참조).
$pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem')); openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]); $encryptedPassword = base64_encode($sealed); $key = base64_encode($ekeys[0]);
원시 이진법을 저장할 수 있습니다.
복호화 방법(개인 키를 사용)
$passphrase="passphrase here"; $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase); // I base64_decode() from my db columns openssl_open($encryptedPassword, $plain, $key, $privKey); echo "<h3>Password=$plain</h3>";
추신: 빈 문자열("")을 암호화할 수 없습니다.
P.P.S. 이것은 비밀번호 데이터베이스용이지 사용자 확인을 위한 것이 아닙니다.
기능을 사용해야 합니다.
언급URL : https://stackoverflow.com/questions/41272257/mcrypt-is-deprecated-what-is-the-alternative
'programing' 카테고리의 다른 글
인덱스가 없는 느린 쿼리를 식별하려면 어떻게 해야 합니까? (0) | 2022.10.02 |
---|---|
onclick/onchange 행사에서 HTML체크 상자의 값을 추가하십시오. (0) | 2022.10.02 |
라라벨 블랭크화이트스크린 (0) | 2022.10.02 |
필드의 특정 값에 대한 테이블에 대한 고유한 제약 조건 (0) | 2022.10.01 |
python 함수 내부의 매개 변수 이름 목록을 가져오는 중 (0) | 2022.10.01 |