web-dev-qa-db-ja.com

MySQLにユーザーのパスワードとソルトを安全に保存するにはどうすればよいですか?

だから、私はSOで、パスワードを「塩」と一緒にハッシュすることになっていることを知りました。(記事は ここで見つけることができます および here 。)

これがコードです:

$password = 'fish';

/* should be "unique" for every user? */
$salt= 'ABC09';

$site_key = 'static_site_key';

hash_hmac('sha1', $password . $salt, $site_key);

次のように、$password$saltの両方をMySQLに保存する必要があります。

+---------+--------+----------+-------+
| user_id |  name  | password |  salt |
+---------+--------+----------+-------+
|    1    | krysis |  fish**  | ABC09 |
+---------+--------+----------+-------+

** fishはもちろんハッシュされ、プレーンテキストで保存されません。

そして、ハッカーや誰もが塩を知っているので、この方法で実際にそれを行うのが理にかなっているのではないかと思っています。したがって、彼らがパスワードを解読し、それがfishABC09であることがわかると、パスワードがfishであることが自動的にわかりますか?または、パスワードがデータベースに保存されていないため、secret_keyを知らないため、パスワードを解読することが「できない」のでしょうか。

意味がわからなくてごめんなさい。私はいつもパスワードにsha1を使用していました。今日、saltの追加について説明した記事を見つけました。

16
user317005

パスワードを正しく保存することについての良い記事があります。たとえば、次のいずれか: パスワードの保存-正しく完了!

ユーザーごとに異なるソルトを使用する必要がありますが、ソルトを個別に保存する必要はありません。 別のスレッド で同様の議論を参照してください

ちなみに、おそらくあなたはsha1を使うべきではありませんが、例えば代わりにsha256またはsha512何かより強力なもの(少なくとも悪い宣伝を避けるため)。これに関しては良い答えがあります: ソルトSHA512と比較したソルトSHA1の安全性

8
kto

レインボー/辞書攻撃、ソルトパスワード-異端者アプローチ

パスワードをデータベースに保存しないでください。独自の認証メカニズムをロールバックしないでください-間違いなく間違います。価値のあるものにはKereberosを使用してください。そうでなければ、良い提案はありません。

しかし、この質問は私の頭蓋骨にしばらくぶつけられており(編集を参照)、異端的な見方をしたいと思います。

レインボーテーブルは、ルックアップメカニズム(チェーン)の使用方法が原因で、いわゆる辞書ですが、辞書攻撃にすぎません。何百万もの辞書の単語と一般的なパスフレーズが最初にハッシュされ、盗まれたハッシュされたパスワードと比較するために使用されます。

これは、md5ハッシュを使用し、ソルトを使用しないNT4パスワードプロセスに適しています。しかし、ハッシュする前にソルトをパスワードに追加すると、レインボーテーブルは役に立たなくなります。「mypass」のmd5ハッシュを探す代わりに、「mypass-random-string_of-letters」を事前計算する必要があります。

誰かが使用する塩を推測することは不可能であるため、塩漬けにより、レインボーテーブルは一般的なものになり、水中で死んだサーバーソリューションに対してどこでも使用できます。

だが ...

これは1つの使用例にすぎません-確かに大きな脅威であり、確実に防御する必要があります。しかし、塩には問題があります。ユーザーが次にログインするときに認証するときのために、saltを保持する必要があります。ユーザーはプレーンテキストを(ssl経由で)送信し、saltとハッシュを追加して、データベースに格納されているハッシュに比較します。しかし、パスワードと一緒にソルトを保持しないと、それを行うことはできません。エラー...ログインなし

しかし、NT4パスワッドをクラックするように設計されたテーブルを通り過ぎる人々を守るだけではありません。ユーザーを個別に保護することになっています。

ソルトは、パスワードに2つの要素の防御を追加します。ハッシュを使用しても、攻撃者はソルトをクラックする可能性があるため、ソルトが必要になります。しかし、標準的なアドバイスは、その2つの要素の防御を放棄するだけです。おそらくその合理的ですが、私は確信していません。

これの背後には少し数学があります。通常のアドバイス(RSAからも提供されます-ftp.rsa.com/pub/pkcs/pkcs-5v2/pkcs5v2-0.pdf)は64ビットのソルトを作成し、ハッシュされたパスワードで保存します。この方法では、ソルトを使用してハッシュを再作成し、ハッシュを元に戻すことによってパスワードを再確認できますが、これはほぼ不可能です。

注意-私はここで間違っている可能性があります...

「次の不可能な」ビットは単純な数学から来ています。

62桁の文字(文字、大文字、小文字、数字)を含む8桁のパスワードを想定しましょう

これは62 ^ 8の組み合わせ、つまり2億兆を少し超えます。

これを総当たりにするために、ハッシュを直接計算することで(つまり、私のソルト固有のレインボーテーブルを作成する)、62 ^ 8/2の後で衝突が発生するはずです。たとえば、毎秒100ハッシュの場合、約1200万日かかります。はい。

OK、ハッシュをパスワードと一緒に保存することでさえ、ハッシュを見つける作業は非常に実行不可能になります。

ただし、上記にはいくつかの前提があります。まず、パスワードは62 ^ 8の範囲のランダムな選択です。実際には、ほとんどのパスワードははるかに弱いです-Rainbowテーブルは実際には62 ^ 8のすべての可能性に基づいているわけではありません-それらは辞書から構築されており、長年にわたって見つかった実際のパスワードテーブルです。

したがって、62 ^ 8である代わりに、検索スペースは本当に小さくなります。どれくらい小さい?はパスワードの「強さ」に依存します。

英語で約250,000〜750,000の単語があります(http://oxforddictionaries.com/page/93)。単純なケースとして500,000を取り上げます。次に、適用できるバリエーションを取ります-数字を追加し、年を追加し、母音を数字に変換します。これにより、1ワードあたり3つの新しい単語、または200万の可能なパスワードが得られます。

100 /秒で200万ハッシュを生成すると、20,000秒または5時間になります。これは、どのラップトップの範囲でも十分です。

したがって、特定のユーザー(root、admin、spolskyなど)がターゲットになっている場合、ソルトとパスワードを保存すると、すぐにクラッキングが可能になります。

ソルトをパスワードから遠ざけると、解読が難しくなります。数学的にではなく、ソルトとパスワードを取得するのが難しくなります。プレーンテキスト、ユーザー名、ハッシュを受け取り、そのユーザーの参加日に使用されたソルトを検索して1/0を返す別のサーバーを想定できます。

つまり、簡単に言うと、ソルトをパスワードとともに保存し、誰かがパスワードにアクセスする場合、パスワードの強度に応じて、各パスワードは妥当な時間内にクラック可能です。ユーザーごとに異なるソルトはすべてのotherユーザーを保護しますが、特定のアカウントを使用している場合、それは無関係です。ハッカーがパスワードを1つだけ使用した場合、ソルトとパスワードを保存すると、クラックが実行可能になります。回転ソルトをパスワードテーブルの別の場所に保持するということは、ソルトがなければ何千年もの作業で運命づけられるため、ハッカーはパスワードを解読するために2つのデータを盗む必要があるということです。

これはすべてトレードオフです。15桁のパスワードを使用するように強制すると、すべての人が画面に書き留められるか、「覚えやすい」、つまり言葉になります。

この時点で、Kerberosまたは同様のものに移行することもできます。保護しているデータが貴重な場合、ユーザーはそれを理解し、推測します。そうでない場合、私たちは気にしています。

しかし、私はあなたが行うことをお勧めしますnot独自の認証メカニズムを実装します。 Kerberosを使用し、セミパブリックPKIを使用し、自分でロールバックしないでください。私のサーバーがRAM私のソルトをディスクに保持している)を交換しただけで、自分の認証をロールするときにすぐに思いつく1つの間違いだけであるかどうかを知る方法がわかりません。

HTH

$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password);
$time = time();
$query = "
INSERT INTO user (name, unixcreationtime, passhash) 
VALUES ('$username', '$time', SHA2(CONCAT('$time','$password'),512) ";

SHA1を使用しないでください。安全ではなくなります。
すべてのハッシュをMySQLで行うことをお勧めします。これにより、ハッシュの結果に違いがないことを確認できます。

次を使用してユーザーを選択します。

$query = "SELECT id FROM user 
          WHERE name = '$username' 
            AND passhash = SHA2(CONCAT(creationdate,'$password'),512) ";

いいえ、パスワードがハッシュ化されるとfishABC09のように見えないため、md5ハッシュである5f4dcc3b5aa765d61d8327deb882cf99のようになります。

システムにアクセスするには、たとえハッシュを知っていても、元に戻すことはできません。ハッシュを複雑にし、レインボーテーブルでのハッシュ検索を防ぐために、ソルトを使用します。

例: Google search を実行して、「password」のmd5ハッシュを取得します。これは、5f4dcc3b5aa765d61d8327deb882cf99です。

多くの結果は正しいですか?

ここでもう一度ハッシュを作成します。「パスワード」を引き続き使用しますが、「AHG(* @」)のSALTを追加します。この投稿といくつかのボットスクレイパーに対する応答のみになると思いますこの投稿を読んだ人:)

cbe57e92ffbb0086320891b9f979156d

少数の結果 、またはこの投稿であるこの投稿のみである必要があります。

覚えとけ

これを覚えておいてください...ハッシュは一方向なので、ハッシュを取得しても、ハッシュの作成に使用されたものはわかりません

4
Layke

古いトピックですが、他のトピックもここに来るので、簡単に説明します。

hash(password)を実行すると、すべてのパスワードに対して同じハッシュ値が得られます[hash(password)= hash(password)]。 2人のユーザーが同じパスワードを持っている場合は、ハッシュ値が同じであるため、それが表示されます。 「password」や「12345678」などの一部のパスワードは非常に頻繁に使用されます。データベース内の同じハッシュ値->おそらくパスワード「password」または「12345678」(レインボーテーブル攻撃)。

hash(salt + password)はhash(salt2 + password)ではないため、hash(salt + password)を使用すると、同じパスワードに対して同じハッシュが得られません。

hash(x)は、f(x)= yのような単なる数学関数です。同じxを入力すると、同じyが得られます。安全のために、この関数は「特別」でなければなりません。もう安全ではないので、sha1を使用しないでください:D

1
user2717345

私はこれが古いことを知っていますが、この投稿でつまずくことができた人のために...

HMACを実際に実行しようとしていること。自分でやろうとすると、問題が発生します。たとえば、ハッシュを部分的に計算できます。これにより、たとえば、パスワードを推測するのに必要な労力を削減できます。 HMACはこの種の懸念に対処します。

Scryptまたはbcryptの方がより良いです。 HMACは依然として、迅速かつ簡単に計算できるように設計されたハッシュアルゴリズムを依然として使用しています。多くのハッシュアルゴリズムのハードウェア実装さえあります。 bcryptは計算コストが高く、scryptはメモリを大量に消費します。どちらも攻撃者にとって事態を難しくしますが、特にscryptは、パスワードを解読するためのハードウェアデバイスを構築することを本当に困難にします。

私はここのチャートが本当に好きです: https://github.com/pbhogan/scrypt#why-you-should-use-scrypt

1
Sam Terrell

ハッカーがあなたのPHP=ファイルにアクセスできる場合、彼は単にメール機能を追加できるので、誰がログインしても、アカウントの詳細がハッカーにメールで送信されます。

ハッカーがデータベースへのアクセスのみを取得する場合、ハッカーはそこに明確に書かれたパスワードを取得するべきではないため、保存する前に暗号化します。元に戻せないmd5ハッシュに保存します。

私は通常、ユーザー名またはユーザーIDに基づいてソルトを使用します。PHPプログラムは、static_site_keyとともに各ユーザーの生成方法を知っています。

0
Atul Gupta

ソルトは、固定長の乱数です。このソルトは、保存されているエントリごとに異なる必要があります。ハッシュされたパスワードの隣にクリアテキストとして保存する必要があります。

から

https://www.owasp.org/index.php/Hashing_Java#Why_add_salt_.3F