🏆

ブラウザのW3C Web Cryptography APIのRSA鍵処理の速度比較をしてみた

2022/01/26に公開

前回は、Nodeでのcryptoモジュール、Node W3C Web Cryptography API、拙作のjsrsasignwasm-rsaの速度比較をしてみたわけですが、今回は「ブラウザはどうなの?速いの?速くないの?どっち?」ということで、速度比較をしてみようと思います。(↓前回のはこちら)

https://zenn.dev/kjur/articles/af74b5d3d2afcb

  • NodeとブラウザではRSA鍵生成、署名生成、署名検証の速度はどう違うか
  • 主要ブラウザで比較するとどうか

みたいなポイントで比較してみようと思います。噂ではChromeのJavaScriptがバカっぱやいという事なので実際どの程度違いが出るのかは興味があるとこですね〜〜〜。

調査内容

以下の3つの機能を

  • 2048、3072、4096ビットのPEM形式のRSA 鍵ペアの生成
  • 2048、3072、4096ビットのPEM RSA秘密鍵による署名
  • 2048、3072、4096ビットのPEM RSA公開鍵による署名検証
    以下の2つの暗号ライブラリ/APIで
  • W3C Web Cryptography API
  • jsrsasign
    3つのブラウザChrome、Firefox、Safariで処理速度を測定します。

前回のNode.JSでの測定結果とも比較します。
今回は暗号強度が十分でないRSA 1024bit鍵での比較はしないことにします。(実際には測定してるんですが、1024bitだけ異常な速度が出るケースがあり、、、)

調査条件

調査条件は前回とほぼ同じで、方法による条件の差がおきないように以下の条件で測定しました。

  • 処理の入出力は共通化します。
    • 外部の鍵を使う場合には、PEM形式の秘密鍵(PKCS#8)、公開鍵(SPKI)の文字列を入力とします
    • 署名対象は"aaa"の文字列とします。これにより、ハッシュ対象データの大きさの影響は少なくなります。
    • 署名値の入出力は16進数文字列とします。
    • 対象のモジュールの提供する機能で入出力の条件を満たせない場合には、jsrsasign等の関数でこれを補い変換します。
    • 測定マシン、OS、処理系は同じものを使用します。
    • WebCryptoAPIなど、非同期APIは同期させ逐次実行するようにします。
  • 測定は3セット測定した平均を取り、1セットは処理が概ね30〜1分の間になるように処理回数の調整を行います。
  • 処理時間の測定はperformance.now()関数の差分を用いて処理時間を測定します。
  • 1分間の平均処理回数で比較します。

測定環境

全てのテストを以下の環境で測定しました。

  • マシン: MacBook Air (M1, 2020)
  • メモリ: 16GB
  • OS: macOS Big Sur 11.6
  • ブラウザ: Chrome 96.0.4664.110 arm64
  • ブラウザ: Firefox 95.0 64bit
  • ブラウザ: Safari 14.1.2
  • 処理系(参考): Node.JS 17.2.0
  • モジュール
    • jsrsasign 10.5.1

W3C WebCrypto APIのRSA鍵生成速度

W3C WebCrypto APIのRSA鍵生成速度
鍵生成に関してはNodeが速いですね。

W3C WebCrypto APIのRSA署名生成速度

W3C WebCrypto APIのRSA署名生成速度
署名に関してはNodeとChromeがほぼ互角です。

W3C WebCrypto APIのRSA署名検証速度

W3C WebCrypto APIのRSA署名検証速度
署名速度に関してはNodeだけ遅いですが、鍵長によらなくて4096bitでは逆転してNodeが速くなります。2048bit、3072bitではChromeが圧倒的に速いですね。

jsrsasignのRSA鍵生成速度

jsrsasignのRSA鍵生成速度
jsrsasignでのNodeと各ブラウザの速度比較も参考まで掲載していきます。W3C WebCrypto APIは、特別な最適化がされていると思いますが、jsrsasignの測定結果は、一般的なJavaScriptでの計算がNodeと各ブラウザでどの程度違うのかを比較する参考になるかと思います。
結果を見るとChromeのRSA 2048bit鍵生成だけ、やたら速くて他はそうでもないという、、、

jsrsasignのRSA署名生成速度

jsrsasignのRSA署名生成速度
jsrsasignのRSA署名生成の速度比較は、最も直感と合う素直な結果になっていて、Chrome、Node、Safari、Firefoxの順に速く、鍵長の変化も納得できるかなと思います。

jsrsasignのRSA署名検証速度

jsrsasignのRSA署名検証速度
jsrsasignのRSA署名検証の速度比較もまた署名生成と同じく、直感と合う素直な結果になっていて、Chrome、Node、Safari、Firefoxの順に速く、鍵長の変化も納得できるかなと思います。

W3C WebCrypto API RSA鍵処理の総合結果

W3C WebCrypto APIのRSA鍵処理相対速度比較
Chromeの処理速度を100とした時のNode、Safari、FirefoxのW3C WebCrypto APIのRSA鍵生成、署名、署名検証の速度を相対的に比較してみます。Nodeは相対的に鍵生成は速いですが、署名検証が遅く、総合力では概ねChromeとNodeは同程度のパフォーマンスですね。
SafariとFirefoxでは評価項目によって遅かったり、速かったりですが、概ねChromeやNodeの半分の速度といったところのようです。

jsrsasign RSA鍵処理の総合結果

jsrsasignのRSA鍵処理相対速度比較
同様にjsrsasignでも総合結果を比較してみましょう。Chromeを100とすると、Nodeが75、Safariが55、Firefoxが25程度の速度で、処理内容によってばらつきが少なく、直感とあってる結果になったのではないでしょうか?

補足: W3C Web Cryptography APIの互換性

正直、私はAPIがイケてなさすぎてW3C Web Cryptography APIが嫌いなんですが、その理由の一つにブラウザや実行環境でのAPIの互換性が無かったというのがあります。今回しらべてみてその互換性問題っていうのは結構解決されていて、Chrome、Safari、Firefoxで同じコードで動いてくれたのはちょっとびっくりしました。昔は、

  • window.crypto.subtle - Chrome、Firefoxと今のSafari?
  • window.crypto.webkitSubtle - Safari 7.1時代?
  • window.msCrypto - IE11?
    みたいな感じでAPIに互換性がなかったんですよね。W3Cで標準化されてたはずなのに。IEの特殊なのは今回は調べなかったですが、今どうなってるんですかね。

所感

調査結果をざっくりまとめるとこんな感じ。

  • W3C WebCrypto APIに関しては、Nodeやブラウザで得手、不得手はあるもののChromeとNodeは同程度に速く、SafariとFirefoxは概ね半分の速度。
  • jsrsasignの結果を参考に一般的なJavaScriptの計算は、Chrome、Node、Safari、Firefoxの順に速いと言ってよさそう。

おわりに

W3C Web Cryptography APIのRSA鍵処理の速度比較がNodeとブラウザで比較でき、また各ブラウザでどれくらい速度に違いがあるのかもわかってすっきりしました。時間があれば楕円曲線暗号についても調べてみようかと思います。ではでは今日はこの辺で。

Discussion