ドキュメント によると、scryptハッシュ関数は次のように機能します。
ハッシュ関数は次のことを行います。
- ランダムな塩を追加します。
- アクティブな攻撃から保護するためのHMACを作成します。
- Scrypt鍵導出関数を使用して、鍵のハッシュを導出します。
ハッシュ形式
すべてのハッシュは「scrypt」という単語で始まります。次に、鍵導出関数で使用されるscryptパラメータが続き、ランダムなソルトが続きます。最後に、以前のコンテンツの256ビットHMACが追加され、HMACの鍵が暗号鍵導出関数によって生成されます。結果は768ビット(96バイト)の出力です。
- バイト0-5:ワード「scrypt」
- バイト6から15:ScryptパラメーターN、r、およびp
- バイト16〜47:32ビットのランダムソルト
- バイト48〜63:16ビットのチェックサム
- バイト64-95:暗号鍵導出関数によって生成された鍵を使用するバイト0から63の32ビットHMAC。
バイト0から63は平文のままです。これらのバイトにはハッシュの検証に必要なメタデータが含まれているため、これは必要です。この情報が暗号化されていなくても、セキュリティが低下しているわけではありません。セキュリティの観点から重要なのは、ハッシュの整合性(ハッシュされた出力のどの部分も変更できないこと)と、ハッシュされた出力から元のパスワードを特定できないことです(これがscryptを使用している理由です-これは良い方法)。バイト64〜95は、これがすべて発生する場所です。
私の質問は、scryptハッシュを直接返すのではなく、scryptハッシュをHMACアルゴリズムのキーとして使用するのはなぜですか?これはどのような追加の保護を提供しますか? 「能動的攻撃」について言及しているが、詳細については触れていない。
Node Scryptモジュールを作成しました。
HMACはセキュリティを強化します。これを使用すると、認証サーバーのデータベースだけでなく、(tarsnapで行われるように)暗号化されたファイル形式のヘッダーとして使用されるスキームも貸し出されます。また、Colin Percival(scryptを作成した人)はこのスキームを使用して検証します(実際には彼からコピーしただけです)。
HMACが使用される理由を説明するために、簡単にまとめます。暗号鍵導出関数を使用して何かを暗号化すると、96バイトの結果が生成され、次のように分解されます。
bytes 0-5: The Word "scrypt"
byte 6: 0
byte 7: logN
bytes 8-11: r
bytes 12-15: p
bytes 16-47: salt (which is 32 bytes)
bytes 48-63: A 16 byte SHA256 checksum (hash) of the contents of bytes 0 to 47
bytes 64-95: A 32 byte HMAC hash of bytes 0 to 63 with the key being the scrypt cryptographic hash
バイト0から47は平文であることが重要です(いかなる方法でも変更または暗号化されていません)。これを確実にするために、16バイトのSHA256チェックサムがあります。 SHAはチェックサムとして非常に効果的に使用できますが(特にこの場合))、アクティブな攻撃から保護することはできません。つまり、誰かがペイロードを入手し、独自の値に置き換えました。たとえば、ペイロードを取得し、自分のlogN、r、pと自分のチェックサムを計算して、それを元の値として渡すことができます。
これを防ぐために、最後の32バイトはHMACです。 HMACはメッセージの整合性を保証するために使用され(つまり、ペイロードを積極的に変更する人から保護します)、暗号化兵器の主力です(読み取り:安全に使用できます)。 HMACには鍵が必要であり、scryptハッシュを鍵として使用します。
最後の32バイトが単なるscryptハッシュである場合、アクティブな攻撃者がすべてを危険にさらして自分のscryptハッシュを代用することを妨げるものはありません。 HMACはこれを防ぎます。これは、scryptハッシュを検証する手段としてだけでなく、スキーム全体の整合性もチェックします。
ところで、チェックサム(バイト48から63)が必要な理由を不思議に思う人もいるかもしれません。まあ、あなたがそれについて考えるなら、私たちはscryptハッシュを計算して、HMACのキーとして使用できるようにする必要があります。したがって、チェックサムは追加のレベルのチェックを追加します。それがパンしない場合、検証はそれ以上続行せずにすぐにfalseを返します。
これについては、後で説明します。
このモジュールに興味があり、パスワードを格納するためのハッシュを生成する場合は、ハッシュ関数を使用することを強くお勧めします。鍵導出関数は、完全性を保証するためのメッセージ認証コードを生成しません。また、scryptパラメータを個別に保存する必要があります。最後に、このモジュールにはネイティブの検証機能は含まれていません。
必要なのは、scryptアルゴリズムを使用してキーを取得することだけである場合は、このパッケージに含まれている KDF function を使用して取得できます。
このパッケージのいわゆるハッシュ関数は、元のscryptハッシュ関数のラッパーです。