自堕落な技術者の日記

基本は喰ってるか飲んでるかですが、よく趣味でカラオケ・PKI・署名・認証・プログラミング・情報セキュリティをやっています。旅好き。テレビ好きで芸能通

SSL証明書

W3C Web Cryptography APIとの果てしなき戦い(第3回 動くサンプル1)

前回はW3C Web Cryptography APIの鍵生成、署名などについて説明しましたが、実際に動く実例がないとAPIの有り難みもわかないのかなと思いまして、とりあえず3つのサンプルを作ってみました。サンプルはChromeやFirefoxでは動くようになっています。画像をクリックするとサンプルページが開くようになっています。

ハッシュ関数


wc-hash
ハッシュアルゴリズムを選んで、ハッシュ計算したい文字列(UTF-8だから日本語も可能)を入力して、「ハッシュ計算」のボタンを押すだけで、16進数でハッシュ計算結果が表示されます。

公開鍵ペアの生成


wc-genkey
RSA公開鍵ペアを生成します。W3C Web Cryptography APIでは、鍵生成やインポートの際、どのような用途で、どのようなハッシュ関数と一緒に使用するかを指定する必要があるようで、生成時に選択するようにしていますが、PKCS#8 で秘密鍵や公開鍵をエクスポートする際には、まぁ、関係のない話になってしまいます。PKCS#8のバイナリデータ(ArrayBufferView)をPEM形式に変換するのにjsrsasignライブラリを使っています。

RSA鍵による署名と検証


wc-sigver
RSA鍵でUTF-8の文字列に対してSHA256withRSA署名アルゴリズムで署名と署名検証ができます。鍵はW3C Web Cryptography APIで内部生成した鍵ペアで署名と署名検証することもできますし、PKCS#8 PEM形式やJSON Web Key(JWK)フォーマットの秘密鍵や公開鍵をインポートして署名や署名検証することもできます。

サンプルの動作環境

これらのサンプルページは新しいChromeのWindows、Android、Mac OS X、Linux版、新しいFirefoxのWindows、Mac OS X、Android版で動作します。Safariでは一部がMac OS X版、iOS8+などで動作します。Internet ExplorerではPromise APIをサポートしていないので動作しません。IEでも動作するようにコード書くのはちょっと面倒で、それらの相互運用性を持たせるような実装の仕方については別途紹介しようかと思っています。

おわりに

とりあえず、いろんなブラウザでW3C Cryptography APIの動作を試してみることができるので、遊んでやってください。ソースコードはgithubに置いてあるのでご覧ください。FirefoxとChromeだけでも相互運用性持たせるのに結構壁にぶちあたったりして、その上、SafariやIEなども一緒にサポートするコードを書くのはかなり骨が折れるんですよね。でも、AndroidのFirefoxでも動くのを見ると、ちょっと目がうるうるしてきたりしますw。今日はこのへんで。

関連記事

POODLE攻撃について本当にTLSv1.0なら安全なのか?

POODLE攻撃は、運用泣かせというか、SSLv3のサポートを本当に切っちゃっていいのか、レガシークライアントについて対応するのがいいのか、悩む所ですよね。ShellShock騒ぎさえまだうちでは収束していないのに・・・

POODLE攻撃は、「SSLv3の問題であってTLSv1.0以上では(パディングの方法が違うので)影響が無い」とされていますが、nahiさんからコメントもらって「実装依存だけどTLSv1.0でも危険な実装があるんじゃないの?」ということで、その事を書いてみたいと思います。

今回のPOODLE攻撃については、何が問題でどのようにすれば攻撃できるのかという、詳しい図入りの素晴らしく判りやすい解説をモバゲーさんが 「SSL v3.0の脆弱性「POODLE」ってかわいい名前だけど何?? - Padding Oracle On Downgraded Legacy Encryptionの仕組み -」でされているので、そちらをご覧になると良いと思います。

SSLv3とTLSv1.0以降のブロック暗号のパディングの違い

SSL/TLSでAESや3DESなどのブロック暗号を使った場合には、暗号化するデータはブロックの大きさの整数倍、つまり、AES-256なら32バイト、AES-128なら16バイト、3DESなら24バイトの倍数でないといけません。で、その大きさに揃うようにパディングと呼ばれる隙間の詰め物をして倍数になるように調整するわけです。

例えば、暗号スイートとして、AES-128(16バイト)、SHA1(20バイト)を使っているとして、8バイトのデータを暗号化するとしましょう。パディングした暗号化するための入力は

平文(8)+HmacSHA1メッセージ認証コード(20)+パディング(3)+パディング長(1)=AESブロック長(16)×2
となります。必ずパディング長の1バイトは含まれます。パディングの長さは(ブロック長-1)を超えない値で今回は3となります。

さて、SSLv3とTLSv1.0のパディング方法の違いですが、

  • SSLv3の場合はパディングの値は任意の値を取れる
  • TLSv1.0の場合はパディングはPKCS#5パディング方式を用い、 具体的にはパディング値の各バイトはパディング長と同じ値が設定される。
となっています。先ほどの3バイトのパディングがあるケースでは 下の例のようになります。
パディング(3)+パディング長 [a0][f3][62][03] - SSLv3の場合(先頭3バイトは任意) [03][03][03][03] - TLSv1.0の場合(先頭3バイトはバイト長と同じ値)
今回のPOODLE攻撃では、SSLv3がパディングの値が任意であるために、 効率的に特定の位置の1バイトの平文を復元することができるわけです。 モバゲーさんの解説にある通り、SSLv3の場合は256回のHTTPS要求の試行で 1バイトを解読することができますが、TLSv1.0の場合には256の16乗の 試行が必要なために現実的な時間で復元することはできません。

で、本当にTLSv1.0なら安全なの?

今日の本題のTLSv1.0なら本当に安全なのか、という話なんですが、 とりあえず、TLSv1.1とTLSv1.0のパディングに関する規定を 見てみましょう。

まず、TLSv1.1についてですが、

RFC 4346 TLSv1.1 6.2.3.2 CBC Block Cipherより
padding
Padding that is added to force the length of the plaintext to be an integral multiple of the block cipher's block length. The padding MAY be any length up to 255 bytes, as long as it results in the TLSCiphertext.length being an integral multiple of the block length. Lengths longer than necessary might be desirable to frustrate attacks on a protocol that are based on analysis of the lengths of exchanged messages. Each uint8 in the padding data vector MUST be filled with the padding length value. The receiver MUST check this padding and SHOULD use the bad_record_mac alert to indicate padding errors.
となっています。

一方、TLSv1.0です。

RFC 2246 TLSv1.0 6.2.3.2 CBC Block Cipher より
padding
Padding that is added to force the length of the plaintext to be an integral multiple of the block cipher's block length. The padding may be any length up to 255 bytes long, as long as it results in the TLSCiphertext.length being an integral multiple of the block length. Lengths longer than necessary might be desirable to frustrate attacks on a protocol based on analysis of the lengths of exchanged messages. Each uint8 in the padding data vector must be filled with the padding length value.

TLSv1.0では、「パディングデータはパディング長で埋められなければならない。」 と書いてありますが、 TLSv1.1では、「 パディングデータはパディング長で埋められなければならない(MUST)。 受信者はこのパディングをチェックしなければならず(MUST)、 パディングエラーを示すにはbad_record_macアラートを使う べきである(SHOULD)。」 となっています。 つまり、TLSv1.0ではパディングデータがちゃんとパディング長の値で うめられているかどうかのチェックはmustとは書いてあり、 多くの実装はちゃんとしてくれていると思いますが、 RFC上の必須要件(MUST)ではないので、チェックしない実装があっても おかしくなく、 チェックされない場合、これではSSLv3と同じで、一般的なSSL/TLSの実装では MUSTと書かれていない事は実装する必要もないので (実際、SHOULDと書いてあれば、これに対応しない実装も多い)、 実装によってはパディング値のチェックをしないために、 SSLv3と同じくPOODLE攻撃の影響を受けるTLSv1.0実装がある可能性がある かもしれないという事です。

時間がある時に、ちょっと主要なオープンソースの実装を覗いてみようと思います。

今日はこの辺で。nahiさん、情報ありがとうございました。

追記

ChromeのSHA1証明書のアラート表示ポリシの問題点

SHA1withなんとかで署名されたSSLサーバー証明書に対するGoogle Chromeの 将来の取扱いポリシについて、Googleのブログで9月5日に情報公開され、ちょっとビックリした人も多いんじゃないでしょうか。私は、「こりゃちょっと問題だなぁ。」と思ったので今日はブログで書いてみようと思います。

SHA1が充分な暗号強度がなくなりつつある話

暗号の専門家ではないので、よくわからないのですが、 例えばコレなんかをみてみるとSHA1ハッシュアルゴリズムの暗号強度が充分でなくなってきていると言われており、暗号に関する日本で主要なガイドラインであるCRYPTREC暗号リストではSHA1は「運用監視暗号リスト」、危殆化リスクが高まっているが互換性維持のため仕方なく使って良いリストに入っています。

このような状況を受けて、製品ベンダー、証明書発行サービスなどのサービサーなどはSHA1からSHA2への移行をようやく始めたところなのかなと思います。

米国の標準化機関であるNISTは2011年1月に「NIST SP 800-131A Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lenghs(暗号アルゴリズムと鍵長の使用に関する勧告)」を発行しており、その中で「SHA1を使った署名の生成と検証は2013年12月31日以降、認められない。」としていますが、NIST内でもSHA1証明書を使ったサイトがまだ残っているそうで、「自分も守れてないじゃ〜〜ん」みたいな状態になっているそうです。

2013年11発表のMicrosoft製品のSHA1移行ポリシー

幾つかの業界や製品では先行してSHA1からの移行ポリシーを策定、公表しているものもありますが、SSLサーバー証明書に関しては幅広い製品やサービスで使われ、SHA1を使っている比率も高く移行は難しいのだろうと思います。本来ならCA Browser ForumのBaseline Profileで規定されてもよかったのだろうと思いますが、SHA1からの移行については言及されていません。 そんな中、2013年11月12日に発表されたMicrosoft製品に関して公開された2つのSHA1移行ポリシーはちょっと衝撃的でした。

Windows Root Certificate Program - Technical Requirements version 2.0
このプログラムはWindows製品の「ルート証明書プログラム」という、Windowsの信頼するルート証明書に加えてもらうためには、どのような基準を満たさなければならないかを定めたものですが、「対象の認証局は2016年1月1日以降、SHA1証明書を発行をしてはならない。」としています。
Windows PKI Blog: SHA1 Deprecation Policy
「Windows製品では2017年1月1日以降、SHA1のSSLサーバー証明書を受理しないためエラーとなる。」としています。すなわち、Windows製品でSSLを使えるようにするには、SHA1 SSLサーバー証明書を2016年12月31日までにSHA2にリプレースしなければならないという事だそうです。
SHA1 証明書がそろそろ偽造の危険性があるという認識も高まっており、充分な猶予期間もありますし、その頃には、SSLサーバー証明書を扱う全ての製品のSHA2対応もかなり進んでいるでしょうから、よく考えられた妥当なスケジュールなのかなと思います。

これに関して注目すべきポイントは以下の2つかと思います。

  • 中間CA証明書やルート証明書のSHA1については言及していない。
  • 2016年1月1日と、2017年1月1日という2つのマイルストーンを守りさえすればよい。
このMicrosoftのSHA1移行ポリシーのアナウンスを受けて、主要なSSL証明書発行サービスは、SHA1証明書の発行は2015年12月31日までとアナウンスをしています。

2014年9月5日に公開されたGoogle ChromeのSHA1 証明書対応ポリシー

2014年9月5日に「Google Online Security Blog: Gradually sunsetting SHA-1」 にて、Google ChromeのSHA-1証明書にするポリシーの変更が発表され、一部の人は驚きを持って読んだのではないかと思います。 ITmediaエンタープライズでも 「Google、「SHA-1」サポート中止のスケジュールを発表(2014.09.08)」 として紹介されました。(何点か間違いがあるので、原文を参照するのがいいでしょう。)

これは簡単に言ってしまうと、「SHA-1のSSLサーバー証明書によってHTTPSの接続表示を近々(大きく)変えますよ」というアナウンスです。

Google ChromeのHTTPSステータス表示

Google ChromeのアドレスバーにおけるHTTPSのステータス表示は以下のようになっているようです。

表示内容
chrome_stat_1ok EV証明書でない正常なHTTPS接続の場合
chrome_stat_2yellow secure, but with minor errors
例えばHTTPSとHTTPのコンテンツの混在の場合などに出る。
chrome_stat_3white neutral, lacking security
平文のHTTPなど、セキュリティが無い中立の状態。
chrome_stat_4red affirmatively insecure
危険だと断言できる場合。
(参考) EV SSLサーバー証明書で正常にHTTPS接続できている場合
chrome_stat_5ev

Google Chromeは証明書チェーンがSHA1かどうかチェック

WindowsのSHA1移行ポリシーはエンドエンティ証明書、すなわちSSLサーバー証明書がSHA1かどうかだけをチェックしており、中間CA証明書がSHA1かどうかは関係無かったのですが、Google Chromeの移行ポリシーは、全ての中間CA証明書もチェックするので注意しなければなりません。
path1

で、ChromeでSHA1証明書でHTTPS接続した場合どうなるのか?

9月5日に発表された、ChromeでSHA1証明書にHTTPS接続した場合のURLアドレスバーのHTTPSステータス表示が、この半年で3回出てくるChromeのバージョンによって、どう変わっていくのかを整理したのが下の表です。

Chrome 39
開発版の途中まで
〜2014.09.26
38安定版まで
(〜2014.11上旬)
Chrome 39
開発版の途中から
(2014.09.26〜
2014.11.09)
39安定版
リリースから
(2014.11上旬〜
Chrome 40
開発版の途中から
(2014.11.09〜
2015.Q1)
40安定版
リリースから
(2015.01?〜
Chrome 41
開発版の途中から
(2015.Q1〜
2016.12.31)
41安定版
リリースから
(2015.03?〜
2017.01.01〜
有効期限が2016年5月31日までのSHA1証明書 chrome_stat_1ok chrome_stat_1ok chrome_stat_1ok chrome_stat_1ok chrome_stat_4red
有効期限が2016年6月1日から12月31日までのSHA1証明書 chrome_stat_1ok chrome_stat_1ok chrome_stat_2yellow chrome_stat_2yellow chrome_stat_4red
有効期限が2017年1月1日以降のSHA1証明書 chrome_stat_1ok chrome_stat_2yellow chrome_stat_3white chrome_stat_4red chrome_stat_4red
Windowsの場合(Chrome同等の表示として) chrome_stat_1ok chrome_stat_1ok chrome_stat_1ok chrome_stat_1ok chrome_stat_4red
表を見ていただければわかる通り、Microsoft WindowsのSHA1移行ポリシに比べて、Chromeはかなりアグレッシブな設定になっており、開発版は2014年9月26日のアップデートから、安定版は2014年11月頃リリースの39から正常なHTTPS接続でないかのようなステータス表示となってしまいます。

今回のChromeのSHA1対応ポリシの問題点

今回のGoogle ChromeのSHA1証明書に対する対応計画は様々な問題があると考えていて、論点を整理したいと思います。

  • 最も重要だと思うのが、ブラウザ毎にHTTPSのエラーや問題に対する表示の意味が異なってしまうという点です。今回のSHA1証明書の表示の計画がブラウザベンダー毎に異なるのはユーザが混乱することになり、良くなかったと思います。本来ならCA Browser ForumのBaseline Profileなどで、業界で意思統一されたSHA1証明書の移行計画を示し、EV証明書のように準拠するブラウザは同じようなステータス表示にするべきだったと思います。
  • 2つの有効期限の異なる証明書があって、その有効期限により表示状態が異なるということは問題です。 今回はSHA1署名アルゴリズムの暗号危殆化を問題に取り上げているのですから、有効期限の長短にかかわらず、ある時点での暗号危殆化の程度は全く同じであり、同じものに対しては同一のHTTPSステータス表示にすべきではないでしょうか。
    notafterdiff
  • 2017年1月1日からを、SHA1証明書を使ってはならない日と定めたとして、2年3ヶ月以上も前にユーザに表示を変えて伝える必要があるのでしょうか。2017年1月1日まではSHA1証明書を使って良いとするなら、いかなる警告もそのことで出す必要がなく、これはユーザも、ウェブサイト運営者も混乱させるだけです。2年以上も前に表示が異なってしまうことで、ユーザはサイトへクレームや問い合わせを入れるようになり、ウェブサイト管理者は仕方なく2年前倒しでSHA2証明書への移行を迫られることになります。
  • 最近のモダンなブラウザではSHA2証明書に対応していますが、古いJavaや、組込み機器、ICカード、ガラケー(フィーチャーフォン)などSHA2証明書に対応できない環境は、未だに多数あります。これらの環境と歩調をあわせながらSSLサーバー証明書のSHA2移行を進める必要があったのではないでしょうか。
  • 前述のOSなどのレベルでアルゴリズムとしてSHA2署名をサポートしていたとしても、検証などで使おうとするSHA2証明書のトラストアンカとなるルート証明書が「信頼するルート証明書」ストアに入っているかどうかは別の問題。例えば全てのお客様や、全社員のWindows XP SP3に対してルート証明書を追加させるという事はかなり困難。
  • Netcraftの2014年5月の調査によれば、 インターネット上のウェブサイトのうち92%がSHA1証明書のままであり、SHA2証明書へ移行済なのはわずか7%にすぎません。HeartBleed脆弱性の影響で証明書のリプレースが多くあったため、SHA2への移行は進んだようですが、それでもたった7%です。このような状況で2014年9月にはHTTPSステータス表示を変えるというのは急すぎないでしょうか。(追記 SSLPulseによると2014年9月時点でSHA2は15%だそう)
  • SHA1証明書に対する表示変更のポリシーを2014年9月5日にアナウンスしてから、わずか21日後の2014年9月26日の開発版アップデート、安定版では2014年11月頃の39リリースで、影響を受けるサイトが出始めます。充分な猶予期間、準備期間を持てるように例えば半年や1年といったスパンで事前アナウンスをする必要があったのではないでしょうか。
  • SSLサーバー証明書は一般に2年や1年といった有効期間のものを購入される組織が多いと思いますが、例えば2014年6月1日から、アナウンスのあった2014年9月5日に2年物のSHA1証明書を購入し設定したウェブサイトは、早速2015年の1Qには、問題があるかのような黄色表示 chrome_stat_2yellow になります。事前に知らされていれば、1年物を買うとかSHA2証明書を買うとか対策ができたかもしれません。 これは、あまりに不親切でユーザやサイト管理者の事を考えていない行為だと思います。
  • 2017年1月1日以降が有効期限であるSHA1証明書が、2017年1月1日以降は使えなくなるという事は理解できるとして、2016年6月1日から2016年12月31日の間に有効期限がある証明書を分けてアラート表示をする必要があるとは思えません。

参考にすべきページ

今回のChromeのSHA1移行について問題提起や対策などを示している良いページがあるので、紹介しておきたいと思います。

CSO Online: Do you agree with Google's tactics to speed adoption of SHA-2 certificates?
CA Security Councilの中の人の問題提起。オンラインショップクリスマス商戦の時にこのような問題を起こすのや良くないとも言っている。Windows Server 2003ではhotfixなしでは非対応だと。他にも参考になるアドバイスがある。意見も募集している。
BLOG: IVAN RISTIC: SHA1 deprecation: what you need to know (2014.09.09)
SSLの状態を調べられるQualysのSSLLabsを作っていたり、SSLの設定ガイドなどを書いているIvanさんのページで、今回のGoogle Chrome SHA1移行について、どのように対処するのが良いか解説しています。いつも冷静な分析をされる人ですが、今回に関し批評が無いのは寂しい。
CA Security Council: List of Operating Systems, Browsers, and Servers Which Support SHA-256 Hashes in SSL Certificates (last update Sep 8, 2014)
最新のSHA-256サポート状況のリストです。参考になります。でも、OSや環境レベルでSHA2をサポートしたと言っても、これから使おうとしているSHA2証明書のトラストアンカとなるルート証明書が信頼するルート証明書ストアに入っているかは別の問題。

おわりに

Google Chromeは良いブラウザだと思うし、便利だし、大好きなんですが、CRLSetの問題と、今回のSHA1対応の件はちょっとヒドイなぁと思います。サイトの運営者の方は、最初のマイルストーンの9月26日まで、あまり余裕がないので、至急自分の環境を調査して対策を取った方がいいと思います。今日はこんなところで。

本ブログの関連記事

関連リンク

Mozilla Security Blog: Phasing Out Certificates with SHA-1 based Signature Algorithms (2014.09.23)
Mozilla Firefoxからも同様のSHA1移行ポリシーが公開されました。

(訂正)バージョン番号の修正(2014.09.17)

バージョン38が既にリリースされていると勘違いして、 今回のSHA1アラート表示の修正が、マイナーで入るのかと勘違いしたため表の バージョンの表記がおかしくなっていましたので修正しました。 バージョンの確認はこちらでできるようになっており、直近のメジャーですと以下のようなリリース履歴であるとわかりました。すみませんでした。(影響日やバージョンについて再修正しました9/17 12:50)

  • 安定版メジャー 37.0.2062.94 2014.08.26 for Win,Mac,Linux
  • 安定版メジャー 36.0.1985.125 2014.07.16 for Win,Mac,Linux
  • 安定版メジャー 35.0.1916.114 2014.05.20 for Win,Mac,Linux
  • 安定版メジャー 34.0.1847.116 2014.04.08 for Win,Mac,Linux
通常は安定版(Stable Channel)のリリースは6週間おき だそうですが、40安定版についてはクリスマスシーズンを挟むので 時期が未定なのだと思います。

(小ネタ)HeartBleed影響で証明書の再発行とそれに使うRSA鍵の事前チェック

OpenSSL HeartBleed問題で証明書の再発行やら説明やらなんやらに追われてたわけですが、再発行に際してちょっと鍵も事前チェックしてみるかなぁ、、、と。

Debianで生成するRSA鍵の乱数が固定の値になってしまい生成される全てのケースの秘密鍵がわかってブラックリスト化されたり[0]、因数分解の片方がわかっていれば秘密鍵は簡単に復元できちゃう問題とかあったり[1][2][3]で、鍵がそのような弱い鍵でないか調べるサイトとして米ミシガン大学のチームのfactorable.netというサイトがあり、PEM形式の証明書を貼れば調べることができます。

でも、これって発行済の(他のサイトの)証明書を調べるツールなわけで、自分の証明書を発行してもらってから鍵がダメだったってわかっても、再発行にはお金もかかるし、なんで公開鍵や証明書発行要求(CSR,PKCS#10)でチェックしてくれないのかなぁと思ったわけす。証明書発行要求時点でわかれば鍵ペア生成し直せばいいだけですから。

factorable.netの管理している方へ「証明書発行要求に対応してくんない?事前にチェックできた方が便利だと思うんだよねぇ。」みたいなメールを送ってもみたんですが「ナイスな改善提案ありがと。でも他にもToDoがあっていつ直せるかっていうのは約束できない。対応したら連絡するね。」という旨のメールが来てやんわり断られました。とほほ。

OpenSSLで鍵生成したならこんな感じで秘密鍵から自己署名証明書をとりあえず作ってチェックすればいいんだけど、

% openssl req -new -key aaa.prv -x509 -subj /C=JP/O=TEST1 -set_serial 1 -days 3652 -out aaa.cer
#できたaaa.cerをfactorable.netでチェックすればよいです。
WindowsやHSMなんか使っている場合には、やはり証明書発行要求で事前チェックをするのが王道かなと。

仕方ないので簡単なツールを作りました。

jsrsasign: CSR to certificate converter:
http://kjur.github.io/jsrsasign/tool_forfact.html
jsrsasignを使って証明書発行要求から公開鍵をひっこ抜いて、適当な公開鍵証明書の形にでっちあげて、証明書の署名値はいいかげんな値に設定したニセの証明書を作ってしまえば、factorable.net で公開鍵が弱くないかチェックできるようになります。

これから発行してもらおうとしている証明書発行要求をツールに貼付けて「Convert」ボタンを押せばニセ証明書ができます。 (署名値は0x0102030405060708です。適当すぎますか?(^^;)
CSR-Self Cert Converter
この生成されたニセ証明書をfactorable.netのチェッカーにかければ、証明書発行要求とそれに紐づく鍵が弱い鍵でないかチェックすることができます。めでたしめでたし。
factorable.net key checker

factorable.net keychecker result

というわけでひっそりとjsrsasign 4.2.2を昨晩リリースしました。AuthorityKeyIdentifier証明書拡張に対応してくんない?というリクエストもあったので追加しときました。

今日はこの辺で

GlobalSignのルート証明書の2014年1月28日の期限切れ(小ネタ)

oauth.jp: Y!J API が止まった日 - GlobalSign の Root 証明書切れから学んだこと
http://oauth.jp/blog/2014/01/30/globalsign-root-cert-expired/
(引用) 昨日あたりから、Yahoo! Wallet や YConnect といった、Yahoo! Japan の API にアクセスできなくなったって人、ちらほらいるかもしれませんね。
というブログの記事を見つけまして、ざっと目を通してみてもよくわからなかったのでちょっと証明書など見てみました。

試しに https://userinfo.yahooapis.jpに繋いでみても問題なさそう。

ちゃんとした説明はYahooデベロッパーネットワークの「WebAPIやOpenIDでSSLエラーが起きる現象につきまして(2014.01.29)」に書いてありました。

GlobalSignのリポジトリには2つのルート証明書があって有効期限が切れたのはこのページの下の方の証明書みたいです。最初は、検証ができないというので相互認証してたり、鍵更新のあたりがおかしいのかと疑って証明書をいろいろみてみたわけです。

最新のブラウザで表示される検証の成功する証明書のチェーンは以下のようでした。

ルートCA証明書
シリアル番号04:00:00:00:00:01:15:4b:5a:c3:94
署名アルゴリズムSHA1withRSA
主体者名C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
有効期間1998/09/01-2028/01/28
主体者鍵ID607B661A450D97CA89502F7D04CD34A8FFFCFD4B
サブCA証明書
発行者名C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
主体者名C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA - G2
有効期間2011/04/13-2022/04/13
発行者鍵ID607B661A450D97CA89502F7D04CD34A8FFFCFD4B
主体者鍵ID5D46B28DC44B741CBBEDF573B63AB7388F759E7E
それじゃぁ、期限切れになった証明書を見てみると
期限切れになったルートCA証明書
シリアル番号02:00:00:00:00:00:d6:78:b7:94:05
署名アルゴリズムMD5withRSA
主体者名C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
有効期間1998/09/01-2014/01/28(確かに期限切れ)
主体者鍵ID607B661A450D97CA89502F7D04CD34A8FFFCFD4B(あれれ?)
これなんだかなぁ。主体者鍵IDが同じ、つまり同じルート鍵を使ったままで、有効期限とシリアル番号と署名アルゴリズムが違う証明書があるわけです。(そういえば前にみたっけ)。こういう事していいんでしたっけ?ルート鍵更新しなくていいんでしたっけ?

結局、クライアント側すなわちYahoo APIを使う側が、ルート証明書ストアをちゃんとアップデートしてなくて、そのために接続できなかっただけという事なんですね。(そう理解してから読むとブログの記事も呑みこめました。)

Debian 5だと問題だったと書いてあるので見てみるとDebianの場合には /etc/ssl/certs にルート証明書ストアがあって、ca-certificatesというパッケージでアップデートされているわけですがDebian 5は2012年2月6日にとっくにサポート終了になっているので、そりゃ文句を言ってもしかたがない。CentOS 5についてはフルアップデートは2014年Q1まで、メンテナンスサポートは2017年3月31日まで提供されるのでCentOS 5では今回の問題にはならないんだろうと思います。

結局、今回の影響はあまりなくて

  • ウェブブラウザを使っていてちゃんとアップデートをしている人にはあまり影響はなかったはず
  • OSのアップデートもちゃんとしている人にはあまり影響がなかったはず
  • CentOSにもOpenSSLトラストリストを持つようなパッケージは確かなかったっぽいので影響はない。CentOS 5もまだサポートされているので問題ないはず。
  • 他のLinux、なんとかBSDなんかもOpenSSLのトラストリストを持つパッケージが無いので問題なさそう。
  • Debian、Ubuntuだけはca-certificatesというパッケージがあるのでDebian5みたいなサポート終了しているものでは問題になるケースがあった。
というところなのかなと思います。

もっと面白い話が見つかるかと思ったけど、それほどでもなかったorz 鍵更新や相互認証じゃないっていうのはどうなんですかねぇ?

(小ネタ) Twitter REST API用の証明書の切り替え

@raysato さんのTLを見ていたらTwitter社の人のブログを紹介していて、以下のようなエントリがありました。

REST API SSL certificate updates
https://dev.twitter.com/blog/rest-api-ssl-certificate-updates
TwitterはAPI用の証明書を切り替えるそうです。

まじかー。api.twitter.comの証明書を見てみると、 確かに有効期限が2013年12月31日までになっとるなー。
g2
でもapi.twitter.comの証明書はちゃんとRSA 2048bit だからいいじゃんと思って 見てみたら、なるほどルートCA RSA 1024bit X.509v1証明書なんだね。そりゃだめだ。
path
認証サービスの共通ルールを作っているCA Browser Forumのガイド 「Baseline Requirements for the Issuance and Management of Publicly-Trusted Certificates, v.1.1.5」というのが 出ていて

2013-12-31
CAs SHALL confirm that the RSA Public Key is at least 2048 bits or that one of the following ECC curves is used: P-256, P-384, or P-521. A Root CA Certificate issued prior to 31 Dec. 2010 with an RSA key size less than 2048 bits MAY still serve as a trust anchor.
とあります。RSA 2048bit未満のCAは使えなくなっちゃうんだなぁと。

やべやべ、明日の資料を作らないと。

将来Google ChromeがSSL証明書のオンライン失効検証をやめて独自の失効情報プッシュを行うという困った話

2012年2月5日にGoogleのセキュリティ技術者Adam Langley氏のブログ "ImperialViolet"において Revocation checking and Chrome's CRL (05 Feb 2012) が公開され、ツイッターのタイムラインや ITmediaニュースの記事「Google Chrome、SSL証明書のオンライン失効チェックを無効に」にもニュースが出て、PKI、認証、セキュリティの関係者の間ではちょっとした騒ぎになったのでご覧になった方も 多いと思います。

Langley氏のブログ記事のポイントはこんな感じ

  • SSL証明書の失効検証をOCSPやCRLをダウンロードしオンラインで検証する方法を 将来のGoogle Chromeではやめにする。
  • その代わりに各認証局の発行するCRL情報をまとめて軽量化したCRLSetという情報をGoogleからプッシュすることにより、これを失効検証に用いる。
  • このような方針をとることにした理由は、
    • オンラインで失効検証ができない際、SSL証明書を有効としてしまうブラウザが他にも存在している
    • オンライン失効検証に係る通信や処理のオーバーヘッドがかなり大きい
  • EV SSLサーバー証明書の検証については、新しい方式を使うかどうかは未定
ここで、
ITmediaニュース記事「Google Chrome、SSL証明書のオンライン失効チェックを無効に」より引用
CAが発行する証明書をめぐっては、2011年に不正なSSL証明書が発行される事件が相次いだことを受け、主要ブラウザメーカーがソフトウェアアップデートを通じて証明書を失効させる措置を取った。Googleは今後、この仕組みを活用して、アップデートを使って失効した証明書のリストを管理していく方針だとしている。
の記事などにより「将来のGoogle Chromeはオンライン失効検証は行わず、(ブラックリストによる)ソフトウェアの再起動を伴うアップデートにより失効検証する方法を採用する」と勘違いされた方もいらっしゃるようだがImperialVioletのブログを読むと「現在はFireFox、Chrome、IEなど(ブラックリストによる)ソフトウェアアップデートによる失効をきたが」と、現状を紹介しているだけで、将来サポート予定といっているのは「失効リスト(CRLSet)をプッシュする方法(Pushing a revocation list)」であると述べられている。

それでは将来的にChromeではどのように失効情報提供しようとしているのか?

Googleはこれまでの

  • (場合によっては巨大な)CRLファイルによるものでもなく
  • 通信オーバーヘッドの大きいOCSPでもなく
  • 迅速に失効情報をアップデートできないブラウザやOSのブラックリストを使う方式でもなく
もっと軽量な失効情報のプッシュ方法を考えているそうだ。

crlsetツールから将来のGoogleの失効情報プッシュを想像する

「将来のGoogleの失効情報プッシュに関して興味があれば crlset というオープンソースのツールがあるので、これを見てみろ」とブログにあるので 早速見てみた。

GoogleはCRLの代わりにCRLSetというデータにより失効情報をGoogleから配信(プッシュ)しようとしているようだ。 crlsetというコマンドでは、CRLSetと呼んでいるデータをダウンロードしたり、 ダウンロードしたファイルを表示したりということができるようだ。

最新のGoogle Goをインストールし試そうと思ったがコンパイルできない。 ここにあるコードはGo1用のコードらしくビルドしようとすると"net/html"やら"json"やらパッケージの 場所やメソッドや不整合が起きる。(ムキーーーッ!!!) できるところまで、最新のGo用に書き直したがバカバカしくなってやめてしまった。 Goはコンパイラのチェックが厳しめなので、ちょっとツールを作ったり 試してみたりするのに全く向かない。

ソースコード見てもらえばわかる通り"crlset.go"は全く大したことをしていないので、 大まかにPerlで書き直した。(Rubyにすりゃよかったと途中で後悔)

Google ChromeのCRLSetダウンロードの動き

"crlset fetch"を実行するとCRLSetをダウンロードするためのメタファイル(XML)がダウンロードされる。 "./crlset fetch"で標準出力に表示されるXMLメタファイルの 内容はこんな感じだ。

<?xml version="1.0" encoding="UTF-8"?>
<gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod">
 <daystart elapsed_seconds="56280"/>
 <app appid="hfnkpimlhhgieaddgfemjhofmfblmnib" status="ok">
  <updatecheck
   codebase="http://www.gstatic.com/chrome/crlset/100/crl-set-10371439235811702542.crx.data"
   hash="" size="0" status="ok"
   version="100"/>
 </app>
</gupdate>
単にCRLSetというデータファイルの実体と、バージョン(CRLNumberみたいなものだ)を記載しているだけのメタファイルだ。

記載されたURLをダウンロードしてみると何かしらのヘッダ領域があり、ZIPファイルのデータがあることがわかる。 ZIPファイルのデータを取り出すと2つのファイルが含まれるZIPアーカイブであることがわかる。

  • manifest.json
  • crl-set
"manifest.json"の方には大した情報は無い。"CRLSet"のデータフォーマットのバージョンが記載されているだけだ。
{"name": "CRLSet", "version": "0"}

ZIPアーカイブに含まれるもうひとつの"crl-set"ファイルが今回調査すべきメインである。 Google Chromeのオープンソース部分であるChromiumの "net/base/crl_set.cc"の ソースコードにcrl-setファイルのデータ構造の定義が記載されており ざっくりとしたデータ構造の定義はこんな感じである。

・crl-setのJSON形式のメタデータのバイト長(2バイト)
・crl-setのJSON形式のメタデータの値文字列
・CAや中間CA毎にある失効情報の並び[]
 ・あるCAの失効情報(証明されてない失効リスト相当)
  ・parent_spki_sha256 - CA証明書のSubjectPublicKeyInfoのSHA256ハッシュ値バイト列
  ・失効した証明書のシリアル番号の並びの数(4byte非負整数)
  ・失効した証明書のシリアル番号情報び[]
   ・serial_length - シリアル番号のバイト数(1バイト)
   ・serial - シリアル番号のバイト列
注:"[]" は同じ要素が繰り返されることを示す
ここでJSON形式のメタデータの例を以下に示す。
{ "Version":0,
 "ContentType":"CRLSet",
 "Sequence":100,
 "DeltaFrom":0,
 "NumParents":35,
 "BlockedSPKIs":[]}
これらの情報からわかる将来のGoogle Chromeで計画しているCRLSetのpush配信の特徴を以下にまとめる。
  • 幾つかのCAまたは中間CAの発行するCRLをまとめたファイルである
  • CAの識別はCA証明書のSubjectPublicKeyInfoフィールドのSHA256ハッシュ値による
  • CRLSetはデジタル署名で保護されない
  • CRLSetはHTTP平文で配信される
  • ただの失効した証明書のシリアル番号のリストである
  • 失効時刻は記載されない
  • 失効理由などCRLエントリ拡張に相当するものは無い
  • CRLSetの世代管理は番号(Sequence値)により管理されている。(CRLのCRLNumber拡張と同等)
  • delta CRLにも対応している
この方法自体はEV SSLの推進、ガイドライン策定を行っているCA Browser Forumで提案されているものだそうだが、それが会員組織の総意を得られているのかはわからない。(PKI業界で最高に真っ当な有識者である議長のTimさんが納得するとは、ちょっと考えられないと思う。)

Googleは、CRLSetファイルをGoogleがプッシュ(=データ配信)するために認証局にCRL提供の呼び掛けを行っていくという事のようだ。

どれくらいCRLを圧縮できるのか

一つのCAが発行するCRLに対し、CRLからCRLSetに変換した場合、 ファイルサイズはどれくらい縮小されるのかを予想してみた。 鍵長やシリアル番号の桁数、拡張の有無なども影響するが、 ZIP圧縮の効果もあり概ね40%程度に圧縮されるものと思われる。

失効証明書数131,9674,596
シリアル番号バイト数1616
CRLファイルサイズ4.4MB157KB
CRLSetファイルサイズ(予想,ZIP圧縮前)2.2MB78KB
CRLSetファイルサイズ(予想)1.8MB63KB
CRLSetではZIP復元処理が2回あるのでCRLのASN.1の 処理コストと比較して5分5分といったところだろうか。

ちなみに、現在プッシュしているCRLSetはたった35のルートCA,中間CAしかサポートしていない。

ImperialVioletのブログの主張のおかしな点

「オンライン失効検証ができない場合様々な問題が起きる」として幾つか問題点を述べている。

  • 「"captive portal"(ホテルのインターネットなどでウェブブラウザで認証してから ネットが使えるようになる仕組みの事)などでは接続前はオンラインの失効検証が できない」としているが、その時点ではホテルのサービスの認証のページしか繋がる 必要が無いのであまり大きなリスクとも思えない。特定の問題なので 別に解決策もあると思う。
  • 「認証局のCRLを提供するリポジトリやOCSPレスポンダがダウンした場合、 そこが単一障害点になる」と述べており、まぁ、確かにその通りだが 認証局はそんなものダウンさせたら大問題になるし、 一般にそのための十分な冗長構成を備えているので 検証側がそれほど心配する問題ではない。
  • 「オンライン失効検証が失敗した場合に、検証が成功してしまう ブラウザがある」と述べており、過去にブラウザを幾つか調査している ようだが、検証結果にかなりの誤解と思いこみがあるんじゃないかと思う。 まず、大前提として一部のウェブブラウザではデフォルトで 失効検証が無効になっているものがあり、失効検証を有効にしてから でないとテストの意味がない。(デフォルトで失効検証ONにして ブラウザ等を提供して欲しいんですけどね。) あと、Microsoft等の製品ではオンラインで失効検証できない場合、 例えば最新のCRLを取得できない場合やOCSPレスポンスが取得できない 場合、キャッシュにあるCRLやWindows Vista以降でサポートされているLightweight OCSPのOCSPレスポンスが有効期間的に問題が無い場合これを利用して失効検証する。 また、証明書の検証結果もまた維持されるようになっており、 ブラウザの利用の途中で通信断があったとしても直近の検証結果を利用して SSLに用いる。ブラウザを再起動しないと検証結果の状態がクリアされない場合がある。 このように、設定、キャッシュ、認証結果の維持のために、 オフラインでも検証結果が「有効」となるブラウザがあるという事である。 また、オンラインかオフラインかにかかわらず失効検証できない場合は (RFC 5280的にも)証明書の検証結果は「無効」とするのが正しいし、 もしそれができないならブラウザの瑕疵だ。 いろいろ攻撃の例を述べているが、 攻撃者者がいくらオンライン失効検証ができないようにしたとしても、 失効検証ができない場合にはブラウザの証明書検証結果が「無効」になれば、 即ちフェールセーフになっていさえすれば問題がない。
  • 「以上に述べたオンライン失効検証の問題から、 「(オンライン失効検証ができない場合でも有効としてしまうブラウザがあるような)失効検証 の仕組みは、衝突するとポキッと折れてしまう車のシートベルトのようなものだ。 99%動作するかもしれないが、必要な時に動作しないのでは価値がない。」と述べている。 ブラウザがフェールセーフになっていれば99%のケースで使えれば全く問題がない。 これって、「銀行強盗、誤った本人確認や、行員の不正着服があったりして利用者の預金が 危険なので銀行の仕組みを一切やめて他の仕組みを使います。」みたいな話じゃないですか?
  • 「OCSPレスポンダへの通信の遅さや、OCSPレスポンダを使った際のIPを認証局が ログ取得できるためにユーザがどのサイトにアクセスしたのかを認証局が 知りえてしまうというプライバシーの問題がある」と述べている。 確かにOCSPレスポンダは、遅いものもあるし、検証の処理コストも高いが Lightweight OCSPを使ったり、CRLのキャッシュを使ったり オンライン失効検証のコストは小さくなるような工夫は認証局もブラウザもしている。 また、プロキシやNATもある状況で接続元IPと接続先の証明書中のホスト名が OCSPレスポンダに残っていることがそれほど大きなプライバシー問題になるだろうか?
以上の理由から、CRLやOCSPによるオンライン失効検証はやめて Google Chrome独自の失効検証方法に切り替えようとしているそうだ。 危険な話じゃないですか?

Google ChromeのCRLSetプッシュ方式の問題点

結局、CRLSetはGoogleのやる軽量なCRLアグリゲーションのようなものだ。

CRLSet失効情報が改ざんされてないと誰が証明してくれるのか?
CRLSetのGoogleからのプッシュでは、HTTPSは使わないし、デジタル署名もつかないようだ。 悪意のある中間者によりCRLSetが改ざんされたとしても、それを知る方法がない。 また、HTTPSもCRLSetを元に失効検証しているならHTTPSの証明書の有効性を判断できない。
Googleは誤ったCRLSetを発行したとしても多分罪を認めたりはしない
CRLSetのデータは各認証局から発行されているCRLを元にこれをまとめてCRLSetデータを 生成するが、CRLSet生成の過程でバグや故意の間違いがあったとしても、 有効な証明書が無効になったり、無効な証明書が有効になったりしても、 通信路の改ざん防止機能はないし、デジタル署名されているわけでもないので Googleの誤りなのか、通信路の問題か、中間者攻撃なのか判断ができない。 ニセのサイトにSSL接続して詐欺被害にあったとしても Googleは多分罪を認めたりはしないだろう。
Googleが回収したCRLを検証するかかなり怪しい
Googleは、申し入れのあった認証局からCRLをロボットにより回収し、 CRLSetを生成するようだが、個々のCRLの有効性、即ち正当な認証局から 発行されたCRLであるかを確認するかどうかはかなり怪しいと思う。 おそらく何も検証せずにCRLSetを生成するだろう。
Googleはビッグブラザーになりはしないか
GoogleがCRLを集約した(ふりをして)署名もしないCRLSetを発行することで、 Googleは証明書の検証結果を意図的にコントロールできる立場になったことに 注意しなければならない。 Googleの意向一つでCRLSetを発行でき、SSLサーバー証明書は有効にも無効にもできるのだ。
CRLSetのファイルサイズや発行周期が問題にならないか
CRLは認証局により発行周期が異なっている。毎日、3日おき、1週間おき、1ヶ月おき等 さまざまであるが、CRLSetを更新する周期はどうするのか、頻度に高いものに あわせるのか気になるところだ。また、CRLSetは複数のCRLをまとめたデータとなるので 現行の全てのルートCA、中間CAをサポートするとなれば巨大なファイルサイズになることが 予想される。(ルートCAだけでも400近く、中間CAも含めたら3倍以上になるのではと想像する。 一回のアップデートで使うかどうかもわからないほとんど無用な失効情報をダウンロードするならば 現行の必要なCRLだけをダウンロード、キャッシュして使う方が効率的ではないだろうか。
全てのCRL発行モデルに対応できるのか
CRLSetはdelta CRLには対応しているようだが、CRL/ARLモデルなど一部の 発行モデルで対応できないケースが無いだろうか。
OCSPでしか失効情報を提供していない場合どうするか
認証局によってはOCSPでしか失効情報を提供しないものもあるが、 そのような場合にはCRLSetでは対応できない。
CRLSetはCRLほどは新鮮でない
CRLSetは認証局がCRLを発行してから、ある期間を経た後に 発行されるのでCRLほどは新鮮ではない。1日以上のタイムラグは 覚悟しておく必要があるだろう。 失効情報の鮮度という意味ではOCSPもまた多くの場合、 CRLの失効情報を元にOCSPレスポンスの値が決まるケースが多いので CRLとほぼ同等かちょっと古いかだ。
結局はCRLSetを発行するGoogleの監査スキームが 最も重要なポイントなんだと思う。

おわりに

私は個人的にOCSPが嫌いでOCSPレスポンダ証明書をちゃんと検証してるよね?とか、 OCSPレスポンス検証のオーバーヘッドだってかえって大きくなるぐらいだよねとか、PKIを ややこしくしていると思っていてAdamさんのOCSPに対する文句もわからなくはないが、 かといってCRLSetプッシュもまた多くの問題を抱えていることは、このブログで 少しは知っていただけたのではないかと思う。

オンライン失効検証にこだわる必要はあまりなく、 CRLをキャッシュして使い、オフラインでも、通信障害でもCRLが取れなければ、 nextUpdate的に問題なければそれを使うというので全く問題無いように思う。 キャッシュされたCRLを使う方がCRLSetを使うよりよっぽど良い。 スマホなんかはディスク容量いっぱいあるしね、、、

参考リンク

米ユタのDigiCertとは無関係なマレーシアのDigicert Sdn認証局の問題について見てみたぞ(補足1)

昨日書いたマレーシアのDigicert Sdn認証局の記事で ちょっと補足しておこうと思います。

CRLについて

  • Digicert Sdnの問題を指摘された2つの中間CAは、 発行した証明書にCRL配布点(CDP)拡張は無いんだけども、 CRL自体はきちんと3日おきに発行しているようです。
  • Entrustは、 Digicert Sdnの中間CAを少し移行までの猶予期間を持たせ 11月8日かそれより前に失効させると声明しています。 現時点(11月7日18:50 JST)では失効されていません。
  • GTE CyberTrust Global Root(Verizon)は 失効させるといった声明はありません。 現時点(11月7日18:50 JST)では失効されていません。
CRLの発行周期および最新のCRLの発行日の情報は以下の通りです。
認証局名発行周期thisUpdatenextUpdate
Entrust.net CA 2048 ルート認証局7日2011年11月6日2011年11月13日
Digisign Server ID - (Enrich) (Entrust用)中間認証局3日2011年11月6日2011年11月8日
GTE CyberTrust Global Root ルート認証局3ヶ月2011年11月1日2012年2月4日
Digisign Server ID (Enrich) (GTE用)中間認証局3日2011年11月6日2011年11月8日

Mozilla(FireFox)の認証局ブラックリスト追加のソースコードの更新

Mozillaでは前回のDigiNotarの証明書をブラックリストに入れる際、 certdata.txt に証明書を登録し、これからコード certdata.c を自動生成しています。

http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt
このファイルの最終更新は2011年11月3日ですが、まだDigicert Sdnに 対応はしていないようです。

以上、ちょっと補足でした。アップデートがあれば、また書きます。

関連記事

米ユタのDigiCertとは無関係なマレーシアのDigicert Sdn認証局の問題について見てみたぞ

2011年11月3日のニュース でマレーシアのDigicert Sdn. Bhd.社という認証局が問題のある証明書を発行しており

  • 現在、解読が可能とされている512bitのRSA鍵の証明書を発行している
  • SSLサーバー証明書として使うには証明書の拡張領域に問題があった
  • マレーシア政府機関に発行したものにも512bitの弱い鍵が使われている
  • 発行した22枚の証明書で512bit鍵が使われている
そのような運用が問題視され、
  • MicrosoftやMozillaが問題のあったマレーシアのDigicert Sdnの中間証明書を ブラックリストに入れた。FireFoxでは8からの対応になる。
  • Digicert Sdnの上位のルート認証局であるEntrust社は問題のある中間証明書を、少し移行までの猶予を持たせ11月8日かそれより前に失効させる
という対応を取りました。

最初、ツイッターなどでこの問題が紹介されたとき米ユタ州にある割と 有名な認証局Digicertの子会社が問題が起こしたのかと 勘違いされていたようですが、全く別のマレーシアの会社だったようで 米DigiCert社も声明を出しています。 米DigiCert社は先日のオランダのDigiNotar社の時も 名前が似てたため「うちは関係ないよ」と声明だしており、最近踏んだり蹴ったりですねw。 さて、今日はこのマレーシアのDigicert Sdn認証局について、 ちょっと見てみたので報告したいと思います。

マレーシアDigicert Sdn社の幾つかの認証局

マレーシアのDigicert Sdn社はルート、中間を含め(おそらく)13もの認証局を持っています。我々に危険性の影響があるのは図の左側、多くのブラウザに信頼するルート認証局として搭載されている EntrustとGTE CyberTrust(現Verizon)をルート認証局とする 2つの中間認証局です。
fig1
Digicert社のそれぞれの認証局の特徴などを下表にまとめてみました。

認証局特徴
ルート認証局
Digicert Class2 Root 組織、個人(18歳以上)向けに発行する下位CAを持つ信頼レベル高中のルート認証局
Digicert Class1 Root 個人向けに発行する下位CAを持つ信頼レベル低のルート認証局
Malaysia Primier CA 1024 SHA1withRSA 1024bit
大量にMD5withRSAユーザ証明書を発行
他社ルートの中間認証局
Digisign Server ID (Enrich) 上位CAはGTE CyberTrust Global Root
自己署名証明書は公開してなさそう
SSLサーバー証明書と(証明書管理者用?)ユーザ証明書を発行
Digisign Server ID - (Enrich) 上位CAはEntrust.net Certification Authority (2048)
自己署名証明書は公開してる
SSLサーバー証明書と(証明書管理者用?)ユーザ証明書を発行
上のとは " - "(ハイフン)が違う
Digicert Class2 Root下位の中間認証局
Digisign Server ID SHA1withRSA 1024bit
証明書管理者用のユーザ証明書を発行しているようだ
金融系やカード系が多い
Digisign ID (Enhanced) S/MIMEにも使えそうなユーザ証明書を発行
変なプライベート拡張がある
Digisign ID (Basic) 一般のユーザ証明書を発行しているようだ
MyKAD Online 一般のユーザ証明書を発行しているようだ
DIGISIGN iVEST CA ユーザ証明書かS/MIME証明書か?
DIGISIGN iVEST CA Enhanced ユーザ証明書かS/MIME証明書か?
Digicert Class1 Root下位の中間認証局
DigiSign ID 現在でも大量のRSA 512bit鍵のユーザ証明書を発行しているようだ
Digisign Corporate Email 本中間CA証明書は2006年に期限切れ
下にユーザ証明書は見当たらず
これらのすべての認証局証明書の鍵長は 1024bitか2048bitで証明書プロファイルも 特に問題になりそうな点は見つかりませんでした。 他にも
  • CIMB Investment Bank Berhad Enterprise CA
  • Bank Negara Malaysia Sub CA
などマレーシアの銀行の認証局を運用しているようですが、 証明書が見つからず調査できませんでした。

EntrustとGTE CyberTrustルートのDigicert Sdn中間認証局

マレーシアのDigicert Sdnのルート証明書はIEやFireFoxなどの ルート証明書には搭載されておらず、 今回、Microsoft や Mozillaがブラックリストに入れたのは EntrustやGTE CyberTrustをルート認証局とするDigicert Sdnの 中間CA証明書です。 IEでみるとGTE CyberTrustルートの場合、証明書チェーンはこんな感じ、
certview-gte
IEでみるとEntrustルートの場合、証明書チェーンはこんな感じです。
certview-entu
両者を少し数字で比較してみましょう。

比較項目GTE CyberTrustルートEntrustルート
(a) 証明書発行枚数(2011年11月5日時点、延べ) 1198枚 984枚
(b) (a)のうち2011年11月3日時点で有効なもの 110枚 448枚
(c) (a)のうち2011年11月3日時点で有効なマレーシア政府のもの 69枚 205枚
(d) (a)のうちRSA512bit鍵のもの 37枚 8枚
(e) (a)のうちRSA512bit鍵で現時点(11/5)で有効なもの 7枚 7枚
(f) (a)のうちRSA512bit鍵で現時点(11/5)で有効なマレーシア政府ドメインのもの 0枚 5枚
ニュースで取り上げられている22枚という数字は どこから出てきたものなのかよくわかりませんね。

現在、解読された実績のある512bit RSA鍵の証明書を発行している ことは問題といえば問題ですが、利用者が鍵を生成して 証明書発行要求しているわけですから利用者側にも問題がありますよね。

問題のある証明書拡張領域とは?

拡張領域の違いはGTE CyberTrustルートとEntrustルートでは なくて、鍵長により微妙に拡張が違うようです。 これは鍵長2048bitのもの。
certext-gte1
これは512bitのものです。
certext-entu1
ニュースでは、通常TLSサーバー用とか TLSクライアント用とか書かれる 拡張鍵使用目的(Extended Key Usage)がないとか、他にも 拡張でおかしなところがあると言っています。 おかしなところをヤバい順にまとめてみましょう。

CRL配布点(CDP:CRL Distribution Points)が無い
これが無いため証明書を失効させることができません。 今回のように発行した証明書に問題があった時に失効できないことはホント致命的。
KeyUsageがないものがある
512bit RSA鍵の場合に拡張が無いようです。 RFC 3280的にはTLSでは署名検証に使うので必須(MUST)ですね。
拡張鍵使用目的(EKU:Extended Key Usage)がない
必須ではなかった気がしますが普通ついてます。
KeyUsageがあっても、不要なビットが立っている
Key Usage拡張は512bitより大きい鍵の証明書では有るようですが、 値としてDigital Signature、Non-Repudiation、Key Encipherment、 Data Enciphermentのビットが立っています。 SSLサーバー証明書ではNon-Repudiation、Data Enciphermentは余計ですよね。
RFC 5280 4.2.1.12 Extended Key Usageより
If a certificate contains both a key usage extension and an extended key usage extension, then both extensions MUST be processed independently and the certificate MUST only be used for a purpose consistent with both extensions.
中略
id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
-- TLS WWW server authentication
-- Key usage bits that may be consistent: digitalSignature,
-- keyEncipherment or keyAgreement
RFC 5280ではExtended Key UsageとKey Usageが一貫している 事がMUSTになっています。
基本制約(Basic Constraints)が無い
なければ認証局証明書でないってことなんですが、一般にはつけることが多いですよね。 随分昔、あるメーラーで基本制約が無いことを無視して、ユーザ証明書から下位証明書発行しても検証成功だったことを発見してしまったり、、、
Authority/Subject Key Identifierで64bitは最近珍しい
ですよね?
結局、CRL配布点拡張がなく失効できないというのが一番の問題 だったんだと思います。失効できていれば、 単に問題のあった証明書を失効させ、鍵長や拡張領域に 問題があったとしても正しいものを再発行すれば よかっただけで、こんなに大きな問題にはならなかったはずです。 失効できないために認証局丸ごとブラックリスト化するしか 手が無かったわけです。 ニュースではEKUが無いのがおかしいとか わけのわからない事指摘してますよね。

CPS(認証実施規程)と照らしてどうなの?

認証局ではCPS(認証実施規程)で定めた運用に従い 証明書を発行するわけですが、これと照らしてどうだったのか Digicert SdnのCPSを ちょっと見てみました。

  • 鍵長が512bit以下ではダメだという記述は見当たらなかったので CPS的に512bitの鍵に対して証明書発行することは問題が無かったようだ。
  • 拡張領域については単に使用可能な拡張をまとめているだけで 発行する証明書の用途ごとに証明書プロファイルを定めて いなかったのでCDP拡張など拡張が不足していたり問題があったと してもCPS違反になることは無い。
とまぁ、このような感じでCPSに違反しているということは 無かったようです。

ただ、CPS中の証明書プロファイルについて、どのような拡張が 必ず含まれるのか、含まれないのか明確になっておらず、 CRL配布点拡張が無いという認証局設計上の重大な欠陥が 明らかになってこなかったという問題はありますけどね。

今回の問題に対する評価はこれでいいのか

今回の問題は、COMODOやDigiNotarのように攻撃されて サブCAやRAが乗っ取られ不正な証明書を出し放題になっていたわけでも なく、同列に問題を語られているのは違和感を覚えます。 高々、認証局ではなくSSLサーバ証明書の鍵が不正に使われるだけですよね。 512bit鍵の証明書を発行してしまったのは、利用者(お客さん)にも 問題があったわけですよね。 とても悔やまれるのはCRL Distribution Points拡張が 入っていなかったその一点です。 それさえ入っていれば、問題が発覚しても 単に証明書再発行すれば済んだのに、 中間CA証明書のブラックリスト入りという結果になってしまいました。 同じCAから発行されているSSLサーバー証明書でも 拡張のまともなものもあり
certext-entu3ok
完全にとばっちりを食ったお客さんも多数いるわけですよね。 可哀想だなぁと思います。

GTE CyberTrust Global Rootを運用しているVerizonからは 何のコメントも無いのも変な感じですよね。

おわりに

以上、マレーシアのDigicert Sdnの認証局の問題について ちょっと調べたところを報告しまいた。 512 bit RSA鍵が問題だみたいなニュースの論調ですが、 あれはユーザの鍵なのでCA鍵と違って危殆化しても大した問題では なくて、それよりもCRL配布点拡張が無いことにより失効の手立てがなく、 中間CA自体を廃棄するしか手が無かったってことが問題だったわけです。

やべやべ、夜更かししちゃったよ。 ではでは、、、

関連リンク

小ネタ:FireFoxとIEでのIPアドレスのSubjectAltName dNSNameの扱いの違い

今日は小ネタです。

今日、某IPアドレスで書かれたサイトにHTTPSでアクセスしてみると うむむ、FireFox 3.6.23だと 信頼できない接続のアラートが、、、
ipadr1

IE8だと問題ありません。
ipadr2

んなアホな。 うむむと思ってSSLサーバー証明書を見てみると

SubjectAltNameのGeneralName値が

dNSName: 192.168.1.5

みたいにDNS NameのところにIPアドレスが 書いてある証明書のせいみたいなんです。

RFC 3280 ではsubjectAltNameにドメイン名を入れる場合には dNSNameフィールドに入れなければならず(MUST)、 RFC 1034の"prefered name syntax"でなければ ならない(MUST)となっています。

RFC 3280 4.2.1.7 SubjectAltNameより
When the subjectAltName extension contains a domain name system label, the domain name MUST be stored in the dNSName (an IA5String). The name MUST be in the "preferred name syntax," as specified by RFC 1034 [RFC 1034].

で、RFC 1034のpreferred name syntaxを見てみると 普通のFQDNドメイン名でありラベルの先頭は英大小文字の A-Zにでなければならないので、 dNSNameには "192.168.1.5" のようなIPアドレスは 入れてはならないことになります。

IPアドレスを指定したい場合にはiPAddressフィールドが使えますよね。

GeneralName ::= CHOICE {
   otherName            [0]   OtherName,
   rfc822Name           [1]   IA5String,
   dNSName             [2]   IA5String,
   x400Address           [3]   ORAddress,
   directoryName          [4]   Name,
   ediPartyName          [5]   EDIPartyName,
   uniformResourceIdentifier    [6]   IA5String,
   iPAddress            [7]   OCTET STRING,
   registeredID          [8]   OBJECT IDENTIFIER }

FireFoxは厳密にsubjectAltName dNSNameをみて それがFQDNでないとリジェクトしちゃうけども、 IE8はIPアドレスが書いてあっても通してしまうと、、、 結局は発行した証明書のsubjectAltNameが 間違ってるってことなんですが誰に言えばいいんですかねぇ、、、

最新記事
Categories
Archives
Twitter
記事Google検索

本ブログ内をGoogle検索
Yahoo!アクセス解析
Travel Advisor
記事検索
QRコード
QRコード
  • ライブドアブログ