してみるテストロゴ
Apache 2.4系でHTTP/2サーバを構築してみるテスト。

OpenSSL1.1.0系の暗号スイート

いよいよApacheもバージョン2.4.26以降から、OpenSSL 1.1.0に対応します。

そこで、改めてOpenSSL 1.1.0のベンチマークを取って、最適な暗号スイートを検討したいと思います。

そして、CHACHA20-POLY1305と呼ばれる、OpenSSL1.1.0で新たに採用された暗号方式を説明し、これを含む暗号スイートの設定を説明します。

OpenSSL 1.1.0で追加された暗号スイート

まずは、追加されたCHACHA20-POLY1305を利用する暗号スイートを確認してみます。

$ openssl ciphers -V |grep CHACHA20-POLY1305
          0xCC,0xA9 - ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xA8 - ECDHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH     Au=RSA  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xAA - DHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=DH       Au=RSA  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xAE - RSA-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=RSAPSK   Au=RSA  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xAD - DHE-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=DHEPSK   Au=PSK  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xAC - ECDHE-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=ECDHEPSK Au=PSK  Enc=CHACHA20/POLY1305(256) Mac=AEAD
          0xCC,0xAB - PSK-CHACHA20-POLY1305   TLSv1.2 Kx=PSK      Au=PSK  Enc=CHACHA20/POLY1305(256) Mac=AEAD

Webサイトで利用する暗号スイートは、黄色で示した3つになると思います。

さらにDHEは処理速度がかかりそうなので、実際に利用の機会がありそうなのは、楕円暗号を利用した、ECDHE-ECDSA-CHACHA20-POLY1305ECDHE-RSA-CHACHA20-POLY1305の2種類になります。

以下、ベンチマークを取っていきますが、現時点で、CHACH20-POLY1305のベンチマークは取れないようなので、それ以外の、これまでも利用できていた暗号の処理時間の比較を進めます。

大きく変化があったのは、256ビットの楕円曲線であるprime256v1と呼ばれる処理です。

OpenSSL 1.1.0のベンチマーク

続いて、ベンチマークをとってみます。まずは証明書の署名・検証を見ていきます。

$ /usr/local/bin/openssl speed rsa1024  rsa2048  rsa4096 ecdsap256 ecdsap384
Doing 1024 bit private rsa's for 10s: 8591 1024 bit private RSA's in 10.00s
Doing 1024 bit public rsa's for 10s: 184207 1024 bit public RSA's in 10.00s
Doing 2048 bit private rsa's for 10s: 1313 2048 bit private RSA's in 9.99s
Doing 2048 bit public rsa's for 10s: 48633 2048 bit public RSA's in 10.00s
Doing 4096 bit private rsa's for 10s: 182 4096 bit private RSA's in 10.02s
Doing 4096 bit public rsa's for 10s: 13260 4096 bit public RSA's in 10.00s
Doing 256 bit sign ecdsa's for 10s: 56541 256 bit ECDSA signs in 9.98s
Doing 256 bit verify ecdsa's for 10s: 24701 256 bit ECDSA verify in 10.00s
Doing 384 bit sign ecdsa's for 10s: 12522 384 bit ECDSA signs in 9.99s
Doing 384 bit verify ecdsa's for 10s: 3350 384 bit ECDSA verify in 9.97s

                  sign    verify    sign/s verify/s
rsa 1024 bits 0.001164s 0.000054s    859.1  18420.7
rsa 2048 bits 0.007609s 0.000206s    131.4   4863.3
rsa 4096 bits 0.055055s 0.000754s     18.2   1326.0

                              sign    verify    sign/s verify/s
 256 bit ecdsa (nistp256)   0.0002s   0.0004s   5665.4   2470.1
 384 bit ecdsa (nistp384)   0.0008s   0.0030s   1253.5    336.0

以前、「暗号スイートの暗号強度と、公開鍵のビット数の設定」のベンチマークを調べた時と、比較すると、ECDSAのパフォーマンスが良くなっています。

  OpenSSL 1.0.2g OpenSSL 1.1.0f
RSA 1024[bits] 署名(sign) 1.043[ms] 1.164[ms]
検証(verify) 0.054[ms] 0.054[ms]
2048[bits] 署名(sign) 6.651[ms] 7.609[ms]
検証(verify) 0.203[ms] 0.206[ms]
4096[bits] 署名(sign) 52.461[ms] 55.055[ms]
検証(verify) 0.765[ms] 0.754[ms]
ECDSA 256[bits] 署名(sign) 0.4[ms] 0.2[ms]
検証(verify) 1.4[ms] 0.4[ms]
384[bits] 署名(sign) 0.9[ms] 0.8[ms]
検証(verify) 3.4[ms] 3.0[ms]

256ビット(prime256v1)のECDSAでは、署名、検証ともに、2~3倍程度の速度となっています。384ビットのECDSAは、1割ほど速くなった感じです。

一方、RSAは、ほとんど変わらないか、署名処理が遅くなっているようにみられます。

 

ECDHEのベンチマーク

ECDSAが速くなっているので、同じく楕円曲線を利用しているECDHEの鍵交換も調べてみます。

$ /usr/local/bin/openssl speed ecdhp256  ecdhp384  ecdhp521
Doing 256 bit  ecdh's for 10s: 32199 256-bit ECDH ops in 10.00s
Doing 384 bit  ecdh's for 10s: 4022 384-bit ECDH ops in 10.00s
Doing 521 bit  ecdh's for 10s: 1867 521-bit ECDH ops in 10.00s

                              op      op/s
 256 bit ecdh (nistp256)   0.0003s   3219.9
 384 bit ecdh (nistp384)   0.0025s    402.2
 521 bit ecdh (nistp521)   0.0054s    186.7

こちらも速くなっていそうです!以前の結果と比べると、

  OpenSSL 1.0.2g OpenSSL 1.1.0f
ECDH 256[bits] 1.2[ms] 0.3[ms]
384[bits] 2.7[ms] 2.5[ms]
521[bits] 5.9[ms] 5.4[ms]

特にECDHの256bit(prime256v1)が4倍速くなっています。384ビットと521ビットのECDHも1割ほど早くなっています。

ここ1年で、楕円曲線(特にprime256v1)の処理が格段に改善されているようです。

 

OpenSSL1.1.0には、X25519と呼ばれるセキュリティービット数が128(実際のビット数は、253ビット)の楕円曲線も追加されていますが、こちらはベンチマークに対応していないようです。

正直、prime256v1がここまで速くなると差別化できるのか心配です。

 

AESのベンチマーク

念のため、AESについても見てみます。

$ /usr/local/bin/openssl speed aes-128-cbc aes-256-cbc
Doing aes-128 cbc for 3s on 16 size blocks: 14242159 aes-128 cbc's in 2.99s
Doing aes-128 cbc for 3s on 64 size blocks: 3950008 aes-128 cbc's in 3.00s
Doing aes-128 cbc for 3s on 256 size blocks: 987123 aes-128 cbc's in 3.00s
Doing aes-128 cbc for 3s on 1024 size blocks: 256092 aes-128 cbc's in 3.00s
Doing aes-128 cbc for 3s on 8192 size blocks: 32003 aes-128 cbc's in 3.00s
Doing aes-128 cbc for 3s on 16384 size blocks: 16057 aes-128 cbc's in 3.00s
Doing aes-256 cbc for 3s on 16 size blocks: 10123252 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 64 size blocks: 2844410 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 256 size blocks: 716655 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 1024 size blocks: 179363 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 8192 size blocks: 22879 aes-256 cbc's in 3.00s
Doing aes-256 cbc for 3s on 16384 size blocks: 11012 aes-256 cbc's in 3.00s

The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-128 cbc      76212.22k    84266.84k    84234.50k    87412.74k    87389.53k    87692.63k
aes-256 cbc      53990.68k    60680.75k    61154.56k    61222.57k    62474.92k    60140.20k

こちらはRSAと同様に、微妙にパフォーマンスが落ちていますが、誤差の範囲と要ったところでしょうか。

続いて、この数値から、Webサーバにおいて使用する暗号スイートのパフォーマンスを見てみます。

暗号スイートのパフォーマンス

さて、これまでの結果をまとめると以下の表の通りとなります。

暗号スイート サーバ クライアント 処理時間合計 共通鍵暗号の
パフォーマンス
鍵認証署名 鍵交換 合計 証明書検証

鍵認証検証

鍵交換 合計
中間(2048bit) サーバ(2048bit)
RSA - AES128 -*
(2048bit)
7.6[ms] 7.6[ms] 0.2[ms] 0.2[ms] 0.2[ms] 0.6[ms] 8.2[ms] 84266.84 KB/s
RSA - AES256 -*
(4096bit)
55[ms] 55[ms] 0.2[ms] 0.2[ms] 0.7[ms] 1.1[ms] 56.1[ms] 60680.75KB/s
ECDHE - RSA - AES128 -*
(256bit) (2048bit)
7.6[ms] 0.3[ms] 7.9[ms] 0.2[ms] 0.2[ms] 0.2[ms] 0.3[ms] 0.9[ms] 8.8[ms] 84266.84KB/s
ECDHE - ECDSA - AES128 -*
(256bit) (256bit)
0.2[ms] 0.3[ms] 0.5[ms] 0.2[ms] 0.2[ms] 0.4[ms] 0.3[ms] 1.1[ms] 1.6[ms] 84266.84 KB/s
ECDHE - RSA - AES256 -*
(384bit) (2048bit)
7.6[ms] 2.5[ms] 10.1[ms] 0.2[ms] 0.2[ms] 0.2[ms] 2.5[ms] 3.1[ms] 13.2[ms] 60680.75KB/s
ECDHE - ECDSA - AES256 -*
(384bit) (256bit)
0.2[ms] 2.5[ms] 2.7[ms] 0.2[ms] 0.2[ms] 0.4[ms] 2.5[ms] 3.3[ms] 6.0[ms] 60680.75KB/s

ここまでECDSAとECDHEのパフォーマンスが上がってくると、ECDSA+ECDHEの組み合わせ以外は、サーバから見ると足かせのように見えてきます。

特に、サーバ側の演算処理が、0..5msで終わるというのは、もはやTLS接続が重いという時代が終わりかけてきている印象です。

Apacheの設定方法(httpd 2.4.26以降)

ということで最後に、サーバにもクライアントにも優しい、256bitのECDHE鍵交換を行い、AES128もしくは、CHACHA20による共通鍵暗号を使用する、Apacheの設定を載せます。

この設定は、Apache httpd 2.4.26以降のバージョンで利用できます。

 

CHACHA20は、OpenSSL1.1.0から利用可能になった新しい暗号方式になります。

CHACHA20は、スマートフォンやタブレットなど、ARMアーキテクチャのCPUにおいて、AES暗号よりも、処理速度が期待できる共通鍵暗号です。

パソコンのCPUには、AES暗号用の機能が付いているので、AES128の方が速いですが、スマートフォンに搭載されているCPUにはAES暗号用の機能が無いため、CHACHA20のほうが速くなります。

CHACHA20では、メッセージ署名には、POLY1305と呼ばれる方式を使います。

この組み合わせは、CHACHA20-POLY1305と呼ばれるています。ちょうど、AES128-GCM-SHA256といった部分に相当します。

 

CHACHA20-POLY1305は、鍵交換としてECDHEとDHEが利用可能です。証明書はECDSAとRSAが利用できます。

DHEは、速度的に不利になる可能性が高いため、今回の設定からは外しています。

特にスマートフォンのブラウザは、積極的にCHACHA20-POLY1305を選択するようですが、サーバ側はたいていAES暗号用の機能を持っているので、サーバ負荷を考えるとAES優先で良いと思います。

 

ECDSAのみを使う場合

比較的古いSafari7以前、と、Chrome49以前、Android4.3以前からのアクセスを気にしなくても良い場合、証明書はECDSAだけを使います。

証明書は、Let's EncryptからECDSAの256ビットのものを取得してください。

まず、暗号スイートは、ECDHE-ECDSA-AES128-GCM-SHA256ECDHE-ECDSA-CHACHA20-POLY1305ECDHE-ECDSA-AES128-SHA256の3つにします。

/usr/local/apache2/conf/extra/httpd-ssl.confの一部
…(省略)…
SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
…(省略)…

続いて、鍵交換に使うECDHEのビット数は256ビットのものを設定します。

/usr/local/apache2/conf/extra/httpd-ssl.confの一部
…(省略)…
#SSLOpenSSLConfCmd ECDHParameters Automatic
SSLOpenSSLConfCmd ECDHParameters prime256v1
SSLOpenSSLConfCmd Curves prime256v1
…(省略)…

これで、256ビットのECDHE-ECDSAだけが利用されます。

この設定では、Safari7以前、と、Chrome49以前、Android4.3以前(と、ガラケー)からのアクセスができなくなります。

どうしても、Safari7以前、と、Chrome49以前、Android4.3以前を救いたい場合は、以下の様に設定してください。

 

ECDSAとRSAを使う場合

Safari7以前、Chrome49以前、Android4.3以前を救いたい場合は、以下の様にRSAを含む暗号スイートを設定してください。

つまり、ECDHE-RSA-AES128-GCM-SHA256ECDHE-RSA-CHACHA20-POLY1305ECDHE-RSA-AES128-SHA256を追加します。

この場合、先ほどのECDSAの証明書に加えて、Let's EncryptからRSAの証明書も取得して、複数の証明書を設定してください。

/usr/local/apache2/conf/extra/httpd-ssl.confの一部
…(省略)…
SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
…(省略)…

続いて、鍵交換に使うECDHEのビット数は、さきほどと同じく256ビットのものを設定します。

/usr/local/apache2/conf/extra/httpd-ssl.confの一部
…(省略)…
#SSLOpenSSLConfCmd ECDHParameters Automatic
SSLOpenSSLConfCmd ECDHParameters prime256v1
SSLOpenSSLConfCmd Curves prime256v1
…(省略)…

これで、クライアント側がECDHE-ECDSAを選べばサーバ側の演算は0.5[ms]で終わりますので、非暗号のHTTPと遜色ない速度で、HTTTPS(特にHTTP/2)が繋がるようになったと思います。

実際にはクライアント側は、ECDSAが使える機種でも、クライアント側の演算負荷が低いRSAを選択してくることもあるので、必要に応じて、ECDSAのみをご検討ください。

NEXT >> トップページに戻る

©Copyrights 2015-2023, non-standard programmer

このサイトは、あくまでも私の個人的体験を、綴ったものです。 軽く参考程度にご利用ください。