私はJavaScript実装の暗号ライブラリ jsrsasign(注:RSAだけじゃないよ!) を開発などして遊んでいるわけですが、 そんな矢先、先週ぐらいですかねぇ、PKI.js(http://pkijs.org/) というJavaScript暗号ライブラリが公開されました。 ぶったまげたのはpure JavaScriptなのにOCSPやCMS SignedDataやTimeStampなんか に対応しているのだそうです。さらに凄いのはNIST PKITSのテストも通すせるような認証パス検証(証明書のチェーンの検証)機能も実装されているのだそうです。 先を越されて悔し〜〜〜って感じ。 ようやく時間ができたので、ちょっと動かしたりしてみたのでブログに書いておこうと思います。
WebCryptoを使っているのね
早速ダウンロードしてみて、サンプルには証明書の生成と、CMS SignedDataの生成があるんですが ブラウザで動かしてみようとするも動かない。ちょっと調べてみると W3C Web Cryptography API を使っているんですよね。 ええ?これってまともな実装あるんだっけ?と思ってTwitterでちょっと書いていたら 作者のYury Strozhevskyさんから連絡が来てメールでいろいろ質問をしてしまいました。 GlobalSignのgithubリポジトリなのでGlobalSignの人かとおもったら フリーランスのプログラマなのだそうです。 YuryさんはCAdESに興味があって ブログ記事書かれているみたいなのでそのうちPKI.jsがCAdESに 対応する日も近いのではと、、、
さて、WebCryptoの実装なんですが、普通のほとんどのブラウザではだめで Chromeのnightly buildを使えって言われました。 確認したところWebCryptoを今使うには方法は3つあるようで
Chrome nightly/Chromiumの環境設定は以下のようにやればいいようです。(Yuryさんあざます。)- アドレスバーでchrome://flagsを開く
- 次の4つを有効にする
- #extension-apis
- #enable-javascript-harmony
- #enable-experimental-web-platform-features
- #enable-devtools-experiments
- フラグ設定画面の一番したのボタンで再起動する
早速動かしてみるぞ
githubで落としただけでは簡単に動かず、まぁ以下のようにやります。
- pkijs.orgからソースを落とす
- asn1js.orgからソースを落とす
- 解凍しasn1jsのorg/pkijs/asn1.jsをpkijsのorg/pkijs/にコピーする
- サンプルHTMLを解凍したpkijsの直下にコピーする(cd pkijs; cp examples/*/*.html .)
- CreateNewX509Certificate.html - RSA鍵ペア生成と証明書の生成
- CreateCMSSignedData.html - RSA鍵ペア生成と証明書の生成とCMS SignedDataの生成
// in CreateCMSSignedData.html (line 341) //result_string = result_string + formatPEM(hex_coded);

ほら、ちゃんとPKCS#7 (まぁだいたいCMS SignedDataと同じ)署名データが できていますよね。 中身のぞいてみるとちゃんと内包形式のCMS SignedDataができてます。 証明書DNはBMPStringなんすよね〜〜。なんか、ロシアの人はBMPString好きですよね。
タイムスタンプを発行しようとするも
ちょっと格闘してタイムスタンプを発行しようとするも、 APIドキュメントがなかったり、タイムスタンプを発行するにも MessageImprintを作るのですら結構手間だったり、 TimeStampResponseに署名をしようとするようなちょっと メソッドがわかりにくかったりで一筋縄では発行できそうになく 心が折れてしまいましたorz
おわりに
W3C WebCrypto APIが一般のブラウザで使われるようになれば、 とても可能性が広がりそうなJavaScript PKIライブラリ PKI.js を さわってみました。とても悔しいのでjsrsasignでもCMS SignedData 対応をしようと思っています。
追記
PKI.jsのコードを眺めてみたりして気になった特徴をここにまとめておきます。
- 現時点ではSHA1,SHA2(256,384,512)の証明書しか対応していない
- 現時点ではRSA鍵しか扱えないようだ
(2014.05.11 23:14) 私がブログやTwitterで書いたことで、日本のプログラマの多くの方がYuryさんのPKI.js githubにLikeをしてくれたそうで、Yuryさんはとても喜んでくれました。ロシアからは何故かこのライブドアのブログが見えないそうで、どんな事が書かれているのか気になるので是非送ってほしいと言われてしまい、Google翻訳したページをメールで送ってあげました。YuryさんがCAdESの記事を書いていたのでETSIやECOMのCAdESの話を紹介してあげたら [1] [2] 喜んでくれました。
追記2(2014.05.12 23:49、2014.10.04更新)
簡単にPKI.jsとjsrsasignと比較をしてみましょう。
PKI.js | jsrsasign | |
---|---|---|
暗号計算 | W3C WebCryptoAPIを使ったネイティブ処理なので速いはず | 各暗号ライブラリに依存するがpure JavaScript実装のため遅い |
対応暗号アルゴリズム | W3C WebCryptoAPIに依存しているが無いものも多い。現時点ではRSA, SHA1, SHA2のみ。 | 比較的豊富でRSA, DSA, ECDSA, SHA1, SHA2, MD5等幅広くサポート |
APIドキュメント | 現時点では無い | 公開済 |
サンプル | 公開されているが非常に少ない | 公開済 |
テストコード | 現時点では無い | 公開済 |
対応ブラウザ・動作環境 | WebCryptoAPIを有効にしたChromium, Chrome, WebKit(Safari)等 開発用ブラウザのみ。スマートフォンは設定不能のため非サポート | ブラウザ、動作環境をあまり選ばない。スマートフォンブラウザでも動作 |
Node.js対応 | 基本的にWebCryptoAPIはブラウザ必須なのでNodeは対応していないはず。 | 鍵生成/乱数生成に一部問題があるもののNode.jsに対応 |
証明書チェーンの検証機能 | あり | なし |
RFC 3161デジタルタイムスタンプ | あり | あり(2014.05より) |
CMS署名/暗号フォーマット | あり | 署名のみ(2014.05より) |
RFC5126CAdES長期署名 | なし | BES/EPES/T(2014.06より) |