web-dev-qa-db-ja.com

文字列を安全にハッシュ/トークン化する方法

私が取り組んでいるシステムは、顧客のアカウント番号を入力として受け入れ、それに基づいてトークンを生成する必要があります。アカウント番号自体のプレーンテキストを保存することは許可されていないため、トークンの目的は次のとおりです。

  1. 口座番号に戻すことはできません
  2. データベース内のアカウントメタデータレコードを検索して一意に識別するために使用できます

アカウント番号はクレジットカード番号に似ています。それらは16桁の長さの数値ストリングです。最初の4文字は定数です。最後の文字は計算可能なチェックディジットです。つまり、入力セットの実際のサイズは11文字の数値文字列、つまり99,999,999,999の可能な順列です。

以下の方法について考えました。 hashは、高い反復PBKDF2、bcrypt、またはargon2などの十分に遅い安全なハッシュを意味し、encryptはAES256を意味すると仮定します。

1。プレーンハッシュ

hash(account_num)

このアプローチは単純ですが、ブルートフォースを介して簡単に元に戻すことができ、レインボーテーブルに対して脆弱です。

2。アカウントごとのソルトハッシュ

hash(salt + account_num)

このアプローチはレインボーテーブルの脆弱性を修正しますが、入力セットのサイズが制限されているため、ブルートフォースを使用して簡単に元に戻すことができます。

3。 Global Pepperで暗号化されたユーザーごとのソルトハッシュ

encrypt(hash( salt + account_num ), pepper)

これは Dropboxのパスワード保存メカニズム に基づいています。ブルートフォースを介して元に戻すには、暗号化されたblobと暗号化キーの両方を漏らす必要があります。ただし、同じキーで同じ値を2回暗号化すると、出力BLOBが異なるため、データベースからアカウント番号でアカウントを選択できなくなります。

4。ハイブリッドアプローチ

  1. アカウント番号の下4桁をプレーンテキストで保存します。
  2. アカウント番号全体を、ペッパー暗号化されたソルトハッシュとして保存しました。
    1. ハッシュ暗号化に AWS KMS を使用して、キーの漏洩の可能性を減らします。

これが達成すること:

  1. アカウント番号の下4桁を使用してアカウントを検索できます。数千のアカウント番号を確認した結果、この選択では1〜3の可能なアカウントが返されます。
  2. 可能なアカウントの一致ごとに繰り返します…
    1. アカウントのアカウント番号ハッシュを復号化します。
    2. 復号化されたハッシュを入力アカウント番号と比較します。
    3. 一致するハッシュが見つかる(このアカウント行を使用する)か、アカウントが不足する(新しいアカウント行を作成する)と、すぐに反復を停止します。

私の質問:アプローチ4は実際に意味がありますか?それが提供する追加のセキュリティのために、それは過度に複雑ですか?私が考えていない欠陥がありますか?何よりも、この問題を解決する簡単な方法はありますか?

5
crgwbr

アカウント番号はクレジットカード番号のようです。便利なことに、5年前のグラフィックスカードは3日間でソルト付きソルト付き10桁キーを使い果たす可能性があることを知っています。つまり、PBKDF(4096)ハッシュを元に戻すのに平均36時間かかります。見た目は良くありません。

トランザクションとペアにするランダムなナンスを生成し、そのナンスをカードに関連付ける方がはるかに優れています。

6
Jeff Ferland

あなたは単に [〜#〜] hmac [〜#〜] を使用することができます:HMACは2つの入力、メッセージと暗号化キーを持ち、基本的にハッシュであるメッセージ認証コードを生成します(例えばMACをメッセージまたはキー、あるいはその両方に戻すことはできません)。したがって、あなたのケースでは:

token = hmac(account_num, key)

HMACは、キーを明らかにする可能性のある攻撃から保護するために特別な方法で構築されています。これはよく理解されている暗号プリミティブです。

キーを知らなければ、アカウント番号を取得するためのトークンへのブルートフォース攻撃は現実的ではありません。 OTOH、あなたにとって、鍵を知っているなら、口座番号をトークンに変えるのは簡単です。

もちろん、アカウント番号のセキュリティはキーのセキュリティにかかっています。そのため、攻撃者がキーとトークンのリストを紛失した場合は、ブルートフォース攻撃のためにアカウント番号を開いたことになります。しかし、あなたのアイデア番号4は同じ問題に悩まされています。

鍵の管理について検討することをお勧めします。そのため、鍵が危険にさらされた場合でも簡単に鍵を変更できます。

1
Out of Band

デザインはOracle攻撃に対して安全ではありません。システムに入力されたクリアテキスト番号により、同じトークンが生成されます。攻撃者はブルートフォースハッシュの代わりに、システムを使用して一連の推測を行うだけでよく、オラクルは彼に正しいか間違っているかを知らせます。

割り当て方法について何も定義せずに、これらの「口座番号」を呼び出しました。それらが本当にランダムである場合、はい、10,000,000,000の可能な推測があります。しかし、私たちが知っているように、真のランダムは手に入れるのが難しいです。そして、それらが可能な値を超えて暗号的にランダムに配置されていない場合、攻撃者は巨大なベビーベッドを獲得します。

最初にクレジットカードを使用して、ベビーベッドでクレジットカードを破る方法の実例を示し、次に、この例を他のシステム、おそらくあなたのシステムで悪用する方法を示します。

銀行が発行した口座番号を検討してください。各カードは、銀行識別番号(BIN)と呼ばれる最初の6桁で銀行を識別します。統計的には、顧客はクレジットカードの組み合わせを持っていますが、それらのかなりの部分(13%としましょう)は、使用されている店舗の近くの銀行によって発行された可能性が高いです。それが私たちのベビーベッドです。したがって、カードの末尾が1234のハッシュ値が表示され、ローカル銀行のBINが444444であることがわかっている場合、この画像のすべての欠落している数字を総当りします:4444 44?? ???# 1234#文字は、チェックディジットアルゴリズムを使用して、欠落している1つの数字を推測から回復します。たった100,000回の推測で、システムで有効なカードを推測する可能性は13%です。

これをあなたのカードに拡張しましょう、そしてあなたはあなたのためにそれらを印刷するいくつかのカードベンダーを持っています。今日100,000枚のカードを注文し、来月に100,000枚のカードを再注文すると、ベンダーは、新しいランが前のランと同じカード番号を発行しているかどうかを知る方法がない場合があります。したがって、衝突を避けるために、彼はカード番号の最初の6桁に6桁の一意の番号を付け、各バッチが他のすべてのバッチと異なることを確認します。 (これは、ギフトカードを印刷するベンダーにとって非常に一般的な動作です。)これは、BIN番号が数字を推測可能にする際に行うことと同様の効果があります。クレジットカードに対して約50,000のBINが発行されていますが、印刷したカードの可能なバッチの数がわからないため、状況によってはさらに悪化する可能性があります。

覚えておいてください、攻撃者は本のバランスをとろうとはしていません。彼は泥棒として成功するために完璧を必要としません。 1人から盗むために、特定のトークン番号を解読する必要はありません。彼がしなければならないことはあなたのデータベースに対して力ずくであり、彼のために働く1つ以上の数を見つけることです。彼がうまく推測すればするほど、彼はより多くの利益を上げますが、カード盗難での成功は彼にとっての勝利です。

代わりに、使い捨てトークンシステムを検討してください。攻撃者が4444 4400 0001 1234を2回置くと、システムから2つの異なるトークンを取得します。これは、システムが潜在的な攻撃者にOracleを提供しないようにする唯一の方法です。

1
John Deters