@rqLizardで提案されているように、代わりにopenssl_encrypt
/ openssl_decrypt
PHP関数を使用できます。これにより、Rijndael暗号化とも呼ばれるAES(高度暗号化標準)を実装するためのより優れた代替手段が提供されます。
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
vs aes-256-ctr
)がより明確になります。
OpenSSLは、mcryptのNULLバイトパディングではなく、CBCモードでPKCS7パディングも使用します。したがって、mcryptはOpenSSLよりもコードをOracle攻撃のパディングに対して脆弱にする可能性が高くなります。
最後に、暗号文(Encrypt Then 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();
}
}
明確にするために、2つの暗号化は異なるブロックサイズと異なる暗号化データを使用するため、上記の変更は真の変換ではありません。さらに、デフォルトのパディングは異なり、MCRYPT_RIJNDAEL
非標準のnullパディングのみをサポートします。@zaph
追加のメモ(@zaphのコメントから):
- Rijndael 128(
MCRYPT_RIJNDAEL_128
)はAES と同等ですが、Rijndael 256(MCRYPT_RIJNDAEL_256
)は AES-256ではありません。これは、256が256ビットのブロックサイズを指定しているのに対し、AESは1つのブロックサイズ(128ビット)しか持たないためです。したがって、基本的に256ビット(MCRYPT_RIJNDAEL_256
)のブロックサイズのRijndaelは、mcrypt開発者の選択により誤って名前が付けられています。@zaph
- ブロックサイズが256のRijndaelは、128ビットのブロックサイズを使用する場合よりも安全性が低くなる可能性があります。第2に、AESが一般的に利用可能である一方で、ブロックサイズが256ビットのラインダールでは利用できないという点で、相互運用性が妨げられています。
Rijndaelのブロックサイズが異なる暗号化では、異なる暗号化データが生成されます。
例えば、MCRYPT_RIJNDAEL_256
(に相当しないAES-256
)256ビットおよび鍵に渡さに基づいて、キーのサイズの大きさとラインダールブロック暗号の異なる変異体を定義する。ここで、aes-256-cbc
ラインダールは、のキーサイズ128ビットのブロックサイズであります256ビット。したがって、mcryptは数値を使用してブロックサイズを指定するため、異なるブロックサイズを使用して完全に異なる暗号化データを生成します。OpenSSLは数値を使用してキーサイズを指定します(AESには128ビットのブロックサイズが1つしかありません)。つまり、基本的にAESはRijndaelであり、ブロックサイズは128ビット、キーサイズは128、192、および256ビットです。したがって、OpenSSLではRijndael 128と呼ばれるAESを使用することをお勧めします。
password_hash
検証しpassword_verify
ませんか?