自堕落な技術者の日記

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

暗号

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; }

(小ネタ)楕円曲線暗号をなんとなく理解した気になるオススメのリンク4選

やっぱり、楕円曲線暗号(Elliptic Curve Cryptography)はRSA暗号に比べて格段になんだかんだ難しいと思うですよ。 自分も勉強中なんですが、なかなか良い説明がなくて悶々としております。 jsrsasignの実装やビットコインを知る必要がある手前仕方なく。そんな状況の中、いろいろ見た中で、 結構オススメなリンクを4つ紹介したいと思います。

CloudFlare: A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography
http://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography
長所点の足し算の説明が絵的でわかりやすく最初の導入として良いのでは
短所単に入り口に入ったところ、点の足し算程度で終わってしまう。
Zero to ECC in 30 Minutes (Entrust Inc.)
http://www.entrust.com/wp-content/uploads/2014/03/WP_Entrust_Zero-to-ECC_March2014.pdf
長所楕円曲線暗号について中学の数学程度でわかるように解説している。絵も多用してわかりやすい。楕円曲線公開鍵暗号はよくわかる。
短所署名(ECDSA)まで辿り着かない。
Elliptic Curve Cryptography Tutorial
http://www.johannes-bauer.com/compsci/ecc/
長所工学系の人に向けてわかりやすく書いてある。ECDSA署名もある。プログラム例もある。結構オススメ。
短所逆に数学をやった人には物足りない?
楕円曲線暗号入門「計算機緒論2」配布資料 伊豆哲也さん
http://researchmap.jp/mulzrkzae-42427/#_42427
長所何より日本語でわかりやすい。でも大学数学の基礎素養がないと読み辛い。ECDSA解説もある。
短所使われている記号が一般的なのとちょっと違うようで少し混乱する。
私は上の順序で読むのがいいのではと思います。誰かこれ全部まとめたやつを日本語で書いてくれると いいんですけどねぇw (オマエガヤレ)

コンピューター、IT関係の英語は何とか少しは読めるけど、数学の英語はやっぱり難しいですねぇ。

追記

  • 2014.05.29 伊豆さんに最新版のリンクを頂いたので修正いたしました。伊豆さんあざます。
  • 2014.10.11 私の書いたスライド「Bitcoinを技術的に理解する(p10-17)」のp10-17で内容8ページで楕円曲線暗号、ECDSAの署名・検証などエンジニア向けにざっくり説明した資料を作りました。我ながら短いページでよくできていると思うのでよかったらご覧ください。
  • 2014.10.21 かなりわかりやすい英語の解説ページが出てきました。CoinDesk: The Math Behind Bitcoin これは、現時点では一番オススメ。英語だけど。

RSA社の暗号2010年問題ラウンドテーブル

間近に迫る「暗号の2010年問題」、企業が取るべき対応は?−RSAセキュリティ
現在主流のいくつかの暗号も、近い将来、安全性を担保するだけの強度が足りなくなってしまうといわれている。そうした状況を受け、2010年に米国連邦政府が次世代暗号方式への移行を決定。その波紋が各業界へ伝わったことで生じた問題が、暗号の2010年問題である。


さすが、RSAさんは頑張っています。エライ!セキュリティの専門家なんだからこうした活動をもっとベンダーが積極的にやらないといけないと思います。本当はもっと早く大々的にやってもらえたらな、、、とも思います。

出回っている根幹となる暗号ライブラリは基本的に既に対応できていると思うのですが、ミドルウェアだったり、証明書だったり、一部のOS、ブラウザやオフィススイートなどよく使われるアプリケーション(この前のマクロのコード署名もそうですね、、、)が進まないと利用者としてはどうしようも無いし、選べないという感はあります、、、、

古いOSなんかもありますし、SHA2への移行が叫ばれている現在MD2とか使われていたり、仕様上RSA512しか使えないようになっていたりね、、、、なかなか難しい、、、、( ´∀`)つ

IPA暗号フォーラム2008

情報処理推進機構:情報セキュリティ:IPA暗号フォーラム2008・大川賞受賞記念シンポジウムのご案内
暗号の世代交代という状況をふまえ、また大川賞受賞を記念してRSA暗号の開発者の一人であるAdi Shamir教授(イスラエル・ワイツマン研究所)と基礎研究から応用技術の開発に至る幅広い分野において、我が国の暗号研究をリードしてこられた今井秀樹教授(中央大学、東京大学名誉教授)のお二方をメインゲストにお招きし、「暗号技術の今後」と題して、IPA暗号フォーラムを、開催いたします。

日時:2008年11月21日(金) 13:00〜18:00 (12:30 開場)
会場:東京大学生産技術研究所An棟コンベンションホール


今年も開催されるんですね。昨年はAdi Shamir先生とトイレで隣になりびっくりしました( ´∀`)つ

128ビットカエサル暗号

「128ビットカエサル暗号」@水無月ばけらのえび日記
<以下、引用>会社で Google Chrome をいろいろ見ていたのですが、HTTPSなサイトで情報を見ると……。
「128ビット暗号により暗号化されています」

いや……単に128ビットとだけ言われてもなぁ。同じ128ビットでも、AESとRC4ではだいぶ違う気がするし……などと社内で話していたら、「ひょっとしたら128ビットカエサル暗号かもしれない」という話が。


やっぱりGoogleはセキュリティに関心がないんだなぁ、、、と、しみじみ思います。128ビットカエサル(=シーザー)暗号はちょっとおもしろかった、、、、、

でも、シーザー暗号は英字をいくつシフトするかが共通鍵となっているので英大文字しか使わないなら26文字で高々5ビット、英大文字小文字空白でも6ビットにしかならなりません。平文も暗号文も印字可能な文字なのでどんな変換テーブルに使っても高々7ビット程度にしかならないので、Google Chromeのメッセージが「128ビットシーザー暗号かもしれない」と勘ぐる必要も無いのではないかと、、、ははは( ´∀`)つ

Google Keyczar

Google、オープンソースの暗号化ツール「Keyczar」を発表 - ITmedia News


Googleから暗号ライブラリが出ています。
対象鍵、非対称鍵暗号の暗号化と復号、署名なんかが
できるようです。

JavaならJCEがあるので、あまり魅力を感じないんですが、
Python でも使えちゃうというのが良いところでしょうか。
機能はシンプルでAPIマニュアルを見れば
(大したことができないので)すぐに使えるような気がします。

個人的には暗号ライブラリ、セキュリティライブラリは
そう多くは必要ないと思っていて、多くの人のレビューを受けた
真っ当なライブラリが幾つかあれば十分だと思っています。
そういう意味では、Googleの暗号ライブラリというのは
どうなのかなという気がします。

鍵の世代管理もできるようですが、HSMやスマートカード等使えないとすると
本当にセキュリティが重要な局面で使えないのではないかと、、、、

★リンク
Google Keyczar トップ
Google Keyczar Java doc

CRYPTREC Report 2007 の公開

情報処理推進機構:情報セキュリティ : 2007年度暗号モジュール委員会活動について
CRYPTREC Report 2007 の公開


読んでおかないといけません、、、、メモ、メモ、、、、

Interop Tokyo 2008のTrusted Computing Groupの講演2

最近のノートパソコンには、殆どTPMというセキュリティチップが搭載されています。

このチップや応用について標準化ならびに普及活動をしているのが
Trusted Computing Group(TCG) です。

今度のInterop Tokyo 2008 では、日本からの唯一のボードメンバーの小谷さんや、元SunにいてJCEの証明書パス検証やPKIまわりの実装をされIETF PKIXで有名だった今はJuniperでTCGの活動をされているSteve Hannaさんが講演されるそうです。
楽しみ楽しみ、、、

リンク
http://www.interop.jp/
https://www.trustedcomputinggroup.org/

Java JCE SecureRandom2

今回のDebian OpenSSL問題のように、RSA・DSA鍵生成などの場面で

同じ値となる可能性がとても低い「良い」乱数を求められるケースがありますが、

Javaでは暗号技術により強化されたjava.security.SecureRandomという

乱数生成器が使えます。

今日、ちょっと必要になって、自分が使えるもの、もしくは

かつて使えたものでどんなものがあるのか

調べてみたのが以下です。

~アルゴリズム名 JCEプロバイダ バージョン
SHA1PRNG SUN 1.6
FIPS186_2using_SHA1 Entrsut 7.2
X9_31usingAES256 Entrsut 7.2
X9_31usingDESede Entrsut 7.2
Windows-PRNG SunMSCAPI 1.6
RNG nCipherKM 不明
IBMSecureRandom IBMJCE 不明(JDK1.3)

ここでわかったのは、

  • 無償で一般に利用できるのはSUNかIBMJCEプロバイダしかない
  • BouncyCastle, IAIKはSecureRandamを提供していない

ってことでした。

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

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