対称鍵暗号化を使用して、PHPでデータを適切に暗号化するにはどうすればよいですか?私はメッセージMと秘密のSを持っています。私は、通常の誤りを犯さずに暗号を適切に使用するソリューションを探しています。特に、ソリューションは認証された暗号化を使用し、IVを適切に選択し、適切な低速ハッシュを使用してシークレットSから実際の暗号化キーを生成する必要があります(Sが実際の暗号化キーではなくパスワードである場合)。
PHPこの目的のためのコードを提案できますか?
私の動機:私はPHPプログラマーにこれを行う方法についての良いアドバイスではなく、良いアドバイスを与えたいと思います。 StackOverflowに関するこの質問 は本当の失望です:ひどく悪い非常に支持された回答がいっぱいです(ECBモードの暗号化?IVの繰り返し?認証なしの暗号化?)正しい答えを理解しましょう-正しく機能するコードスニペット-そして、StackOverflowでその壊れたウィンドウを修正します。PHPプログラマーの精神に沿って、私はコードのスニペット(可能な限り設定します。アルゴリズムや概念についてのアドバイスだけでなく、説明や制限/警告の説明を含めることもできます)。
PHPこの目的のためのコードを提案できますか?
優先順に。
Libsodiumについて聞いたことがない場合は、 今すぐ確認してください 。私は非常に強く 可能であればlibsodiumの使用を推奨 します。
これらの手順 を使用すると、コンピューターにlibsodiumとPECL拡張機能をインストールできます。その電子書籍の残りの部分では、特定のコンポーネントの使用方法を理解できるはずであり、たくさんのサンプルコードが含まれています。 PHP暗号化で非専門家を指す暗号化の出発点が必要な場合、libsodiumは今日入手可能な最良のものです。
秘密鍵で認証された暗号化については、 電子書籍のこの章 を参照してください。
(免責事項:私はHaliteを書きました。)
Libsodiumのすべての機能と、次のようなインターフェース:
use \ParagonIE\Halite\Symmetric\Crypto as Symmetric;
$key = KeyFactory::loadEncryptionKey('/path/to/key/file');
$ciphertext = Symmetric::encrypt($plaintext, $key);
確認してください: paragonie/halite 。
Defuse SecurityはGithubの暗号化*ライブラリを defuse/php-encryption で公開しました。
暗号化とは、実際には認証された暗号化を意味します。
免責事項:私はこのライブラリの共著者の1人ですが、バージョン2のリライト(バージョンのタグ付けとファイルを安全に暗号化/復号化するためのストリーミングインターフェイスを含む)が完了するまで、ほとんどの貢献は行われません。
私はそれを個人的に監査していないため、 これ 最後にすることをお勧めしますが、それはis Zend Frameworkの一部であり、PHPセキュリティエキスパートはその品質を証明しています。すでにZend Frameworkを使用している場合は、それを使用してください。
更新:私が最初にこの回答を書いたので、Zend\Crypt\PublicKey\Rsa
に問題を発見しました( ZF2015-10 aka CVE-2015 -75 )。ただし、対称鍵暗号化の実装は安全であるように見えます。
D.W.、答えはコードスニペットよりもデザインパターンの形で来る必要があります。これの1つの理由は、PHPおよびPHPコミュニティーを備えた最先端の技術です。「正しく理解する」ための貴重な例がいくつかあります。平均PHP開発者。
この困難の例:
コードにmcryptを入力している場合は、それを間違っています :mycryptは、前回調べた時点では維持されておらず、事実上破棄されています。ただし、mycryptは、/ dev/urandomから乱数を取得できる拡張機能です。これは、Linuxベースのサーバーで乱数を取得する正しい方法のようです。
乱数を安全に生成する方法 :PHPのopenssl拡張機能が間違っています。 opensslは新しい開発に使用する拡張機能ですが、すべてが正しく機能するわけではありません。
これにより、独自の暗号化コードを作成する必要があるという結論に達します。専門家なら誰でも「やめろ!」と言うでしょう。しかし、PHPを使用すると、代替手段がない可能性があります。コミュニティが提供する暗号化パッケージがありますが、同じ問題です:そのパッケージが「正しく機能する」かどうかをどうやって知るのですか?
もう1つの理由は、PHPでは特定の状況のために問題が発生するためです。安全でないネットワークを介してハッシュされたパスワードを保存しようとしていますか?プロトコルの1つのセットが最適な場合があります。
サーバーとモバイルアプリ間のWebサービスを保護しようとしていますか?別のアプローチがより適切な場合があります。 (たとえば、アプリが攻撃者によってリバースエンジニアリングされる可能性がある場合、アプリが秘密キーを秘密にしておくことに依存できますか?)
参考までに、対称秘密鍵暗号化で検討した手順は次のとおりです。 PHP 5.3、/ dev/urandomにアクセスするためのmcrypt拡張、およびaes-256-cbcのopensslを使用しています。
すべてが秘密鍵を秘密にしておくことに依存していることを認識してください。秘密鍵をリモートクライアントソフトウェア(または通信のいずれかのエンドポイント)から抽出できる場合、暗号化されたテキストへのアクセス権を持つ攻撃者はあらゆるものを読み取り、偽のメッセージを挿入できます。
たとえば、HTTPS経由で送信すると、一部の攻撃に対するセキュリティが不十分になることを認識してください。たとえば、攻撃者はアプリをインストールし、アプリとの間で送受信される復号化されたHTTPSトラフィックを観察できます。
つまり、暗号化が動作している環境を理解し、どのような攻撃を考慮する必要があるかを見つけます。
暗号化の両側で同じ共有秘密鍵が必要です。両方の側がキーを取得する必要があり、キーの盗難、見られ、リバースエンジニアリングなどが行われないようにする必要があります。
私は(確かに十分な専門知識はありませんが)秘密鍵を正確に256ビット(AES-256の場合)にハッシュすることは正しい習慣であると信じています。たとえば、hash( 'sha256'、$ secretKey)を使用して256ビットの鍵を作成します。暗号化/復号化機能にフィードします。つまり、単純なASCII text as-isには、秘密鍵として直接使用するのに十分なエントロピーがありません。したがって、正しい数を作成する(または切り捨てられる)ハッシュ関数を使用しますバイトの。
AESの場合、128ビットの入力ベクトルが必要です。この入力ベクトルは、暗号化/送信ごとに異なる必要があることを理解してください。固定入力ベクトルを使用したコードサンプルが多すぎます。ランダムバイトには、MCRYPT_DEV_URANDOMモードでmcryptを使用します。
The Doom Principle * thanks @ mti2935)は、メッセージの整合性を検証する前に受信メッセージに対して暗号操作を実行すると、必然的にDoomにつながることがあると述べています。 1つのベストプラクティスは、HMACを使用することです(次のポイント)。
(リンクを投稿するのに十分な評判がありません):暗号化は認証ではないことを理解してください。 HMACは、メッセージが変更されていないことのみを確認できます。また、メッセージがあなたの秘密鍵を持っている誰かによって送信されたことを確認します。その事実を十分な認証であると見なす場合と見なさない場合があります。
HMACは、復号化関数へのすべての入力をカバーする必要があります。これは、暗号化されたメッセージと入力ベクトルの両方を意味します。使用する復号化アルゴリズムを示す識別子がある場合、それもHMAC計算の一部である必要があります。それ以外の場合、攻撃者はそのインジケーターを変更して特定の攻撃を仕掛ける可能性がありますが、HMAC検証はクリーンなままです。
上記は、「暗号化してからHMACを使う」という考え方の考え方です。特にブルース・シュナイアーを含む対立する学派があります。ブルースの推論は、「暗号化してからHMAC」を正しく取得することは特に難しいということです。ブルースがそれが特に難しいと言うなら、それは特に難しいです。
私の要点は、暗号化とHMACを行う場合、どのような順序で行っても、正しく取得するのが非常に難しいものを見つけ出し、正しく一致したことを確認することです。
暗号化コードを記述しないでください さらに考察すると、例としてロール独自のコードを公開しない方がよいでしょう。 libsodiumを使用します。