Crypt()関数は、パスワードの暗号化または検証にPHPを使用する場合、特にPassword_hash()とPassword_verify()が初期には利用できなかった場合、典型的な選択です。ただし、多くの開発者はCrypt()を使用すると混乱する問題に遭遇します。同じコードが異なるオペレーティングシステムまたは環境で実行されますが、結果は一貫性がなく、セキュリティリスクにつながる可能性があります。この記事では、この現象の背後にある理由と、これらの「ピット」を回避する方法について詳しく説明します。
PHPのCrypt()関数は、片道で文字列を暗号化するために使用されます。そのコアロジックは、提供された「塩値」(塩)に基づいて使用する暗号化アルゴリズムを選択することです。この塩値は、アルゴリズムを制御するだけでなく、暗号化プロセスにも参加します。例えば:
echo crypt('password', '$1$mysalt$'); // 使用 MD5 暗号化
異なるプレフィックスは、異なる暗号化アルゴリズムを表します。
$ 1 $とは、 MD5ベースの暗号化を使用することを意味します
$ 2a $ 、 $ 2Y $ 、 $ 2ber $は、 Blowfish(bcrypt)を使用することを意味します
$ 5 $は、 SHA-256を使用することを意味します
$ 6 $は、 SHA-512を使用することを意味します
Crypt()はPHPの標準関数ですが、その実装は基礎となるシステム(LIBC)のCライブラリに依存しています。つまり、PHPはシステムレベルのCrypt()関数のみをカプセル化します。このため、異なるオペレーティングシステム間でcrypt()の動作に大きな違いがある可能性があります。これは次のように示されています。
すべてのシステムが同じ暗号化アルゴリズムをサポートするわけではありません。例えば:
MACOSシステムの古いバージョンの中には、従来のデスコランスのみをサポートしています。
Linux(特にGNU LIBCを使用したシステム)は通常、MD5、SHA-256、SHA-512、ブローフィッシュなどをサポートします。
Alpine Linuxは、MUSL LIBC、特にBcryptによるいくつかのアルゴリズムに対して不完全なサポートを持っています。
これは、$ 2Y $のプレフィックス暗号化を使用してubuntuでうまく実行されるスクリプトが、高山容器の*0または*1 (故障を示す)を直接返すか、間違った形式でハッシュ文字列を返すことができることを意味します。
一部のシステムでは、同じアルゴリズムがサポートされている場合でも、返された暗号化の結果はわずかに異なる形式を持つ可能性があります。例えば:
$hash1 = crypt('password', '$2y$10$1234567890123456789012'); // 存在する Linux 優れた
$hash2 = crypt('password', '$2y$10$1234567890123456789012'); // 存在する macOS 優れた
上記の2行のコードの$ hash1と$ hash2は異なる場合があり、システムの異なるバージョンのパフォーマンスでさえ異なります。これは、クロスプラットフォームの展開の潜在的なリスクです。
適切な塩値が提供されていない場合、 Crypt()の動作はシステムによって決定されます。
従来のDesを使用しています
デフォルトでハッシュアルゴリズムを使用します
直接戻ることができませんでした
これは、アルゴリズムと塩値がコードで明示的に指定されていない場合、プログラムの動作はシステムの実装に完全に依存し、非常に信頼できないことを意味します。
開発者は、LaravelフレームワークでCrypt()を使用して、ユーザーパスワードを手動で暗号化し、データベースに保存しました。コードは、ローカルUbuntu開発環境で正常に実行されます。ただし、高山ベースのDockerコンテナに展開した後、ユーザーのログインは常に失敗します。その理由は、AlpineのCrypt()が使用する$ 2Y $ BCRYPTアルゴリズムをサポートしておらず、生成されたハッシュが違法であるためです。
これらの互換性と携帯性の問題を回避するには、推奨されます。
これらの機能は、PHP 5.5以降導入されており、システムのCrypt()動作に依存することなく、基礎となる実装でより適切にカプセル化されています。サンプルコード:
$hash = password_hash('mypassword', PASSWORD_BCRYPT);
if (password_verify('mypassword', $hash)) {
echo '正しいパスワード';
}
この方法は、最適なアルゴリズムの自動選択をサポートするだけでなく、現在最も推奨されるプラクティスである暗号化パラメーター(コストなど)アップグレードを処理します。
そして、ターゲット環境がアルゴリズムをサポートしていることを確認してください。
$salt = '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(16))), 0, 22);
$hash = crypt('mypassword', $salt);
展開前にターゲットサーバーで生成と検証プロセスをテストして、環境の違いを避けてください。
構成ファイルまたは環境変数を使用して暗号化ポリシーを制御することを検討してください。これにより、さまざまな環境でのポリシーの調整が容易になります。
Crypt()はPHPで長い間存在していましたが、そのプラットフォーム依存関係により、特に最新のアプリケーションでのクロスプラットフォームの展開が標準である場合、信頼性の低いオプションになります。 Crypt()で遭遇する「ピット」は、実際にはシステム間互換性の現れです。最良の解決策は、 password_hash()など、よりモダンで安定したAPIを使用することです。
まだ古いシステムを維持している場合、または特別なニーズでCrypt()を使用している場合は、すべての詳細をテストおよび検証して、すべての動作環境が暗号化アルゴリズムを一貫してサポートすることを確認してください。
さらにデバッグするには、アクセスできます。
https://m66.net/crypt-debug-tool (ツールページが展開されていると仮定)
システム全体の別の暗号化動作をプロジェクトの「時限爆弾」にしないでください。