自堕落な技術者の日記

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

署名

I♡S/MIME(Mac、iPhone、Outlook 2013、Office 365のS/MIME署名暗号メールの設定与太話)

唐突ですが、私はS/MIME暗号メールが大好きだ。PGPが大嫌いなのに対してS/MIMEが大好きだ。何故ならばデジタル証明書が大好きだからだ。さらにはデータフォーマットがCMSやPKCS#7でありこれも大好物だからだ。S/MIMEは多くのメーラーで標準サポートされており奇妙なプラグインやソフトウェアを入れなくても、証明書さえあればすぐに使えるところが素晴らしい。こんな私に対して、最近首をつっこんでしまったインシデントレスポンスの世界ではPGPを強要される。標準でサポートするメーラーなど一つも無いのにもかかわらずだ。酷すぎる。 私にとある紳士がgmail.comアドレス用にパブリックなS/MIME用証明書を発行してくださった。(ありがたや、ありがたや) 本当は、Androidで良いS/MIME対応のメーラーを調べるために発行してもらったのだけど、幾つかみてみたものの結局ロクなメーラーは無かった。

最近、S/MIMEネタから遠ざかっていたが、今日からゴールデンウィークでもあり暇だし(本当はクソでかい宿題があるのだが全くやる気がおきず)、幾つか設定してみたS/MIMEメーラーについて紹介がてら徒然なるままに書いてみたいと思う。

注意:以下に書いたことは私の無知から間違っていることもあるかもしれないので、その時はいろんな方法で教えてください m(_ _)m

iOS 8.3 標準メーラー

前にも紹介しているがiOSの標準のメーラーはS/MIMEに対応しており、かなりしっかり作ってあり、AppleはPKIやSSLやS/MIMEに前向きで「良い会社だなぁ」と思う。

iOSで、S/MIMEを使えるようにするには、まずPKCS#12形式のS/MIME用証明書(と鍵)、必要な中間証明書などを、まずメールでiOSのデバイスに添付ファイルで送ってやる。添付ファイルを開くと、プロファイル設定の画面が出るので、これに従うとこれらがインストールされる。

iOS標準メーラーのS/MIME設定

次にメールアカウントでS/MIMEの設定をする。「設定>メール/連絡先/カレンダー>(S/MIMEを使うアカウント)>アカウント>詳細>S/MIME」で、S/MIMEをオンにして、証明書を選択する。あとは設定は好みだが、私は「署名=はい」「デフォルトで暗号化=いいえ」にして使っている。
smime20
smime21
smime22

iOS標準メーラーのS/MIMEメール受信

S/MIME署名暗号メールを受信するとこのようにアイコン表示され、正しい署名がついており、暗号化されて送られてきたことがわかるようになっている。差出人の箇所をクリックすると、メールの署名暗号化の状態が表示される。シンプルなインタフェースだが、まずまずの使い勝手だと思う。例えば暗号化のみのメールを受信した場合、以下のようになる。
smime16
smime17
署名暗号化されたメールの場合には以下のようになる。
smime18
smime19

iOS標準メーラーのS/MIMEメール送信

送信時は、先ほど設定した通り、全てのメールに対してS/MIME署名が付与されてしまい、メッセージ毎に署名の有無を切り替えられず、少し面倒だ。相手に暗号化してメールを送ろうとしたが、なぜかうまくいかなかった。前はできていたような気がするのだけど、、、

Mac OS X標準メーラー

Mac OS Xの標準メーラーもまたプラグイン不要でS/MIMEに対応している。 キーチェインに自分のメールアドレス用のS/MIME証明書(と鍵)、相手のS/MIME証明書を登録しておけば、送信時に署名や暗号化ができるようになる。

Mac OS X標準メーラーのS/MIME設定

アプリ「キーチェーンアクセス」を起動し、自分のS/MIME用証明書と鍵をインポートします。次に、標準メーラーを起動し、「環境設定」メニュー>「アカウント」タブを選び、なぜか「TLS証明書」の箇所で、登録した自分のS/MIME用証明書を選択します。
smimea01_

Mac OS X標準メーラーのS/MIMEメール送信

送信画面は以下のようになる。鍵やメダル (?)のボタンを押せば、暗号化、署名ができる。
smimea05_

Mac OS X標準メーラーのS/MIMEメール受信

受信した場合の表示は非常に地味で、詳細表示をしないと署名の有無がわからないのは非常に残念。 署名メール、暗号化のみのメール、署名暗号メールを受信した場合の表示はそれぞれ以下の通り。
smimea04_
smimea03_
smimea02_

Outlook 2013 for Windows

Outlook 2013のS/MIME設定

Outlook 2013のS/MIME設定はとてもわかりにくいところにある。もう、S/MIMEなんか使わせたくないんじゃないかと思うくらいだ。メニューの「ファイル>オプション>セキュリティセンター>Outlookセキュリティセンターの詳細設定>電子メールのセキュリティ」から設定することができる。証明書が設定されていれば、以下のようになる。
smime01
規定の設定の「設定」ボタンを押すと更に詳細設定ができる。
smime02
で、これみて気づいちゃいました。Outlook 2013 署名と暗号化のアルゴリズム設定が、まともになったんですよ。前は、Thunderbirdぐらいだけのもんだったんですけどね。署名のハッシュアルゴリズムはSHA1、SHA256、SHA384、SHA512、暗号化アルゴリズムはRC2 64bit、RC2 128bit、3DES、AES 128bit、AES 192bit、AES 256bitから選べます。すごいですよねぇ。さすがにDESはもう無くなりましたが、RC2はまだあるんですねぇ。古いメーラーとの互換性を気にするならSHA1、3DESのチョイスで、新しくて良いならSHA256、AES 128bitあたりがいいんじゃないですかね。

Outlook 2013のS/MIMEメール送信

Outlook 2013では、返信しようとするとき、メインウィンドウの中の右側に返信ウィンドウが表示されますが、あのままだとS/MIME使えないんですよ。も〜やる気あんのか?っていう。「ポップアウト」ボタンで別ウィンドウにしてから設定します。で、ポップアップしたとしてもですねぇ、署名、暗号化がとても探しにくい位置にあるんですよ。「も〜やる気あんのか!(Part2)」と。タブの「オプション>アクセス許可」なかにひっそりとあります。
smime04
これじゃ、あまりに寂しいので、リボンを右クリックして、リボンの編集機能で追加してしまいます。
smime03
ほら、メール送信ウィンドウから、すぐに署名、暗号メールが送れてしまいます。(素晴らしい)
smime05

Outlook 2013の連絡先のS/MIME証明書の登録

私の設定が間違っているだけなのかもしれないけど、Outlook 2013で署名メールを受け取ったら、自動的に証明書が連絡先に登録されるわけではなく、手作業でいちいち登録しなければならないようだ。非常に面倒臭い。(シンジラレナイ!)

送信先のS/MIME証明書ファイルを持っていないなら、S/MIME署名メッセージから取り出すことができます。Outlook 2013で署名メッセージを開き、赤いリボンをダブルクリックすると署名プロパティダイアログが表示されます。「詳細ボタン>署名者を選択>詳細の表示ボタン>証明書の表示ボタン>詳細>ファイルにコピー」でエクスポートすることができます。「も〜やる気あんのか!(Part3)」

送信相手のS/MIME証明書を登録しておくには、まず、Outlook連絡先のカードを開く必要があります。(これも非常に探しにくい。) 2通り開く方法があります。

  1. Outlookのメインウィンドウの下にある「連絡先」リンクを開き、対象の人をダブルクリックする。
  2. メインウィンドウで相手からのメールを開いている状態で、メールアドレスを右クリックし「連絡先カードを開く」を選択、「変更の保存先 Outlook 連絡先」をダブルクリック。
送り先の証明書を登録するには、上方真ん中の辺にある、「証明書」をクリックします。
smime06
先ほどダウンロードしておいた相手のS/MIME証明書をインポートして設定すると、こんな感じになります。
smime07

Outlook 2013のS/MIMEメールの受信

S/MIMEの署名だけのメール、暗号化だけのメール、署名暗号化されたメールを受信すると、メッセージの表示はそれぞれ下のようになります。
smime10
smime11
smime12
署名に問題があった場合には、ちゃんと警告も出ます。ただ、メッセージ一覧のところできになるところがあって、S/MIMEの時に赤リボンや黄色鍵が表示されるのはいいんですが、
smime08
PGP署名メールでも検証する気もないのに赤リボンが表示されるんですよね。これは如何なものかと、、、
smime09

Office 365 メール

Office 365のメールアプリでも標準プラグイン(アドオン)を使えば、ウェブアプリなのにクライアント側でS/MIMEに対応してしまう。アドオンはInternet ExplorerとFirefoxに対応しており、Chromeには対応していないようだ。

S/MIME用アドオンのインストール

画面キャプチャを撮り忘れてしまったのだが、メインウィンドウのメッセージを見る箇所で、S/MIMEメッセージの場合にリンクを辿っていけば、プラグインがダウンロードできる。"owasmime.msi"という名前のファイルだ。これをインストールしブラウザを再起動すればよい。

Office 365メールのS/MIMEメール送信

新規メールやメールの送信などで、編集ウィンドウを別ウィンドウにする。「…」のメニューがあるのでこれを開き、「メッセージオプションの表示」を選ぶと下記のダイアログが表示される。
smime13

ただ、何故かエラーができるようになってしまった。IE、FirefoxにかかわらずアドオンはWindowsキーストアの秘密鍵は読みに行こうとしているが署名ができない。また、送信先の公開鍵証明書も正しく選択できていないようだ。(前はちゃんと署名に成功した気がする。) ブラウザを再起動するなどすると復旧するかもしれない。

Office 365メールのS/MIMEメール受信

暗号メールを受信した場合には、場合によりWindowsキーストアの秘密鍵を使用する旨の確認ダイアログが出てから
smime14
別窓で暗号化メールが復号されて表示される。
smime15
アドオンの動作は私の環境ではとても不安定で、復号できたり、できなかったり、署名の赤リボンも表示されていたものが、最近全く表示されなくなってしまった。

おわりに

てなわけで、今晩はいくつかの手持ちのメーラーのS/MIME署名暗号メールの機能をみてみました。うまくいかないところもありましたが、ぼちぼち調べようとおもいます。ではでは。

関連記事

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。今日はこのへんで。

関連記事

W3C Web Cryptography APIとの果てしなき戦い(第2回 RSA署名生成と検証)

前回は、 W3C Web Cryptography APIについて、一番簡単そうなハッシュの生成を紹介しながら、 幾つかの課題について紹介しました。

今回は、W3C Web Cryptography APIによる、 RSA公開鍵暗号によるデジタル署名の生成と検証を紹介していこうと思います。

署名と検証の例題って、よく一人の人というかプログラムが、 鍵ペアを生成して、署名して、検証するサンプルを出しますよね。( sjclの楕円暗号のテストコードとか・・・) 一人の人が同時に署名と検証を行うってユースケースとしてありえないと思うんですよね。 実際、私が見た当時、sjclでは鍵オブジェクトの秘密鍵と公開鍵を 分けてエクスポートができないようで、実際問題使えないことがありました。

そんなわけで、今回はまず、ちゃんとOpenSSLで生成した秘密鍵と公開鍵をインポートして、 署名の生成と検証をできるようにしたいと思います。 その後で、RSAの鍵ペアの生成をします。

データの準備

W3C Web Cryptoで鍵生成してもよいのですが、今回はOpenSSLで作ったRSA 2048bitの 秘密鍵で署名することにしたいと思います。PKCS#5 PEM形式の2048bit RSA秘密鍵を生成し、 それを平文のPKCS#8 DER形式に変換し、 bin2hexスクリプト で16進数文字列表現に変換します。

% openssl genrsa 2048 > k2048.p5p.pem % openssl pkcs8 -topk8 -nocrypt -in k2048.p5p.pem -outform DER -out k2048.p8p.der % bin2hex < k2048.p8p.der > k2048.p8p.hex #16進数形式のRSA秘密鍵
鍵ペアとなる公開鍵について、同様に16進数文字列形式のものを取得します。
% openssl rsa -in k2048.p5p.pem -pubout -out k2048.pub.pem # PEM形式の公開鍵 % openssl rsa -in k2048.p5p.pem -pubout -outform DER -out k2048.pub.der #DER形式の公開鍵 % bin2hex < k2048.pub.der > k2048.pub.hex # 16進数形式のRSA公開鍵
次に"aaa"という文字列に対して署名するとして、この文字列が含まれる署名対象 データファイルを作っておきます。
% echo -n aaa > aaa.txt
OpenSSLで前述の秘密鍵と署名対象データを使ってSHA1で署名すると結果のデータは以下のように 作られます。同様に16進数データを作っておきます。
% openssl dgst -sha -sign k2048.p5p.pem aaa.txt > k2048oaaa.sig.bin % bin2hex < k2048oaaa.sig.bin > k2048oaaa.sig.hex
OpenSSLで前述の公開鍵と署名対象データと生成された署名値データを使って検証するには 以下のように行います。
% openssl dgst -sha1 -verify k2048.pub.pem -signature k2048oaaa.sig.bin aaa.txt Verified OK
署名値は正しいことがわかります。

秘密鍵のインポートと署名の生成

秘密鍵の16進数値を使って文字列"aaa"に対してSHA1withRSAで署名する場合の、 W3C Web Cryptoのコードは以下のようになります。

var prvHex = "308204bd02010030..."; // 前節の16進数秘密鍵 var prvUint8a = hextouint8a(prvHex); // 秘密鍵のUint8Array var aaaUint8a = asciitouint8a("aaa"); // 署名対象aaaのUint8Array // PKCS8形式の秘密鍵を署名用にインポート window.crypto.subtle.importKey( "pkcs8", prvUint8a, { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-1"} }, true, ["sign"] ).then( // 秘密鍵インポートに成功したら署名する function(prvKey) { console.log("**importKey** 成功"); console.log("prvkey=" + prvKey); return window.crypto.subtle.sign("RSASSA-PKCS1-v1_5", prvKey, aaaUint8a); }, function(e) { console.log("**importKey** エラー: " + e); } ).then( // 署名に成功したら署名値(ArrayBuffer)を16進数表示 function(sigVal) { console.log("**sign** 成功"); console.log("sigVal=" + abtohex(sigVal)); }, function(e) { console.log("**sign** エラー: " + e); } );
実装で注意しなければいけないポイントは以下の通りです。
  • OpenSSLの(平文の)PKCS#8秘密鍵を使うにはimportKeyで"pkcs8"を指定する。
  • 鍵使用目的で["sign"]を指定する。
コンソールに"sigVal="で表示された16進数の署名値は、 k2048oaaa.sig.hexファイルの値と同じになっていると思います。 hex2binスクリプト で署名値をバイナリデータに変換して、以下のようにOpenSSLで検証することが できます。うまく検証できたでしょうか。
署名値16進数をk2048waaa.sig.hexとして保存 % hex2bin < k2048waaa.sig.hex > k2048waaa.sig.bin openssl dgst -sha1 -verify k2048.pub.pem -signature k2048waaa.sig.bin aaa.txt Verified OK
hextouint8aについてはこちらをご覧ください。

公開鍵のインポートと署名の検証

前々節のOpenSSLで作った署名値でもよいですし、前節で生成された署名値でも よいですが、これをインポートした公開鍵で検証してみましょう。 以下のようなコードで検証することができます。

var pubHex = "30820122300d0609..."; // 前々節の16進公開鍵 var sigHex = "afd36b6f3f2af788..."; // 前節or前々節の16進署名値 var pubUint8a = hextouint8a(pubHex); // var sigUint8a = hextouint8a(sigHex); var aaaUint8a = asciitouint8a("aaa"); window.crypto.subtle.importKey( "spki", pubUint8a, { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-1"} }, true, ["verify"] ).then( function(pubKey) { console.log("**importKey** 成功"); console.log("pubKey=" + pubKey); return window.crypto.subtle.verify("RSASSA-PKCS1-v1_5", pubKey, sigUint8a, aaaUint8a); }, function(e) { console.log("**importKey** エラー: " + e); } ).then( function(isValid) { console.log("**verify** 処理成功"); if (isValid == true) { console.log("**verify** 署名検証成功(一致)"); } else { console.log("**verify** 署名検証失敗(不一致)"); } }, function(e) { console.log("**verify** エラー: " + e); } );
実装で注意するポイントは以下の通りです。
  • OpenSSLの公開鍵をインポートする際には"spki"を指定する。
  • インポートする際の鍵使用目的に"verify"を指定する。
  • 署名検証の結果はブール値(isValid)で返されるのでこれに従う。 関数が呼ばれただけで安心して終わりにしない。

RSA鍵ペアの生成

上の例ではインポートした秘密鍵、公開鍵を使っていますが、 鍵ペアの生成だってできます。(現状RSAだけのようですが・・・) RSA 2048bitの鍵ペアは以下のように生成します。

var paramKeyGen = { name: "RSASSA-PKCS1-v1_5", // 現状ではRSA-PSS, RSA-OAEPは指定できなそう modulusLength: 2048, // 鍵長 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 公開指数 65537 hash: { name: "SHA-256" } // 署名のハッシュアルゴリズム?別に利用外のを指定しても良い? }; window.crypto.subtle.generateKey( paramKeyGen, // 生成する鍵ペアのための鍵長等の各種パラメータ true, // エクスポート可能にするかどうかのフラグ ["sign", "verify"] // 鍵使用目的 ).then( function(key) { console.log("**generateKey** 成功"); console.log("秘密鍵:" + key.privateKey); console.log("公開鍵:" + key.publicKey); }, function(e) { console.log("**generateKey** エラー: " + e); } );

Web Crypto APIの困った所5:importKeyの融通の利かなさ

こうしてこのブログをすんなり見ていただくと、「W3C Web Cryptoって簡単じゃん」と 思われるかもしれませんが、このような動く例を見つけるまで、かなりの紆余曲折があり 時間がかかっています。importKeyの正しく動く例というのが、仕様に記載されておらず、 他の方のサンプルも動くものあり、動かないものあり、何が正しいのかよくわかりません。 importKeyの引数には、

  • format - 鍵データの形式 (pkcs8, spki, jwk, raw)
  • keyData - 鍵データ (ArrayBufferView(Uint8Array)かJSONデータ)
  • algorithm - アルゴリズムのJSONデータ
  • exportable - エクスポート可能かのブール値
  • keyUsage - 鍵使用目的の配列 ["sign", "verify"] 等
を指定しますが、仕様がイケてないと思うのは
  • 鍵のデータ形式など指定させる必要があるのか。公開鍵か秘密鍵のバイナリかはASN.1構造を見ればわかる話。JWKだって区別はできる。
  • アルゴリズムの指定も必要性がよくわからない。pkcs8、spkiであれば、鍵アルゴリズムが何であるかわかるし、鍵のインポートの際に署名アルゴリズムやハッシュアルゴリズムを指定させる 意味がわからない。"RSASSA-PKCS1-v1_5"にするか"RSA-PSS"にするかは、鍵インポート時に決める必要がない。署名のハッシュアルゴリズムについても同様に決める必要がないのに、"MD-5"などサポート外のアルゴリズムを指定するとエラーとなる。JWKデータも同様に鍵アルゴリズムの指定の必要がない。
  • keyUsageの指定の必要性もよくわからない。例えば、RSASSA-PKCS1-v1_5で秘密鍵をインポートしたらkeyUsageはsignに決まっており、省略できることの方が多い。
  • JSON等指定の自由度が非常に高い割に、値の指定を間違えるとすぐにエラーとなり融通が利かない。省略可能やデフォルト値を持つ引数、パラメータがあっても良さそうだが、そのようにはなっていない。
  • algorithmのhashのパラメータ値でMozillaのテストコードでは"SHA-1"となっているが、仕様上は{name: "SHA-1"}となるのが正しいようでこれならChromeでもFirefoxでも動作する。前述のように必要の無いパラメータの指定方法が原因で実装により動作するもの、しないものがあり、相互運用性の問題が生じている。
そのような意味では、jsrsasignのKEYUTIL.getKey()メソッドでは入力は極力自動解析し最小のパラメータで動作するようになっていて、秘密鍵であろうが、公開鍵であろうが、JSON形式であろうが、鍵が暗号化されていようが、鍵アルゴリズムが何であろうが、許容範囲の広い実装となっています。

Web Crypto APIの困った所6:アルゴリズムサポート状況の不明瞭

前回紹介したCan I Use CryptographyのページでChrome等いろんなブラウザが フルサポートかのような記述になっていますが、W3Cの勧告候補でも特にどのアルゴリズムは 実装必須となっているわけではないようで、ECDSA、RSA-PSSなど サポートしていないアルゴリズムはかなり多いです。(IE11+ではSHA-1未サポートのよう) この辺りについてスペックがどうなっているのかブラウザベンダーから正式な開示が 無いようですし、仕様上も何をサポートしているかを知る術が特になく、 動かしてみて動かなかったら未サポートのような状況になっています。 そもそも、Java JCEやOpenSSLなどに比べたら、 アルゴリズムの数が圧倒的に少ないのですから、全アルゴリズムを実装必須(MUST) としても良いぐらいではないかと思います。 また、Java JCEではどのようなアルゴリズムをサポートしているかを知るためのAPIがあります。 ブラウザ毎のアルゴリズムや機能のサポート状況の比較は、 そのうち表などで比較できればと思っています。

Web Crypto APIの困った所7:サポートアルゴリズムの狭さと変なバランス感

W3C Web Crypto APIでは、 MD5、RSA暗号(RSAES-PKCS1-v1_5)など現時点で脆弱とされているアルゴリズムは除外されており、 サポートされているアルゴリズムはかなり限定的で狭いものです。 後方互換性や相互運用性のために使いたいというケースもあるでしょうから、暗号ライブラリとしては、 サポートしても良いのかなと思ったりもします。 その割には、例えばFirefoxではRSA鍵の鍵長が256bit〜7168bitをサポートしており、むしろそちらの方を制限すべきなのでは?とも思ってしまいます。 また、FirefoxではECDSAをサポートしていないのに、ECDHはサポートしているなど、同じECCの鍵生成なのに、このあたりのバランス感や優先順位も奇妙に思います。

Web Crypto APIの困った所8:鍵生成のパラメータ

例えばRSA鍵生成のパラメータですが、RSA署名やRSA暗号化のアルゴリズムを 指定しなければならないのかわからず、公開指数の指定の仕方も面倒で、 何故ハッシュを指定しなければならないのかわかりません。 また、これらのパラメータは省略は一切許されていません。 間違えるとエラーとなり、どこが間違っているのかに関するエラーメッセージは どの実装も非常に不親切です。

var paramKeyGen = { name: "RSASSA-PKCS1-v1_5", // RSA-PSS, RSA-OAEPなど指定する必要なくRSAで十分では? modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 整数65537でいいのでは?Uint8Array面倒 hash: { name: "SHA-256" } // hashが必須な意味がわからない };

高い相互運用性のために

一連のシリーズでは、最も汎用性が高くなるように、 window.crypto、window.crypto.subtleを使っており、 FirefoxやChromeでそのまま動く動作コードになっています。 これらに加え、IEやSafariなどいろんなブラウザで動かそうとする場合には、 以下のようなコード先頭に入れ、

var WC = null; var WCS = null; if (window.msCrypto) WC = window.msCrypto; // IE11+ if (window.crypto) WC = window.crypto; // FF34+,CH37+ and others if (WC.subtle) WCS = WC.subtle; // IE11+,FF34+,CH37+ and others if (WC.webkitSubtle) WCS = WC.webkitSubtle; // Safari 7.1+
window.cryptoの代わりにWCを、 window.crypto.subtleの代わりにWCSを使えば、 どこでも動く可能性が高くなるかと思います。

おわりに

今回は、RSA鍵ペアの生成、署名生成、署名検証についてみてみました。 今日はこんなとこで。

関連記事

W3C Web Cryptography APIとの果てしなき戦い(第1回)

あけましておめでとうござます。 ウェブ関連技術の標準化を進めているW3Cから W3C Web Cryptography API という勧告候補が 出てまして、このAPIを使えば公開鍵暗号、共通鍵暗号、鍵交換、鍵生成、 暗号化、署名、ハッシュ関数、擬似乱数なんかが使えちゃうのだそう。 Twitterの私のリプライに「ほとんどのブラウザがサポートしてるから (jsrsasignでも) 使いなさいよ」と海外から何名かの方がコメントしてくださるので、 重い腰を上げて勉強してみたんですが、「ムキ〜〜っ!!わけわからん! 標準化って何なの?相互運用性著しく低いしっ。そもそも、 このAPIってJavaScriptを書くプログラマにちっとも優しくないよね!」 と怒り心頭なんですが、 年も明けたことですし、そのあたりのことを愚痴っぽく、 ぼちぼち書いてみたいと思います。

結論から言うと「今すぐ、これを使うとヤケドするので、 実装がこなれてきたり、様々なラッパーやユーティリティが整備される まで使うのは1、2年はお待ちなさい」という事かなと思います。

APIはどれくらい使えるの?

いろいろなウェブブラウザの機能のサポート状況を 公開してくれているサイトにcaniuse.comという サイトがあるのですが、そこで W3C Web Cryptography API の主要なウェブブラウザ毎のサポート状況 が公開されています。


fig1
(出典: Can I Use Web Cryptography)
グレーで囲まれているのが2015年1月時点で現行バージョンのブラウザで、 緑はフルサポート、黄緑は一部サポートを示しているんですが、 IE、Firefox、Chrome、Safari、Operaやスマホなどのほとんどブラウザで APIをサポートしていると言っています。 世界のブラウザシェアでは51.39%、日本では58.17%が APIをサポートしているのだそうです。 この図だけを見たら、問題なく簡単に使えそうな気がしちゃいますよね。

ハッシュ関数の例

それでは早速、ハッシュ関数の例を見ていきましょう。 文字列"aaa"のSHA-1ハッシュ値を計算するとします。 細かい関数は後で紹介していくとして、ハッシュ計算の流れは以下の例の ようになります。

var textBuf = asciitouint8a("aaa"); // ハッシュ対象文字列aaaをUint8Arrayに変換 window.crypto.subtle.digest({name: 'SHA-1'}, textBuf).then( // SHA1ハッシュを計算 function(hashValue) { // 成功した場合に呼び出される関数 console.log("sha1(aaa)=" + abtohex(hashValue)); // 結果ArrayBufferを16進数に }, function(error) { // 失敗した場合に呼び出される関数 console.log("sha1(aaa)エラー: " + error); } ); #文末にasciitouint8a, abtohexのコードはつけておきます。
APIのハッシュ関数、暗号化、鍵生成などの関数は、乱数生成を除いて 全て "window.crypto.subtle" の名前空間に入っており、 ハッシュ関数は "digest" となっています。

ハッシュの入力はHTML5で導入されたバイナリデータを扱うクラスUint8Arrayなど、 ハッシュの結果はArrayBufferクラスで帰ってきます。例では文字列から Uint8Array配列にしたり、ArrayBufferを16進数で表示できるようにユーティリティー関数を 使っています。

APIの殆ど全ての暗号機能は非同期実行APIになっており、 関数やメソッドが実行されても、すぐには結果が帰ってきません。 ウェブブラウザで、ある処理を行っている間、表示が固まったりしないように 非同期実行にしてあるのだそうです。(後日、突っ込みますw)

JavaScriptで非同期実行するには2通りの方法があるらしく、 windows.crypto.subtle.digest関数は非同期実行オブジェクトを返します。

  • Promiseパターンを使う方法(thenを使う。WebCryptでは主流?)
  • イベント(oncomplete,onerror)を使う方法(IE WebCryptで主流?)

Promiseパターンによる非同期実行

Promiseパターン、もしくはDeferredパターンと呼ばるデザインパターンは、 非同期処理は遅延実行を扱うパターンなのだそうです。 上の例ではdigest()関数により、非同期実行のためのPromiseオブジェクトが 生成され、処理が終わった際にどんな関数を実行するか、エラーが起きた際に どんな関数を実行するかをthen()メソッドで定義しておきます。

var promiseObj = new Promise(); promiseObj.then( 処理が終わった時に実行される関数, エラー発生時に実行される関数 );
Promiseパターンでは、非同期処理するオブジェクトをthenでチェーンすることにより、 処理1、処理2・・・のようにシーケンシャルに実行させることも可能です。
var promiseObj1 = new Promise(); promiseObj1 .then( function(result) { // 処理1が成功したら実行される関数 ... return new Promise(); // 新しい処理2の非同期処理オブジェクト } function(err) {...} ).then( function(result) { // 処理2が成功したら実行される関数 ... return new Promise(); // 新しい処理3の非同期処理オブジェクト } function(err) {...} ).then( // 処理3 );
Promiseパターンの方が、後述のイベントによる非同期実行よりも、 thenチェーンなど使えて綺麗に書けるので Web Crypto APIでは、 こちらの方が主流の使い方となるのだと思います。 Promiseパターンについて詳しく知りたい場合には、以下を参考に されると良いと思います。

イベントによる非同期実行

IEのWeb Crypto APIのサンプルでは、digest()で非同期実行オブジェクトを 生成するところまでは一緒ですが、これに処理が完了した場合に実行される 関数を参照するイベントプロパティ oncomplete と、エラーが発生した際に 実行される関数を参照するイベントプロパティ onerror を定義することにより ハッシュ計算を非同期実行しています。

var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); var digestValue; var crypto = window.msCrypto; if (crypto.subtle) { var op = crypto.subtle.digest({ name: "SHA-256" }, data); op.onerror = function (evt) { console.log("op.onerror event handler fired."); } op.oncomplete = function (evt) { digestValue = evt.target.result; console.log("op.oncomplete event handler fired, digest computation complete."); }; } else { console.log("Unable to create window.crypto object."); } (出典:MSDN: Web Cryptography: digest method)
IE 11+のW3C Web Cryptography APIでは、Promiseパターンではなく、 イベントによる方法しかサポートされていないのだと思います。

Web Crypto APIの困った所1:非同期実行

ここから、なんだか愚痴や文句っぽくなってきますorz W3C Web Cryptography APIの困ったなぁと思うのは、 (処理が大して重くないのに)非同期実行しかサポートされていないところです。 非同期実行は、それを使い始めてしまうと以降の全ての処理を非同期実行 しなければならず、途中の一部だけを非同期実行することができません。
fig2

非同期実行は鍵生成して、鍵を保管して、署名するといった一連の処理を まとめて非同期実行させて、表示が固まらないようにしたいのであり、 個々の暗号プリミティブレベルで非同期実行したいわけではないと思います。 暗号プリミティブを非同期実行するかはプログラマに任せてほしく、 暗号プリミティブは同期実行の方がよかったのではないかと思います。

IEと他のブラウザとで非同期実行の記述に一貫性が無いのも面倒だと思います。

Web Crypto APIの困った所2:名前空間が統一されてない

Can I useサイトやMSDNの例を見て「あれ?」と思った人もいると 思いますが、Web Crypto APIの名前空間って実装によって統一されている というわけではないんです。

  • window.crypto.subtle - Firefox、Chromeなど
  • window.msCrypt.subtle - IE11+
  • window.crypto.webkitSubtle - Safari, iOS Safari
実装の中身がブラウザによっていろいろ違うので、 名前で分かれていてもいいのかなとも思いますが、 そもそもW3Cで「標準化」してるんですよねぇ?と。 酷い話だなぁと思います。

Web Crypto APIの困った所3:ArrayBufferによるインタフェース

ハッシュや署名の入力はUint8ArrayといったArrayBufferViewのサブクラスでなければ いけなかったり、出力はArrayBufferになっていたりと、 文末のasciitouint8aやabtohexなど見てもらえれば判る通り、 処理するのが結構面倒くさいです。 ファイルなど大きなサイズのデータを扱う際にはわかりますが、 ハッシュの結果となるハッシュ値なんか大した大きさでないのに ArrayBufferで戻されます。

Web Crypto APIの困った所4:多態性のなさ

ハッシュ関数の入力に関して、文字列でも、整数は配列でも、Uint8Arrayでも 「ひとつよしなに」ハッシュを計算してくれてもよさそうなもんですが、 そうした 多態性(polymorphism)は無くて、 入力はUint8ArrayのようなArrayBufferViewでなければなりません。 多態性はJavaScriptの大きなメリットの一つだと思うんですが、 W3C Web Cryptography APIを使っていると、JavaScriptから Cで関数を呼び出ししているような気分になります。 (入力の融通のきかなさは次回他にも紹介します。)

Web Crypto APIの困った所5:ドキュメントやサンプルの少なさ

解説記事やサンプルを紹介しているサイトもあるのですが、そもそも、例が少ないですし、 それが希望のブラウザで動作するかわからず、コードの相互運用性に本当に苦労させられます。 また、ブラウザがどの機能をちゃんとサポートしているのか、よくわからず、公開ドキュメントも ないので、それが自分のコードのバグなのか仕様なのかよくわからない事も問題です。

おわりに

というわけで、今回は導入として、W3C Web Cryptography APIの雰囲気とハッシュ関数の例に ついて見てみました。 不勉強なため、認識違いをしている所もあると思いますが、その際にはコメント等でご指摘いただければ と思います。 次回以降、鍵生成、署名、共通鍵暗号等を紹介したり、 勉強になるサイトを紹介していこうと思います。 ではでは。

関連記事

(おまけ)例で使ったabtohex、asciitouint8aの定義

// ASCII文字列をUint8Arrayの配列に変換 function asciitouint8a(s) { var buf = new Uint8Array(s.length); for (var i = 0; i < s.length; i++) { buf[i] = s.charCodeAt(i); } return buf; } // ArrayBufferから16進数文字列に変換 function abtohex(arrayBuffer) { var s = ""; var dataView = new DataView(arrayBuffer); for (var i = 0; i < arrayBuffer.byteLength; i++) { var hex = dataView.getUint8(i).toString(16); hex = "00".substr(0, 2 - hex.length) + hex; s += hex; } return s; }

スライド「Bitcoinを技術的に理解する」の反響のお礼

一昨日、Bitcoinの技術解説のスライドをslideshare.netに公開したんですが、

難解な資料にもかかわらず、あまりの反響の多さに少し驚いています。

Untia1
二日ぐらいで17800を超えるslideshareへのアクセスを頂き、「it is one of the most popular this week on SlideShare」に選んで頂いたり、
たくさんTwitterでつぶやいて頂いたり、Facebookでいいねを頂いたり、
a2
はてなブックマークでもたくさんブックマークやコメントを頂いたり
a3
感謝至極でございます。この場を借りて御礼申し上げます。ありがとうございました。

(小ネタ)Bitcoin勉強会の資料を公開しましたよ

会社からの許可が下りたので(^^; 2014年6月に日本ネットワークセキュリティ協会(JNSA) PKI相互運用WG・電子署名WGの共催で行われた「Bitcoin勉強会(技術編)」の資料を公開させて頂きました。

これまでにも、いろいろBitcoinを解説した資料はあったんですが、自分は電子署名屋なもんで、どんなデータにどうやって署名するのか、署名検証するのか、ハッシュ計算するのか、もやもやした感じですっきりしなかったので、実際にプログラム書いてデータ覗いたり署名やハッシュが正しいか確認したりしながら、時間をかけてじっくりいろいろ調査した結果を資料にまとめました。

例えば、blockexplorer.comのトランザクションの詳細情報なんかにしても、詳細表示といいながらこんなふうにJSONで表示されちゃうと、JSONの連想配列は順序関係がないので署名対象がどうなってるのか、理解が止まっちゃうんですよね。そのあたりが、この資料ではすっきりできるのかなと思ってます。よかったら参考にしてください。

私は、暗号の専門家ではなくて、暗号アプリケーション屋だと思っているですが、楕円曲線公開鍵暗号についても今まで理解が十分でなかったものを、これを期にかなり勉強しまして、公開鍵からECDSA署名まで「数学者」ではなく「技術屋」さんのイメージが湧くようにたった「7枚」のスライドで「なんとなく」理解できるようなものができたかなと思います。(専門家の方に言わせると「だめじゃん」みたいな話になっちゃうかもしれないですけど。)

サッカー、同点になりましたね。後半期待できそうです。今日はこんなところで。

(続)RSAとECDSA、署名生成と署名検証どっちが速い?

前回の記事では、署名生成と署名検証とか、RSAとECDSAとかどっちが速いのかOpenSSLやJava JCEを使って速度の比較をしました。一度作った署名を何回か検証に使うというケースもあるので、検証にかかる時間はとても重要だと思います。今日は、前回の比較をさらに掘り下げてみたいと思います。

・署名検証の速度は(今我々が普通に使う鍵長では)RSAの方が断然速い
・しかしながらECCは鍵長が長くても遅くならないという特徴があるのでいつか逆転するはず

鍵長が長いとRSA不利、ECDSA有利になってくるのでいつか速度の逆転が起きるのだろうと思います。では、それが鍵長としていつなのかを調べたいと思います。

NISTの暗号強度の比較表を再度引用します。

共通鍵暗号
相当
RSAECDSA
80 1024 160-223
1122048 224-255
1283072 256-383
1927680 384-511
25615360512-

まずは、同じ暗号強度のECC、RSAの鍵長に対して秒間署名検証回数をプロットしてみましょう。
cmp6-verify2
ご覧の通り共通鍵暗号で200bit相当、RSAなら9000bit、ECCなら200bit程度の所で署名検証の のスピードが逆転しているように見えます。我々が現在利用することの多い2048〜4096bit程度の RSAの鍵ならまだまだ十分高速であることは言えるのではないかと思います。

上記のグラフが指数関数的なので今度は秒間署名回数の対数を取ってプロットしてみましょう。
cmp7-verify3log
グラフから、暗号強度に対してはほぼリニアに秒間署名速度の対数が推移し、 共通鍵暗号相当の暗号強度の軸であるx座標が212.5423729(bit)の時に、 RSAとECCの署名検証の速度が逆転しています。

それでは、共通鍵暗号の強度で213bitということはRSAやECCではどの程度の鍵長に 相当するのでしょうか。 共通鍵暗号暗号強度と同等のECC、RSAの鍵長は最初のNISTの表から これも指数関数的なのでRSAの鍵長と、ECCの鍵長の対数を使ってプロットしてみます。
cmp8-strength
すると、ご覧のように取った対数に対してほぼリニアに推移することがわかります。 共通鍵暗号の暗号強度で213bitとする点はRSAだとy軸が3.965、ECCだと2.612となり、 これらは指数に戻して

RSAとECDSAと同じ暗号強度で署名検証速度が逆転するのは
・RSAだと9234bit のとき
・ECCだと409bitのとき
ということのようです。この値に近づいてるようならECDSAへの移行を考えた方が よいということなんでしょうね。

今晩はこの辺で

あ、そうそう。これ書いている途中でizuさんのとてもためになる関連記事を発見してしまいました。杜撰な研究者の日記「RSA暗号の強度 (2009.11.19)」

RSAとECDSA、署名生成と署名検証どっちが速い?

2013年9月4日に開催されたOpenID Tech Night Vol.10 に参加してて、

大きなプロバイダではRSA署名の検証は結構大変です。 RSAは署名よりも検証の方が計算コストがかかるので...

みたいな話をされ、「んん?逆じゃないの。RSA署名の検証は署名生成よりも圧倒的に計算コスト低いよね。」とか 思ってたわけで「がが〜〜ん」と。 「まぁ、ちょっと調べてみるべぇ。」と手持ちのノートPCで調べてみました。

検証内容

以下のことを検証してみたいと思います。

  • 署名の生成と検証ではどちらが速いのか。RSAとECC(ECDSA)では違いがあるのか。
  • 同程度の暗号強度のRSA署名とECDSA署名ではどれくらい速度差があるのか。
  • RSA署名では鍵長が変わったとき、どれくらい速度差があるのか。
  • ECDSA署名では楕円曲線や鍵長が変わったとき、どれくらい速度差があるのか。
  • Ruby+OpenSSLとJava JCEではどれくらい速度差があるのか。
なんか、楕円「マンセー」みたいな人もおられますが、 「楕円は鍵長が短いから圧倒的に速い」みたいな事を言い出す人もいて 「ホンマかいな?」と調べてみたかったわけです。 楕円って期待するほどそんなに速くないですよね? むしろ遅いですよね。

検証方法・検証環境

言語の偏りがあるのも良くないのでOpenSSLベースのものとJava JCEベースのものと調べます。 いちいちOpenSSLをCで書くのも面倒なので。Rubyを使いました。 処理時間の測定方法については、Ruby+OpenSSL、Java JCEで次のような観点で測定しています。

共通
  • 鍵や証明書のロードの時間は処理時間に含めない。
  • 測定条件統一のためハッシュ計算の時間は処理時間に含める。
  • 同一のマシンで測定する。
  • 再利用しない同一の鍵で2000回の署名生成、署名検証の時間を計測。
  • 公開鍵暗号のパフォーマンスを知りたいだけなので署名対象は"aaa"の短い文字列。
  • SHA1withRSAもしくはSHA1withECDSAで比較する。
Ruby+OpenSSL
  • Ruby標準の'benchmark'モジュールを用い、リハーサルも行う。benchmarkのrealの時間を用いる。
Java JCE
  • イテレーションループの前後でのSystem.currentTimeMillis()の値の差を処理時間とする。
細かい検証環境情報は以下の通りとなります。
検証環境
マシンLenovo X201s
CPUIntel Core i7 L620 2.00GHz
メモリ8GB
OSMicrosoft Windows 7 Professional 32bit SP1
Java
バージョンOracle Java 1.7.0 build 1.7.0-b147
RSA署名JCEプロバイダSunRsaSign 1.7 Provider
ECDSA署名JCEプロバイダSunEC 1.7 Provider
Ruby (+ OpenSSL)
バージョンcygwin C Ruby 1.9.3p194
OpenSSLOpenSSL 1.0.1c

Ruby + OpenSSLで署名

Ruby + OpenSSLでRSAやECDSA署名するには、OpenSSLコマンドで普通に PKCS#5の秘密鍵と公開鍵を準備してこんな感じで署名生成、署名検証すればヨロシ。

# ECDSAの署名生成
prvKey = OpenSSL::PKey::EC.new(File.read(PKCS#5秘密鍵PEM))
hashed = OpenSSL::Digest::SHA1.digest(署名対象メッセージ)
sigVal = prvKey.dsa_sign_asn1(hashed)

# ECDSAの署名検証
pubKey = OpenSSL::PKey::EC.new(File.read(PKCS#5公開鍵PEM))
hashed = OpenSSL::Digest::SHA1.digest(data)
isValid = pubKey.dsa_verify_asn1(hashed, sigVal)

# RSAの署名生成
prvKey = OpenSSL::PKey::RSA.new(File.read(PKCS#5秘密鍵PEM))
sigVal = prvKey.sign("sha1", data)   

# RSAの署名検証
pubKey = OpenSSL::PKey::RSA.new(File.read(PKCS#5公開鍵PEM))
isValid = pubKey.verify("sha1", sigVal, data)   
ECDSAの時はハッシュを自分で計算するのと、 ECDSAの署名値をASN.1構造で表現することに気をつければ問題ないかと思います。

Java JCEで署名

最近、キーストア使って楽してたので普通に鍵ファイルを読みたい場合には、 PKCS#8 DERじゃないといけないんだよなとか探してみると 自分の記事 「OpenSSLで鍵生成した秘密鍵をJavaで使う」が見つかって助かりました。 秘密鍵ファイルはPKCS#8にしといて、公開鍵もPKCS#8にしようとしたら 「読めな〜〜〜い!!」鍵はパラメータの数値(BigInteger)を指定するか 証明書じゃないといけないそうだ。仕方ないから無理やり自己署名証明書を作りました。

ECDSAの署名生成はこんな感じ。

KeySpec keySpec = new PKCS8EncodedKeySpec(PKCS#8秘密鍵DERのデータbyte配列);
KeyFactory kf = KeyFactory.getInstance("EC");
PrivateKey prvKey = kf.generatePrivate(keySpec);
Signature sig = Signature.getInstance("SHA1withECDSA");
sig.initSign(prvKey);
sig.update(署名対象データaaa);
sigVal = sig.sign();

RSAの署名生成はこんな感じ。

KeySpec keySpec = new PKCS8EncodedKeySpec(PKCS#8秘密鍵DERのデータbyte配列);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey prvKey = kf.generatePrivate(keySpec);
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(prvKey);
sig.update(署名対象データaaa);
sigVal = sig.sign();

RSAやECDSAの署名検証はこんな感じ。

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cer = (X509Certificate)cf.generateCertificate(new FileInputStream(公開鍵証明書));
pubKey = cer.getPublicKey();
Signature sig = Signature.getInstance("SHA1withECDSA"); // RSAならSHA1withRSA
sig.initVerify(pubKey);
sig.update(署名対象データ);
isValid = sig.verify(sigVal);

最初、BouncyCastle使えばいいかとも思ったんですが、 Java SE 7から楕円用のプロバイダSunECが標準提供されるようになったので、 Java SE 7の標準バンドルされたプロバイダを使うことにしました。 サポートしている楕円曲線はどうだっけと思ったら 前に自分で調べてあったのでそれを参考にしました。 ( 祝 Java SE 7 リリース記念「JCEはどうなってんの?」)

RSAとECCの暗号強度対応

一般に、

  • ECC 160bit は RSA 1024bitに相当する、とか
  • ECC 256bit は RSA 3072bitに相当する、とか
言われていますが、調べて見ると、 NIST SP800-57 Recommendation for Key Management - Part1: Generalの 5.6.1節 Comparable Algorithm Strengthで対象暗号、RSA、DSA、ECC(ECDSA)の鍵長と 暗号強度の対応の表があり、 RFC 5656 Elliptic Curve Algorithm Integration in the Secure Shell Transport Layerでも引用してます。(こっちの方が見やすい)

表を引用しておきましよう。

共通鍵暗号DSARSAECDSA
80 L=1024,N=160 1024 160-223
112L=2048,N=256 2048 224-255
128L=3072,N=256 3072 256-383
192L=7680,N=384 7680 384-511
256L=15360,N=51215360512-

(結果1)RSAの署名生成と署名検証はどっちが速いか

まずはRSA鍵での署名と検証がどれくらい違うのか見てみましょう。


cmp1-rsa-sign-verify

署名と生成では、署名の方が圧倒的に時間がかかることがわかります。 また、鍵長が長くなるほど指数関数的に時間がかかることがわかります。 署名生成に関しては特にJava JCEの遅さが顕著です。

(結果2)ECDSAの署名生成と署名検証はどっちが速いか

グラフからECDSAではRSAとは逆に署名検証より署名生成の方が わずかながら速いですが、あまり変わらないということがわかります。 また、同じ鍵長のsecp160r1, secp160r2, secp160k1とでは ほとんど処理速度には違いはなく、鍵長が長くなると処理時間は増えますが、 RSAが非常に鍵長の影響を受けるのに対し、ECDSAでは あまり鍵長が長くなっても処理時間が長くはならない事がわかります。


cmp2-ecdsa-sign-verify

(結果3)同じ暗号強度ではRSAとECDSAとどちらが速いか

ECC 160bit とRSA 1024bitはほぼ同等の暗号強度です。 ECDSAと比較して、RSAは署名生成はとても遅いが、署名検証は とても速いことがわかります。


cmp3-ecc160rsa

鍵長が長いケース、ECC 256bit と同等なRSA 3072bit を比較してみると、 順序関係は変わりませんが、鍵長が長くなった分、 非常にRSA署名の生成時間が長くなっています。 これに対し、ECDSAではRSAほどは鍵長が長くなった影響を受けていません。


cmp4-ecc256rsa

まとめ

簡単にまとめると時間がかかる順に

  • RSA署名の生成には非常に時間がかかる
  • ECDSAの署名検証は署名生成よりほんの少し長く時間がかかる
  • ECDSAの署名生成は普通に時間がかかる
  • RSA署名の検証は非常に短時間であるECDSAの署名生成は普通に時間がかかる
  • RSAでは鍵長が長くなるほどその傾向が顕著になる。
  • ECDSAはRSAほどは鍵長が長くなる影響を受けない。
といった感じでしょうか。認識してたとおりで良かったなぁと思いました。今日はこの辺で。

ETSI STFテレカン初め

今日は年が明けて最初のETSI STF351の電話会議になります。

2月末に行われる"ETSI 3rd Remote XAdES/CAdES Plugtests"の準備に本格的に取り掛かります。

プラグテストまでの参加者のスケジュールはこうなっています。

2009.02.06 オンライン登録〆
2009.02.06 参加者とETSIのNDA締結〆
2009.02.06 参加費のカード払い〆(海外送金の場合別途)
2009.02.16 テスト開始
2009.02.27 テスト終了

ウェブカム忘れないようにしないと、、、、、、

ETSI 3rd Remote XAdES/CAdES Plugtest

Plugtests Portal for Electronic Signature

来年2009年2月にETSIで長期署名フォーマット CAdES/XAdES の相互運用実証実験を行います。ETSIの主催するXAdESのテストとしては3回目、インターネットを用い日本からもリモートで気軽に参加できるテストとしては2回目、CAdESのテストとしては初めてのテストとなります。

CAdESのテスト内容は、前回のXAdESのテストと同じようなテストケースになります。
・長期署名の生成・交換・検証について35程度
・失敗系のみの検証テストについて15程度
になるかと思います。

OCSPや属性証明書などを使ったテストもありますので、よかったら参加してください。STF351でそろそろテストケースの設計や準備に着手することになります。XAdESの方については何かニューなテストが必要かなと思っていますのでご要望などありましたらよろしくおねがいしますm(_ _)m


Dear Madam,
Dear Sir,

The ETSI Plugtests Service is pleased to invite you to participate in a new remote XAdES plugtests!

After the success of the first remote plugtest event, ETSI has continued the development of the supporting Remote Plugtest Portal, which now offers on-line PKI-related services (Certificates provision, OCSP server, LDAP and Time-stamp).

The purposes of these new events are:

* To consolidate solutions to already identified interoperability issues of XAdES.

* To enable participants to assess the level of interoperability of CAdES.

* To identify additional issues that should be taken into account in future XAdES/CAdES standardization activities.

* To improve the quality of XAdES/CAdES specifications.

* To ease the introduction of XAdES/CAdES signatures, by providing the means to solve interoperability problems before widespread deployment.

The event will evaluate (X-C)AdES interoperability by focusing on all the different XAdES forms standardized in ETSI TS 101 903 and ETSI 101 733, including (X-C)AdES-BES, (X-C)AdES-EPES, (X-C)AdES-T, (X-C)AdES-C, (X-C)AdES-X Type 1, (X-C)AdES-X Type 2, (X-C)AdES-XL and (X-C)AdES-A.

Participants will also be able to generate new test case definitions and signatures, which will be taken into consideration for extending the test cases set according to ETSI's discretion.

The registration deadline for the 3rd event is 6th February 2009. We recommend you to register as soon as possible. All details about the events, including all the technical information are available at http://www.etsi.org/plugtests/XAdES2/html/XAdES2.htm

Should you need any further information, please feel free to contact us at: plugtests@etsi.org

The Plugtests Team

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

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