ソリューション

マクニカネットワークスが取り扱う製品で、皆様の課題を解決します

“秘密鍵”の外部漏えい…サーバのなりすまし・通信の漏えいの危険に備える
RSA鍵の構成要素となる素数を作り出す「乱数生成器」の出力結果を比較検証!

マクニカラボ便り

「マクニカラボ便り」は、ちょっとやってみたい検証や、このテクノロジー、こう使ってみたらどうなる?など、マクニカネットワークスのエンジニアが気になった製品や技術について、ディープな検証や評価を行い、面白かったら皆さんにも公開しようという、ちょっと気まぐれなコーナーです。

最近話題の「パスワードリスト攻撃」等を鑑みると、ID/パスワードのみの認証では安全とは言えなくなってきた昨今、PKIが脚光を浴びつつあると感じます。詳細は後述しますが、RSA鍵の一方向性を巧みに利用した認証基盤であるPKIに関して、『PKI Day2012「公開鍵の多くが意図せず他のサイトと秘密鍵を共有している問題」(※1)』という講演を受講しました。講演内の指摘として、「(1)アプリケーションのデフォルトの秘密鍵をそのまま利用してしまっている、(2)素数を抽出する空間が小さいアプリケーションが、同じ鍵を生成してそのまま利用してしまう」が挙げられていました。前者は問題外としても、後者はユーザが直接認識するのは難しいため、興味津々な思いでおりました。なぜなら、会員個人用鍵を大量に生成するシステムでこの脆弱性をもつアプリケーションが使われていたとしたら、電子記録的に不正が見抜けない侵入が横行し得てしまうからです。一方、弊社取り扱いのHSM(※2)では、2011年頃以降発売のすべてのモデルにハードウェア乱数生成器が搭載されるようになりました。

多元認証への要請が求められる中、もう15年以上前に策定されたX.509 v3仕様の証明書を利用するPKIがようやく身近になってきていると感じています。例えば、ソフトウェア生成の鍵とハードウェア乱数生成器を介して生成された鍵との間で品質差を客観的に示すことができれば、HSMの「厳重な鍵の金庫」に加えて新たな付加価値をお客様に提供できるのではないか、との期待が膨らみます。

【今回のチャレンジ】
RSA鍵の構成要素となる素数を作り出す乱数生成器について、果たして乱数がどれほどばらけているのか?また、ソフトウェアとハードウェアの乱数生成器で差異はあるのか?各乱数生成器について実際に出力結果を比較検討してみました。

(※1)
(※2) Hardware Security Module(ハードウェアセキュリティモジュール)

RSA鍵を利用するアプリケーションPKIのおさらい

暗号の起源は、紀元前3000年前に遡りますが、1900年代後半までは共通鍵暗号方式、すなわち暗号化鍵と復号化鍵が同一である方式、のみが普及しておりました。近年になってこの共通鍵を秘密うちに復号利用者へ提供するためのコストが問題視され、非対称暗号方式への要請が叫ばれはじめました。1977年になって、Ronald Rivest、Adi Sharmir、Leonalrd M. Adlemanの3氏によってRSA暗号方式が発明されました。これは、桁数の大きい数を素因数分解することが困難であることを安全の根拠としたアルゴリズムで、現在も広く利用されています。

公開鍵で暗号化されたデータは、受信者のみが保持する秘密鍵でしか復号化ができないことから、盗聴防止に役立ちます。また、秘密鍵による電子署名は、公開鍵による署名検証によってその本人性を間違いなく確認することができる点で、なりすまし防止にも一役買います。このような意味で秘密鍵は、本人性確認のために非常に重要なデータであることが言えます。

一度この秘密鍵が外部に漏れてしまったら、どのような事態に陥るでしょうか?

  • 銀行サイトや買い物サイトの秘密鍵が悪意のある第三者に盗まれてしまったら?
  • OSベンダサイトの秘密鍵が悪意のある第三者に盗まれてしまったら?
    • サーバのなりすまし・通信の漏えい
    • 不正プログラムへのコード署名、署名付きドキュメントの偽造

が行われ、第三者による不正を見抜けなくなってしまい、大変な惨事が想定されます。

秘密鍵の使い回しの実態を確認できるのか

(※1)に指摘されているDebianに付随していた特定バージョンのOpenSSLを取得し、以下の検証を行いました。実際にはUbuntu 7.04(Debian 4.0)のパッケージに含まれているOpenSSLのモジュールを利用しました。

検証1

検証内容:
  • 現在の主流であるRSA2048ビット鍵の扱いを想定し、その元となる1024ビットの乱数を、「openssl rand -out <出力ファイル名> 128」コマンドにて50000個生成。
  • 生成された乱数同士に重複したものが現れていないか、総比較を行う。Linuxのdiffコマンドは、ファイルに差異が「ある」場合にメッセージを出すが、差異がない場合のみをチェックしたいため、相応のファイル内容比較プログラムを自作した。
  • 生成された50000個の乱数をすべて「openssl prime」コマンドにかけて素数判定を行う。

検証結果:
  • 50000個の乱数のうち、一意なものは32437個。それ以上生成すると、同じ乱数の使い回しとなった。即ち、最初に生成した乱数=32438回目に生成した乱数、2回目に生成した乱数=32439回目に生成した乱数…となる。
  • 50000個の乱数のうち、素数は91個。前述の「使い回し」を考慮すると、一意な素数は57個。1つの鍵ペアには2個の素数が必要なので、一意な鍵ペアは28ペアしか生成できず、それ以上生成すると「使い回し」になる、と考えられる。

対象が28人を超える個人用鍵ペア生成のシステムに利用されていたら…何のための個人用鍵なのか、分からなくなってしまいますね。

(※1)

その他の乱数生成器ではどうか

検証2

検証内容:
ソフトウェア(他のバージョンのOpenSSL)とハードウェアについて、50000個の乱数を生成して重複が発生するかの確認を行います。

  • OpenSSLについては、上記「openssl rand」コマンドを使用。
  • ハードウェアについては、PKCS#11にて、「初期化」「セッション開設」「HSMへログイン」後、C_GenerateRandom()を呼び出す。(※3)

検証内容:
ソフト/ハードの別 モジュール名、バージョン 重複の有無
ソフト OpenSSL 1.0.0-FIPS(※4) 29 Mar 2010 重複なし
ソフト OpenSSL 0.9.7a Feb 19 2003 重複なし
ハード(HSM) SafeNet社PSI-E(※5) PL600 fw3.20.00 重複なし
ハード(HSM) SafeNet社LunaPCI5 fw6.2.1 重複なし
検証結果:
  • OpenSSL 1.0.0-FIPSの場合、FIPS認定取得の条件として、一定の品質を持った乱数生成器が満たすべき基準の一つANSI X9.31(※6)に準拠している。
  • OpenSSL 0.9.7aにおいてもFIPS認定に準ずる生成アルゴリズムが適用されている可能性はあるが、その担保は無い。(※3)
  • HSMは、工場出荷状態ではFIPS認定取得済のファームウェアが搭載されており、各ハード上の乱数生成器も同上の基準を満たす仕様となっている。

(※3) 各ハードウェアにはハードウェア乱数生成器が装備されており、シード生成のためのAPI(C_SeedRandom())を予め呼び出す必要がない。
(※4) Federal Information Processing Standardization ― 暗号モジュールに関するセキュリティ要件の仕様を規定する米国連邦標準規格であり、NIST(National Institute of Standards and Technology 米国立標準技術研究所)により策定および各モジュールの認定を行っている。米国の規格だが、日本の官公庁や金融機関の納入要件として、FIPS認定が必須な案件が多い。
(※5) Protect Server Internal - Express
(※6) ANSI X9.31 ― 日付情報DT、初期値V(乱数生成の場合はシードと呼ぶ)、暗号処理Enc=3-Key 3DESかAES暗号処理に対し、Enc(Enc(DT) XOR V)で算出される。

乱数生成器の良し悪しは?数値化できるのか?

さて、上記検証結果では、OpenSSL0.9.8c以外のソフトウェアとハードウェアとの間で、生成される乱数の質に違いがあるのかは確認できていません。

乱数生成器自体の品質を確認する上で、巷には幾つもの検定手法が公開されております。今回はdieharder(※7)というツール(バージョン3.3.1)を用いました。ツール内部では、検定手法やパラメータ変更により、100を超える検定が行えるものです。既知のアルゴリズムを持つ乱数については、dieharderにて生成しながら検定を行えるが、外部の乱数生成器による乱数値を引数として検定することも可能です。

各検定の結果については、PASSED、WEAK、FAILEDの3段階評価となります。例えば、「WEAKと判定される場合の閾値」といった数値を与えて検定することも可能だが、今回はdieharderデフオルトのパラメータ状態でのテストを実施し、PASSED=2点、WEAK=1点、FAILED=0点で換算し、各10試行の平均値を算出しました。

以下は実際のツールの表示結果例:
  #===========================================#
  #       dieharder version 3.31.1 Copyright 2003 Robert G. Brown           #
  #===========================================#
     rng_name    |           filename             |rands/second|
     file_input_raw|                       o71-50000|  9.26e+06  |
  #===========================================#
          test_name   |ntup| tsamples |psamples|  p-value |Assessment
  #===========================================#
  # The file file_input_raw was rewound 8 times
     diehard_birthdays|   0|       100|     100|0.48312210|  PASSED  
  # The file file_input_raw was rewound 71 times
     diehard_operm5|   0|   1000000|     100|0.00000000|  FAILED  
  # The file file_input_raw was rewound 151 times
     diehard_rank_32x32|   0|     40000|     100|0.00000000|  FAILED  
  # The file file_input_raw was rewound 188 times
     diehard_rank_6x8|   0|    100000|     100|0.00000000|  FAILED  
  # The file file_input_raw was rewound 205 times
     diehard_bitstream|   0|   2097152|     100|0.13504299|  PASSED 
  # The file file_input_raw was rewound 336 times
     diehard_opso|   0|   2097152|     100|0.00000000|  FAILED  
  # The file file_input_raw was rewound 423 times
     diehard_oqso|   0|   2097152|     100|0.00740823|  PASSED  
  # The file file_input_raw was rewound 464 times
     diehard_dna|   0|   2097152|     100|0.11388787|  PASSED 
  # The file file_input_raw was rewound 468 times
     diehard_count_1s_str|   0|    256000|     100|0.03300088|  PASSED 
  # The file file_input_raw was rewound 548 times
     diehard_count_1s_byt|   0|    256000|     100|0.00000000|  FAILED

(以下省略)

また、実際にdieharder内に実装されている検定には下記のようなものがあります;
検定名 詳細
Diehard Birthday Test
(誕生日検定)
乱数ビットの羅列を、「日付」部を512(9ビット)、「年」部を24ビットとして、同一の誕生日でない確率はポアソン分布に従うはずであり、その分布との乖離具合を検定
Diehard Overlapping 5-Permutations Test
(順列検定)
0と1からなる乱数列を160ビットの部分列に分け、それを32ビット単位の5数値組とみなす。5数値組の大小関係により、120個のクラスに割り当て、その度数の分布が一様になっているかを検定
Diehard Bitstream Test
(ビット列検定)
0と1からなる乱数列から20ビットの数値を221個作り、一度も出現しなかった数値の偏りを調査
Diehard Minimum Distance
(2d Circle) Test
(最小距離検定)
0と1からなる乱数列を32ビット単位で分割し、各32ビットXを Y=10000X/232 と変換する。(Xn, Xn+1)および(Yn, Yn+1)をそれぞれ2次元座標上の点とみなし、8000個の点をプロットしていく。すべての点の組合せの中から距離が最小となる2点の距離を計算し、その偏りを調査

今回、OpenSSL 0.9.8c、OpenSSL 1.0.0-FIPS、PSI-E fw3.20.00、LunaPCI5 fw 6.2.1の4乱数生成器についての検定結果を下記の様にグラフ化してみました(全生成器にてFAILEDとなったであること盛り込んでおりません)。

① OpenSSL 0.9.8cとOpenSSL 1.0.0-FIPSとの比較

OpenSSL0.9.8cとOpenSSL1.0.0-FIPS のdiharder検定結果比較 OpenSSL 0.9.8cとOpenSSL 1.0.0-FIPSとの比較

検定23項目目から28項目目あたりで後者が優位であることが分かります。

② OpenSSL 0.9.8cとPSI-E fw 3.20.00との比較

OpenSSL0.9.8cソフトウェア と PSI-E ハードウェアのdiharder検定結果比較 OpenSSL 0.9.8cとPSI-E fw 3.20.00との比較

ほぼ同上の議論が成り立ちます。

③ OpenSSL 0.9.8cとLunaPCI5 fw 6.2.1との比較

OpenSSL0.9.8c ソフトウェア と LunaPCI5 ハードウェア diharder検定結果比較 OpenSSL 0.9.8cとPSI-E fw 3.20.00との比較

こちらもほぼ同様の議論となります。

④ OpenSSL 1.0.0-FIPSとHSM2種との比較

OpenSSL1.0.0-FIPSソフトウェアとPSI-E/LunaPCI5ハードウェアのdiharder検定結果比較 OpenSSL 1.0.0-FIPSとHSM2種との比較

グラフを見る範囲ではソフトウェアと各ハードウェアの間での
有意差を確認することはできませんでした。

(※7)

ならばハードウェアを利用するメリットとは?

SafeNet社Lunaシリーズ(ソフトウェアv5.x)およびSafeNet社PSI-Eはいずれもハードウェア乱数生成器を搭載しています。

ハードウェア乱数生成器

HSMを利用するメリット

  • 秘密鍵(値)を装置から取り出せない(Lunaシリーズ認証局モデル)
  • 複数人認証設定により、第三者に鍵生成、鍵利用(暗号/署名処理)されにくい
  • HDDと異なり、鍵データの完全消去が可能
  • ハードウェアノイズをエントロピー源とすることにより、シードを利用することなくハードウェア乱数生成が可能
  • 鍵生成/署名生成のオフロード

処理時間:単位ミリ秒(処理時間の少ない方が高速=高性能、を表します) 検定結果比較

マシンスペック:Intel Xeon E5620 2.40GHz *4 メモリ 4GB
HSM: SafeNet社 LunaSA5-7000 sw 5.1.0/fw 6.2.1

まとめ

  • OpenSSL x.x.x-FIPS や他のFIPS認定済アプリケーションなど、一定の乱数品質が担保されるソフトウェアや、FIPS認定のHSMを利用するのが、他と重複しない安全な秘密鍵生成には望ましいと考えられる。(※8)
  • アプリケーションが用意しているデフォルト鍵を使うのは当然避けるべきだが、生成器で最初に生成されたものではなく、数試行後に生成された乱数(秘密鍵)を利用するのが、他との重複を避ける上で望ましいとも考えらる。
  • 秘密鍵の重要度や鍵を大量に発行するシステムでは、シード不要かつ高速なHSM利用の検討をおすすめしたい。

今回の検証によって、HSMに対しての、従来と視点を違えた付加価値なるもの、をご提供できなかったのが心残りではありますが、今後も周辺情報の提供に一役買えればと、まい進してまいります。

以上


(※8) 実際に採用するソフトウェアなどのバージョンについては、最新リリース版がそれまでの不具合を修正していると考えられる点で最有力と考えられるが、Common Vulnerabilities and Exposures

http://cve.mitre.org/cve/index.htmなどの脆弱性データベースにて、既知の他の脆弱性がないか、もあわせて確認しておくことが望ましい。

いつか見た景色 from Staff's Albums