重要な注意事項:
次に進む前に、この記事では次のことを強調しておくことが重要です。非認証暗号化について簡単に理解できるようにすることを目的としています。堅牢なデータ保護を実現するには、パスワードの保存に業界標準の認証された暗号化ライブラリまたは bcrypt/argon2 を使用することを常に検討してください。
PHP 5.4 以降を使用している場合は、openssl_* 関数の使用を検討してください。暗号化操作用。これらは、ネイティブ サポートによる堅牢な暗号化機能を提供します。
OpenSSL の openssl_encrypt() 関数と openssl_decrypt() 関数は、データを暗号化および復号化するためのアクセス可能な方法を提供します。推奨される暗号化アルゴリズムは、128、192、または 256 ビットの AES-CTR です。
注意: mcrypt は非推奨であり、潜在的なセキュリティ リスクがあるため、使用しないでください。
暗号化と復号化を簡素化します。復号化プロセスでは、次のラッパー クラスを利用できます。
class UnsafeCrypto { // Encryption method (CTR mode) const METHOD = 'aes-256-ctr'; /** * Encrypts data using the specified key. * * @param string $message Plaintext message * @param string $key Encryption key * @param bool $encode Whether to encode the result * * @return string Ciphertext */ public static function encrypt($message, $key, $encode = false) { // Generate random IV $ivSize = openssl_cipher_iv_length(self::METHOD); $iv = openssl_random_pseudo_bytes($ivSize); // Encrypt using OpenSSL $ciphertext = openssl_encrypt($message, self::METHOD, $key, OPENSSL_RAW_DATA, $iv); // Concatenate IV and ciphertext if ($encode) { return base64_encode($iv . $ciphertext); } return $iv . $ciphertext; } /** * Decrypts data using the specified key. * * @param string $message Ciphertext * @param string $key Encryption key * @param bool $encoded Whether the message is encoded * * @return string Decrypted message */ public static function decrypt($message, $key, $encoded = false) { if ($encoded) { $message = base64_decode($message, true); if ($message === false) { throw new Exception('Encryption failure'); } } // Extract IV and ciphertext $ivSize = openssl_cipher_iv_length(self::METHOD); $iv = substr($message, 0, $ivSize); $ciphertext = substr($message, $ivSize); // Decrypt using OpenSSL $plaintext = openssl_decrypt($ciphertext, self::METHOD, $key, OPENSSL_RAW_DATA, $iv); return $plaintext; } }
上記のアプローチでは暗号化のみが提供され、データは改ざんに対して脆弱なままになります。これに対処するには、認証された暗号化スキームを実装します。
class SaferCrypto extends UnsafeCrypto { // MAC algorithm const HASH_ALGO = 'sha256'; /** * Encrypts and authenticates data using the specified key. * * @param string $message Plaintext message * @param string $key Encryption key * @param bool $encode Whether to encode the result * * @return string Encrypted and authenticated data */ public static function encrypt($message, $key, $encode = false) { // Split key into encryption and authentication keys list($encKey, $authKey) = self::splitKeys($key); // Encrypt using UnsafeCrypto::encrypt $ciphertext = parent::encrypt($message, $encKey); // Calculate MAC $mac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true); // Concatenate MAC and ciphertext if ($encode) { return base64_encode($mac . $ciphertext); } return $mac . $ciphertext; } /** * Decrypts and authenticates data using the specified key. * * @param string $message Encrypted and authenticated data * @param string $key Encryption key * @param bool $encoded Whether the message is encoded * * @throws Exception * * @return string Decrypted message */ public static function decrypt($message, $key, $encoded = false) { // Split key list($encKey, $authKey) = self::splitKeys($key); // Decode message if necessary if ($encoded) { $message = base64_decode($message, true); if ($message === false) { throw new Exception('Encryption failure'); } } // Extract MAC and ciphertext $hs = strlen(hash(self::HASH_ALGO, '', true), '8bit'); $mac = substr($message, 0, $hs); $ciphertext = substr($message, $hs); // Calculate expected MAC $expectedMac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true); // Verify MAC if (!self::hashEquals($mac, $expectedMac)) { throw new Exception('Encryption failure'); } // Decrypt message using UnsafeCrypto::decrypt $plaintext = parent::decrypt($ciphertext, $encKey); return $plaintext; } /** * Splits a key into two separate keys for encryption and authentication. * * @param string $masterKey Master key * * @return string[] Array of encryption and authentication keys */ protected static function splitKeys($masterKey) { return [ hash_hmac(self::HASH_ALGO, 'ENCRYPTION', $masterKey, true), hash_hmac(self::HASH_ALGO, 'AUTHENTICATION', $masterKey, true) ]; } /** * Compares two strings without leaking timing information * (PHP 7+). * * @param string $a * @param string $b * * @return bool */ protected static function hashEquals($a, $b) { if (function_exists('hash_equals')) { return hash_equals($a, $b); } $nonce = openssl_random_pseudo_bytes(32); return hash_hmac(self::HASH_ALGO, $a, $nonce) === hash_hmac(self::HASH_ALGO, $b, $nonce); } }
堅牢なセキュリティを実現するには、信頼できる暗号化ライブラリの利用を検討してください。
以上がOpenSSL を使用して PHP で単純な双方向暗号化を実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。