C#: パスワードハッシュ生成サンプル(PBKDF2)

概要

  • 鍵導出関数であるPBKDF2を使って、「パスワードからAES-256等で使用可能なキー(256ビット)」(パスワードハッシュとしても使用可)を生成するサンプルを紹介します。
  • 完全なサンプルコードはgithubで公開しています。
    GitHub

    Contribute to nextdoorwith/example-dotnet6 development by cr…

  • 次の実行環境を使用しています。
    OSWindows 10(64ビット)
    IDEMicrosoft Visual Studio Community 2022(17.1.3)
    言語C#(10.0) + .NET6
    ハードウェアCPU: AMD Ryzen 5 3400G, MEM: 16GB, SSD: 130GB
  • 次のリファレンスを参考にしています。

鍵導出関数とPBKDF2

  • PBKDF2は鍵導出関数と呼ばれ、パスワードからキーを生成するための関数です。
    • ブルートフォース等の攻撃に対抗できるよう、予測が難しく、キー生成に時間がかかる(CPUやメモリ負荷が高い)アルゴリズムが使用されています。
    • 生成されたキーは、パスワードハッシュやAES256等のキーにも使用できます。
    • PBKDF2は、RSAのPKCS #5 v2.0として規格化され、RFC2898として発行されています。RFC2898は2017年に発行されたRFC8018(PKCS #5 v2.1)で置き換えられています。
  • PBKDF2は古くなりつつあります。可能であれば、より新しいArgon2idの使用をお薦めします。こちらを使用できない場合、LINUX等で使用されているbcrypt等のをお薦めします。
  • アメリカ政府機関、金融やセキュリティ系システムで参考とされる「暗号化モジュールのためのセキュリティ要件(FIPS140-2)」では、PBKDF2がサポートされています。Argon2idやbcryptはサポートされていないので、FIPS140-2の準拠を求められるシステムではPBKDF2を使用する必要があります。

推奨パラメータ

  • 業務でPBKDF2を使用する場合の推奨パラメータは次の通りです。(2022年8月現在)
    説明にある「コード分析」はVisual Studio 2022の.NET コード分析を意味しています。

    項目推奨値根拠など
    ソルト長128ビット以上NIST. SP 800-132.で推奨。
    ハッシュアルゴリズムSHA-256以上OWASP推奨。
    MD5やSHA-1は脆弱性があるため。
    コード分析ではSHA-256以上が推奨(CA5379)
    ストレッチング回数
    (イテレーション回数)
    31万回以上OWASPが推奨するSHA-256使用時の値。
    コード分析では10万回以上が推奨(CA5387)
  • PBKDF2などの鍵導出関数は、CPUやメモリ等のリソースを大量に消費します。性能要件を満たせない場合、前述のストレッチング回数などのパラメータを調整する必要があります。
  • パスワードを使用した認証は初回アクセスのみで、その後は発行されたCookieやトークンを使用して認証・認可するのが一般的です。性能劣化を最小限にするために、PBKDF2の使用は初回アクセス時の認証のみに留め、それ以降のアクセスには使用しないような設計になります。
  • ささいな抵抗ですが、ストレッチング回数は31万回等のように予測しやすい回数(キリが良い回数)より、313,324回等のようにキリの悪い回数の方が良いかもしれません。

サンプルコード

  • PBKDF2を使用して、パスワードとソルトからパスワードハッシュを生成するサンプルです。
    (「鍵導出関数を使用する」という意味では、AES-256等の256ビット長のキーを生成するサンプルとも言えます。)
  • ソルトの生成、PBKDF2によるキー生成のコード部分です。
    • 128ビット(16バイト)長のソルトを使用する前提です。ソルトの生成には暗号用の予測が難しいRandomNumberGeneratorクラスを使用します。なお、RNGCryptoServiceProviderは非推奨になりました。
    • PBKDF2によるキー生成はRfc2898DeriveBytesクラスを使用します。
    • GetBytes()メソッドを使用する方法と、Pbkdf2()というstaticメソッドを使用する方法があります。後者のPbkdf2()メソッドを使う方が性能が良いようです。
      私の環境でキー生成を1,000回繰り返した場合、前者は60秒、後者は40秒程となり、後者のPbkdf2()の方が30%程良い。)
    • 既定では安全性が低いSHA-1が使用されるので、前述の通りSHA-256を指定しています。また、イテレーション回数はOWASPで推奨される31万回(SHA-256使用時)を指定しています。
    • コード分析(セキュリティ規則)が有効になっている場合、イテレーション回数は10万回以上(CA5387)、ハッシュアルゴリズムはSHA-256以上(CA5379)、の警告(推奨)が出力されます。