ラズパイ2でTLSハンドシェイクのパフォーマンスを比較した話
2018年現在、TLS通信で使用されている鍵交換方式では、RSA、DHE、ECDHEなどがありますが、 使用するアルゴリズムや鍵長さの違いにより、セキュリティ強度やパフォーマンスに違いが生まれます。
PFS特性のある鍵交換方式はRSAよりもアルゴリズムとして重いため、PFSが知れ始めた頃には、パフォーマンスが悪化するという話もありましたが、 最近のサーバ機器やPC、スマホではハードウェア自体の性能が上がり、通信のTLS化に伴うパフォーマンス影響は比較的に少なくなっていますが、 スペック的に制約のあるRaspberry PiなどのIoT機器では速度差がどの程度あるのかを調べてみました。
検証環境
サーバ
- マシン
- Model: Raspberry Pi 2 Model B
- CPU: ARM Cortex-A7 900MHz (4Core)
- Memory: 1GB
- S/W
- OS: Raspbian Stretch
- Web Server: nginx 1.14.0 (+ OpenSSL 1.1.1)
クライアント
- マシン
- S/W
- OS: Ubuntu 16.04 LTS
- Web Client: OpenSSL 1.1.1
内容
試したパターン
今回試したTLSの鍵交換方式は下記の通りです。 なお、鍵の署名に使用されるサーバ証明書は一般的なRSA 2048bitのものと、処理が高速と言われるECDSA(ECC) P-256のものを用意しました。
評価方法
openssl s_client
コマンドでコネクションを確立する部分までの実行時間をtime
コマンドで計測し、realの時間を計測。
これを10回実行し、所要時間の平均値と中央値を計算。
鍵交換部分以外は同条件なるよう、openssl s_client
コマンドの-tls1_2
オプションと
-cipher
オプションを利用して、プロトコル(TLS 1.2)と暗号化方式(AES-GCM 128bit)を固定するようにします。
ECDHEの鍵長に関しては、openssl s_client
コマンドの-curves
オプションを使用してパラメータを選択し、
DHEの鍵長に関しては、クライアント側でコントロールが出来ないため、サーバ側でDHパラメータ(1024~4096bit)を生成して都度再起動します。
実行コマンド
# RSA鍵交換 $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "AES128-GCM-SHA256" < /dev/null # DH鍵交換 $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "DHE-RSA-AES128-GCM-SHA256" < /dev/null # ECDH鍵交換(RSA証明書利用) $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-RSA-AES128-GCM-SHA256" -curves "prime256v1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-RSA-AES128-GCM-SHA256" -curves "secp384r1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-RSA-AES128-GCM-SHA256" -curves "secp521r1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-RSA-AES128-GCM-SHA256" -curves "X25519" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-RSA-AES128-GCM-SHA256" -curves "X448" < /dev/null # ECDH鍵交換(ECDSA証明書利用) # ※curvesには証明書で使用している曲線も含める必要あり $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -curves "prime256v1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -curves "secp384r1:prime256v1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -curves "secp521r1:prime256v1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -curves "X25519:prime256v1" < /dev/null $ time openssl s_client -connect example.com:443 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -curves "X448:prime256v1" < /dev/null
結果
各鍵交換方式と、TLSハンドシェイクにかかった時間(10回の平均値、中央値)は以下のようになりました。
鍵交換方式 | サーバ証明書 | 平均値(秒) | 中央値(秒) | RSA 2048bit比 |
---|---|---|---|---|
RSA 2048bit | RSA | 0.055 | 0.054 | - |
DHE 1024bit | RSA | 0.083 | 0.083 | 151% |
DHE 2048bit | RSA | 0.261 | 0.260 | 475% |
DHE 3072bit | RSA | 0.597 | 0.591 | 1,085% |
DHE 4096bit | RSA | 1.219 | 1.221 | 2,216% |
ECDHE P-256 | RSA | 0.053 | 0.051 | 96% |
ECDHE P-384 | RSA | 0.134 | 0.132 | 244% |
ECDHE P-521 | RSA | 0.233 | 0.233 | 424% |
ECDHE X25519 | RSA | 0.052 | 0.052 | 95% |
ECDHE X448 | RSA | 0.073 | 0.073 | 133% |
ECDHE P-256 | ECDSA | 0.022 | 0.022 | 40% |
ECDHE P-384 | ECDSA | 0.106 | 0.107 | 193% |
ECDHE P-521 | ECDSA | 0.214 | 0.212 | 389% |
ECDHE X25519 | ECDSA | 0.024 | 0.025 | 44% |
ECDHE X448 | ECDSA | 0.039 | 0.040 | 71% |
まとめ
DHE系がやたらと重い
DHE系はサーバ側の負荷が大きいという情報は多々ありますが、Raspberry Pi 2では予想していたより差が大きな結果になりました。
RSA 2048bitと同強度のDHE 2048bitでは4.75倍の時間がかかっており、ECDHE P-256とほぼ同強度のDHE 3072bitでは10倍を超えています。
ハンドシェイク中はラズパイ側のCPUもリソースを取られてしまうため、ECDHEが使える環境であれば、DHEを使うメリットはあまりなさそうです。
RSAとECDHE系の速度差はほとんど無し
Wikipediaの記事では、ECDHE-RSAはRSAと比べて15%程のオーバーヘッドがあるとされていますが、今回のRaspberry Pi 2では時間に差はほとんどありませんでした。(むしろRSAよりもECDHE P-256やX25519の方が早い結果に)
最新のOpenSSL 1.1.1を使用したので、実装が最適化されているのかもしれませんが、Raspberry PiでもRSA方式と比べた大きなオーバーヘッドはないと言えそうです。
ECDSA証明書使用のハンドシェイクはRaspberry Pi上でも速い
ECDHE P-256やX25519では、RSA 2048bitの半分以下の時間でハンドシェイクが行えており、ラズパイ上でもECDSA証明書利用による高速化の恩恵は受けられそうです。