暗号とその実装は初めてです。私はAndroidアプリを設計しています。このアプリでは、ユーザーがパスワードを入力して暗号化されたデータを取得します。可能な解決策を調査した後、bcryptは次のように使用されました。
ユーザーがパスワードを入力-> bcrypt(パスワード)->暗号化用のキー
そしてそれをデータベースに次のように保存します:
SHA256(bcrypt(password))->ユーザーチェック(これはDBに保存されます)
私はAndroidでjBCrypt実装を使用することを計画していましたが、私が読んだものから、携帯電話でbcryptが非常に遅い( 分単位 モデルによっては 選択された電話/強度 =。)
ハッシュ手順を遅くすることがbcryptアルゴリズムの中核であることは知っていますが、ユーザーがモバイルデバイスでログイン/復号化するのに2分かかることは許容されませんが、通常のPCでの同じ操作には数秒かかります。ただし、スマートフォンで反復回数を減らすと、攻撃者はより高速なPCでブルートフォースを実行できます。問題のこれら2つの側面を調整するにはどうすればよいですか?
私はようやくAndroidでjBCryptを試すことにしました。さまざまなSOバージョンがインストールされているいくつかの携帯電話でテストしました。自宅のPCでもテストし、結果の表をまとめました。
適度に安全でありながら、10-11の作業係数は許容できるようです。結果を改善できるかどうかを確認するために、NDKソリューションの実装を試みます。 (テストを終了した場合は結果を掲載します。)
jBcryptは、Java実装です。Androidアプリは、ほぼJavaで記述されています Dalvik と呼ばれるほぼJavaの仮想マシン用です。
計算集中型のタスク、特に暗号化アルゴリズムの場合、Javaは、同等の最適化されたCコードと比較して、典型的な3倍のスローダウンを引き起こします:良いJava仮想マシンは- JITコンパイラ 、およびコードのパフォーマンスは、JVMが動作する必要がある制約によって制限されます(バイトコードからネイティブコードへの変換は高速でインクリメンタルである必要があり、メソッドは呼び出しごとに変換されます。結果はまだ ガベージコレクター に適している必要があります。CPUが提供する追加のオペコードからネイティブコードが恩恵を受けるいくつかの特定のケースでは、さらに減速が見られます。通常、大きな整数の計算(たとえば、RSAの場合)、CPUは「拡張」乗算(64x64-> 128)を提供する可能性があるため、Javaには128ビット整数型がないため、Javaコードは使用できません) 。
ハッシュ関数(「パスワードハッシュ」ではなく、単に「ハッシュ」)のコンテキストでのかなり完全な実験については、 sphlib を参照してください。Cで多くのハッシュ関数を実装するライブラリおよびJavaでは、「最適化における同様の取り組み」(ロット全体で同じ開発者)を使用し、さまざまなプラットフォームタイプでの対策を含みます。
Androidアプリ:
スマートフォンのCPUはPCのCPUほど高速ではありません。スマートフォンのCPUはギガヘルツの範囲に入る可能性がありますが、それでもx86のCPUよりもサイクルあたりの処理が少なくなります-スマートフォンのCPUの主な目的の1つはバッテリーの節約です。スマートフォンはラジオ活動をしている間、丸一日生きている必要がありますが、ラップトップはより大きなバッテリーを持つことができ、数時間稼働するだけで済みます。現代のスマートフォンは効率的ですが、デスクトップPCと比較するとまだギャップがあります。追加の3倍の係数を考えてみましょう。
Dalvikは必ずしも最良のJITコンパイラーではありません。生の筋肉が比較的不足しているということは、メソッドのJIT変換が高すぎるため、JITが最も複雑な最適化戦略を適用できないことを意味します。
最大Android 2.1(付属)、DalvikにはJITがありません。これは、他の回答が示唆する最悪のスローダウンです。Android 2.1(およびそれ以前)では、Javaバイトコードが解釈され、ネイティブコードに変換されません、これは重い追加費用が発生します(たとえば、JITコードよりも10倍から20倍遅くなります)Android 2.2以降にはJITがあります。
PBKDF2に切り替えても、画像はあまり変わりません。 PBKDF2 を使用する場合は、SHA-512ではなくSHA-256(またはSHA-1)を使用してください。これは、スマートフォンのCPUがARMベースであり、64ビットの算術演算で非常に不快になるためです。そのSHA-512は大きく依存しているため、コードの速度が低下します-攻撃者はPCを使用しており、朝食に64ビットの操作を実行するため、同じ速度低下は発生しません。
概要:bcryptは、Android 2.1(および以前のバージョン)では非常に遅くなります。 Android 2.2、PCほど高速ではありませんが(たとえば、5〜10倍遅い)PBKDF2、scrypt ...この画像を大幅に変更しないでください。
これはすべて、bcryptのパフォーマンスについて述べられています。暗号化とパスワード検証の両方にbcryptから派生したシークレットを適切に使用する方法については、コメントしませんでした。実際、「何か」を保存してパスワードを検証する場合、暗号化に使用するパスワードから派生したキーに近づきすぎて「何か」を保存することはありません。
「暗号的に妥当な方法」の1つは、bcryptまたはPBKDF2(saltと反復などすべて)を使用してパスワードハッシュを計算し、出力を取得してexpand鍵導出関数 あなたのニーズに十分な鍵素材に。あなたのコンテキストでは、bcrypt出力を取得し、それをSHA-256でハッシュします。これにより256ビットが生成されます。最初の128ビットを「パスワード検証トークン」としてデータベースに保存します。 otherの半分を暗号化キーとして使用します。
PBKDF2は、KDFであるため、このプロセスを少し単純にします。そのため、追加のハッシュを必要とせずに、すぐに256ビットのパスワードからの出力を要求できます。一方、bcryptの出力サイズは192ビットに固定されているため、ニーズに十分ではない可能性があります。
私も同じ状況にあります。 Androidで快適に_PBKDF2
_を使用できるはずです。私はモバイルデバイスでscryptをテストしていませんが、生成時にscryptよりもパフォーマンスが優れているとは思いませんハッシュ。それとは別に、_SHA-256
_を取る代わりに、_PBKDF2
_を_SHA-256 HMAC
_と一緒に使用するだけで簡単にできます。PBKDF2では、ハッシュの出力長を設定することもできます(できれば 代わりにPBKDF2の出力でHKDF-Extractを使用 )なので、通常はSHA-256(pbkdf2(pass))
の取得は多すぎます。
ただし、別のPBKDF2(PKBDF2(pass))
を取得してアプリケーションに保存することをお勧めします。これにより、ユーザーがパスワードを入力し、PBKDF2を使用してキー(内部_PBKDF2
_)を生成したときに、復号化する前にキーが実際に正しいキーであることを確認できます。
そう:
password
=>鍵の生成に使用(秘密、保存しないでください)PBKDF2(password)
=>暗号化されたデータを復号化するためのキーとして使用されます(秘密、保存しないでください)PBKDF2(PBKDF2(password))
=>復号化を試みる前にキーを検証するために使用されます(秘密ではなく、アプリケーション内に保存できます)複数のプラットフォーム間でKeePassのようなパスワードマネージャーを構成する場合と同じジレンマです。どのプラットフォームに重点を置いていますか?
なぜなら、bcrypt
は、予測可能な人間のパスワードをステップスルーするという、さもなければ迅速なプロセスを拡張するために使用される主要な派生関数だからです。人間のパスワードの問題を回避する場合、パフォーマンスの問題を回避します。
セッションキーによって管理されるデータにアクセスできます。セッションキーを再生成する必要がある場合(たとえば、24時間ごとまたは電話の再起動後)、bcrypt(password)
またはbcrypt(password + master key)
が使用されます。セッション中、セッションキーは速度を上げるために非暗号化パスワード暗号化によってのみ保護されます。
または、bcrypt()
と関連する遅延をそのままにして、プロセスのユーザーインターフェイスエクスペリエンスを改善することもできます。
復号化プロセスがCPUキャップのバックグラウンドタスクとして実行され、フォアグラウンド通知により、復号化ステータスが進行状況バーとパーセンテージでマークされます。アプリケーションの中心的な目的がセキュリティである場合、ほとんどのユーザーはそれを受け入れられます。実際、アプリケーションがmoreであると超高速の復号化よりも安全だと感じさせるかもしれません。
もちろん、アプリケーションの主要な目的がセキュリティに関連していない場合は、bcrypt()
のセキュリティ強化と関連するモバイルデバイスの遅延が本当に必要かどうかを再度確認することをお勧めします。
ご承知のとおり、あなたには相反する要件があります。オフラインのクラッカーから身を守るのに役立つようにbcryptをできるだけ高くすると同時に、比較的低電力のデバイスを使用している正当なユーザーにとっては法外なコストをかけないようにします。
アプローチには2種類あり、どちらも追求する必要があります。コスト係数(または反復)を調整し、最良の(最小の)攻撃者/防御者比率を得るハッシュ実装を見つけます。
パスワードクラッカー、Bitweisel について語る 彼が「攻撃者/防御者比率」(ADR)と呼ぶもの。 Defenderがbcrypt、scrypt、またはPBKDF2の実行がスタックしている場合、たとえば、攻撃者が利用できる速度の1/10である場合、ADRは10対1です。この状況では、Defenderはそれほど強力ではないデバイスであり、これらのシステムではうまく機能しないコンパイラでスタックしている可能性もあります。
Androidがあなたを正しい方向に向けるのに十分役立つとは思いませんが、その動作環境に合わせて慎重に最適化されたものを探す必要があります。それがbcryptかPBKDF2かにかかわらず、私は知りませんわかりません。繰り返しますが、絶対的な速度については(まだ)心配していませんが、環境と攻撃者の速度の比率については心配しています。
たとえば、HMAC-SHA512を使用するPBKDF2は非常に遅い可能性がありますが、SHA512の使用により、攻撃者がGPUを使用してクラッキングすることができない場合は、その価値があるかもしれません。そのため、速度が遅くても、実際に失われたADRが発生する可能性があります。
ocl-hashcat + (高速のクラッカー)のコピーをインストールしてデスクトップコンピューターでクラッキングレートをテストし、さまざまなハッシュ方式のADRを判断するための方程式の側面を確認します。
PBKDF2、bcrypt、およびscryptはすべて、作業係数を設定できます。 「bcryptに2分かかる」という文言は、コストパラメータを1つ(1分かかる)または2つ(30秒)削減することで修正できます。 PBKDF2では、線形にスケーリングする反復を設定します。
したがって、最高のADRを実現するアルゴリズムと実装を見つけたら、ユーザーが許容する時間を決定するだけです。 2秒の場合は、コスト係数または反復を調整して、その2分を取得します。