パスワードを安全にハッシュするために、PBKDF2などのアルゴリズムは、SHA1などの一般的なハッシュを何度も繰り返します。安全のためにこれらの反復を実行する必要がある特定の方法はありますか?
特に、 password-hash.js から:
function generateHash(algorithm, salt, password, iterations) {
iterations = iterations || 1;
try {
var hash = password;
for(var i=0; i<iterations; ++i) {
hash = crypto.createHmac(algorithm, salt).update(hash).digest('hex');
}
return algorithm + '$' + salt + '$' + iterations + '$' + hash;
} catch (e) {
throw new Error('Invalid message digest algorithm');
}
}
これはパスワードをハッシュ化する安全な方法ですか?このようなアルゴリズムがあれば、次のようになると想像できます。
HMAC(HMAC(HMAC(password)))
その後、いくつかのより高速な機能が存在します
HMAC3(password)
同じ出力が得られます。これは事実ですか?
はい、反復ハッシュ関数にはいくつかの要件があります。
特に最後のポイントでは、サンプルコードが欠けています。 crypto.createHmac(algorithm, salt)
は、ループの外にある必要があります。攻撃者は同じソルトで多くのパスワードをハッシュするため、createHmac
呼び出しをパスワードループの外に置くこともできます。
_hmac = crypto.createHmac(algorithm, salt)
for (password in allpasswords) {
var hash = password;
for(var i=0; i<iterations; ++i) {
hash = hmac.update(hash).digest('hex');
}
...
}
_
これにより、攻撃者はパスワードをクラックするときに利点を得ることができます。これは、PBKDF2のように、HMACがソルトではなくパスワードをキーとして使用した場合に回避されます。
Cで指定されたコードを実装する といくつかの最適化を行うことにより、元のNodeJS実装よりも10倍速くなるようにしました。これは、攻撃者がGPUやFPGAを使用しなくても、意図したよりも10倍速くパスワードを解読できることを意味します。
つまり、HMAC
がすべての反復でほぼ同じ処理を行うため、doesはHMAC(HMAC(HMAC(password)))
の高速バージョンを実行する関数が存在します。
これについて ブログ投稿 と書きました。