Translated message

A translation of this page exists in English.

/etc/shadow 内のパスワードに対する bcrypt サポート

更新 -

概要

  • インターネット上では、さまざまな声が噴出しています。

    • Red Hat Enterprise Linux バージョン 8.9 以前では、bcrypt はサポートされていません。しかし、Red Hat Enterprise Linux 8.10 以降には、bcrypt のサポートが含まれています。
    • パスワードを保存するための最新かつ安全な方法を確保するために、glibc に bcrypt サポートを追加していただけますか?
    • codahale.com/how-to-safely-store-a-password によると、SHA ハッシュ化されたパスワードの使用は危険であり、簡単に解読されてしまいます。Red Hat はなぜセキュリティーを重視しないのでしょうか?

背景情報

  • bcrypt とは何ですか?

  • bcrypt の主な利用者は?

    • 注目すべきは、セキュリティーを重視する OpenBSD オペレーティングシステム (および他の BSD 系 OS) が、長年にわたってパスワードベースの鍵導出関数として bcrypt を採用しているという点です。
    • Red Hat Enterprise Linux バージョン 8.9 以前では、bcrypt はサポートされていません。Red Hat Enterprise Linux バージョン 8.10 以降では、/etc/shadow で bcrypt がサポートされるようになりました。
  • この事実を知ると、多くの人が「なぜ Linux では bcrypt がサポートされていないのか」という疑問を抱きます。

    • bcrypt の使用を支持する議論の多くは、現代のコンピューター (さらには専用ハードウェア) による SHA ハッシュの計算速度が極めて高速であるため、bcrypt の方が SHA ベースのスキームよりも優れているはずだ、という点に基づいています。

bcrypt 以外では、何を使うべきか?

  • GNU C ライブラリープロジェクトは 2007 年に、glibc v2.7 の crypt() 実装にカスタム SHA-2 パスワードハッシュアルゴリズムを追加しました。

  • 新しいアルゴリズムでは、設定可能なラウンド数を使用したイテレーティブプロセスで SHA-256 と SHA-512 を利用しています。具体例として、以下にソースコード (sha512-crypt.c) からの抜粋を掲載します。ここでは、ラウンド数の最小値、最大値、およびデフォルト値が指定されています。

    /* Default number of rounds if not explicitly specified.  */
    #define ROUNDS_DEFAULT 5000
    /* Minimum number of rounds.  */
    #define ROUNDS_MIN 1000
    /* Maximum number of rounds.  */
    #define ROUNDS_MAX 999999999
    

    glibc は、最大値を 999,999,999 に規定していますが、現行バージョンの RHEL では、pam_unix.so モジュールによって最大値が 9,999,999 に制限されています。以下は、pam_unix/support.c のからの抜粋です。

    /* Enforce sane "rounds" values */
    if (on(UNIX_ALGO_ROUNDS, ctrl)) {
            if (on(UNIX_BLOWFISH_PASS, ctrl)) {
                    if (*rounds < 4 || *rounds > 31)
                            *rounds = 5;
            } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
                    if ((*rounds < 1000) || (*rounds == INT_MAX))
                            /* don't care about bogus values */
                            unset(UNIX_ALGO_ROUNDS, ctrl);
                    if (*rounds >= 10000000)
                            *rounds = 9999999;
            }
    }
    
  • この実装は、OpenBSD の bcrypt スキームと同一ではありませんが、結果としては同様の性質を持ちます。攻撃者がハッシュ競合を試みようとしても、1 回の試行ごとに (少なくとも) 数千回ものハッシュ計算を実行する必要があるため、多大な時間を要することになります。

2007 年から、かなりの年月が経過したが...

  • bcrypt と同様に、このスキームにはイテレーション (つまり計算の複雑さ) を増やすメソッドが含まれていることに注意してください。以下は、上記のリンク先の仕様書からの引用です。
    (編注: 引用文中の強調は編集者によるもの)

    If the SALT strings starts with

      rounds=<N>$

    where N is an unsigned decimal number the numeric value of N is used to modify the algorithm used. As will be explained later, the SHA-based algorithm contains a loop which can be run an arbitrary number of times. The more rounds are performed the higher the CPU requirements are. This is a safety mechanism which might help countering brute-force attacks in the face of increasing computing power.

  • しかし、長年にわたってピアレビューに耐え、今日でも glibc を採用するあらゆるモダンな Linux ディストリビューションで使われ続けているにもかかわらず、デフォルトのラウンド数は 5000 から引き上げられていません。

  • とはいえ、デフォルトのラウンド数は簡単に設定できます。
    RHEL 5.2 では、/etc/login.defs および /etc/libuser.conf ファイルに設定が追加され、さらに最も重要な pam_unix.so の rounds= オプションも追加されました。

  • また、アップストリームでは、デフォルトの動作を微調整することについての議論が行われているほか、bcrypt や scrypt を実装してほしいという別のリクエストも寄せられています。

    これに加えて、2015 年には Password Hashing Competition が終了し、優勝者として Argon2 が発表されました。Red Hat のシニアセキュリティーソフトウェアエンジニアである Tomas Mraz の以下の言葉 は、この出来事がどのような意義を持つのかをよく物語っています。

    As the current SHA-2 based password hash is fairly sufficient and comparable with bcrypt in regards to security for implementing any additional password hash we should wait for the Password Hashing Competition to select the best choice.The support should be of course added to glibc and not to individual consumers of the crypt() function.

    2018 年 7 月時点では、glibc はいまだ Argon2 をサポートしていません。

OK、でもなぜ bcrypt ではないのか?

タイムラインは、以下のとおりです。

  • glibc のバグが 2006 年 1 月に報告されました。Bug 2100 - blowfish crypt support

  • 2007 年 9 月の Ulrich Drepper 氏 (glibc のメンテナー) による最初の発表 からの以下の抜粋は、glibc 開発チームが bcrypt に対して決して否定的な感情を抱いていたわけではないことを明確に示しています。
    (これは、MD5 ベースのパスワードハッシュの代替を開発するという文脈で書かれたものであることを覚えておいてください。編注: 引用文中の強調は編集者によるもの)

    There have been solutions to the problem for some time.Specifically the Blowfish encryption-based solution is implemented on a variety of systems, including some Linux distributions.The design of this method is sound: an encryption algorithm which has survived peer review for some time and which is not fast is used together with the obligatory salt.The result is a safe password encoding.
    ...
    I can already hear everybody complaining that I suffer from the NIH syndrome but this is not the reason.The same people who object to MD5 make their decisions on what to use also based on NIST guidelines.And Blowfish is not on the lists of the NIST.Therefore bcrypt() does not solve the problem.

    What is on the list is AES and the various SHA hash functions.Both are viable options.The AES variant can be based upon bcrypt(), the SHA variant could be based on the MD5 variant currently implemented.

    Since I had to solve the problem and I consider both solutions equally secure I went with the one which involves less code.The solution we use is based on SHA.More precisely, on SHA-256 and SHA-512.

  • glibc の 2007 年の仕様書 からの抜粋は、この決定をさらに明らかにしています。
    (編注: 引用文中の強調は編集者によるもの)

    Requests for a better solution to the problem have been heard for some time. Security departments in companies are trying to phase out all uses of MD5. They demand a method which is officially sanctioned.For US-based users this means tested by the NIST.

    This rules out the use of another already implemented method with limited spread: the use of the Blowfish encryption method. The choice comes down to tested encryption (3DES, AES) or hash sums (the SHA family).

    Encryption-based solution do not seem to provide better security (no proof to the contrary) and the higher CPU requirements can be compensated for by adding more complexity to a hash sum-based solution. This is why the decision has been made by a group of Unix and Linux vendors to persue this route.

    The SHA hash sum functions are well tested. By choosing the SHA-256 and SHA-512 algorithms the produced output is 32 or 64 bytes respectively in size. This fulfills the requirement for a large output set which makes rainbow tables less useful to impossible, at least for the next years.

  • 同じ頃、glibc Bug 2100 (blowfish による暗号化サポート) がクローズされました。

  • それから数年後、Coda Hale 氏による物議を醸した記事 (How To Safely Store A Password) が公開され、多くの誤解を招くことになりました。

  • その後まもなくの 2011 年 10 月、Fedora 16 に bcrypt を実装するよう求める RFE が提出されました。

    当然のことながら、彼らはアップストリームである glibc に RFE を提出するよう案内され、彼らはそれに従い、リクエストを提出しました (同じ 2011 年 10 月中に提出)。

    Ulrich Drepper 氏とそのチームが glibc の crypt() に SHA ベースのパスワードハッシュソリューションを実装してから (これは前述の記事で指摘された懸念に対応するものでした) 実に 4 年が経過した頃、Drepper 氏は次のようにコメントしています。

    I added a long time back the new hash sum based password mechanisms. They are at least as good. I'm not going to add anything more.

    その後すぐに、新しい glibc の RFE 13286 は "RESOLVED WONTFIX" としてクローズされました。

  • 2014 年 4 月に、新しい glibc RFE が作成されました。Bug 16814 - RFE: Reconsider adding bcrypt (or scrypt) support を参照してください。

  • 2017 年 6 月頃、glibc の RFE 13286 のステータスが "RESOLVED WONTFIX" から "RESOLVED DUPLICATE of bug 2100" へと変更されました。これにより、Bug 2100 が再オープンされ、将来的に bcrypt が追加される可能性があることを示唆するコメントが添えられました。

bcryptをどのように設定・使用すればよいのか?

Comments