こんにちは。
キャスレーコンサルティング LS(リーディングサービス)部の趙です。

現在、多くのウェブサイトはHTTPS(Hypertext Transfer Protocol Secure) を利用しています。
HTTPSは、メッセージを平文で送受信する標準のHTTPと異なり、SSL/TLSプロトコルを用いて、
サーバの認証・通信の暗号化などを行います。

今回は、その暗号化方式として楕円曲線暗号(Elliptic Curve Cryptography: ECC)を利用し、
HTTPSサーバを構築してみたいと思います。

SSL/TLSとは

SSL(Secure Sockets Layer)とTLS(Transport Layer Security) とは、
インターネット上(コンピュータネットワーク)で通信を暗号化し、
第三者による通信内容の盗み見や改ざんを防ぐ技術です。

SSLとTLSは表記が異なるだけで、同じ機能を指しており、
SSLがバージョンアップを重ねて「SSL3.0」となり、
次世代規格として「TLS1.0」という名称で呼ばれるようになりました。

最新のバージョンは「TLS1.3」です。
※2015年6月、RFC 7568によって、SSL 3.0の使用は禁止されました。
https://tools.ietf.org/html/rfc7568

OpenSSLとは

OpenSSLとは、インターネット上で標準的に利用される暗号通信プロトコルである
SSLおよびTLSの機能を実装した、オープンソースのライブラリです。

楕円曲線暗号とは

楕円曲線を利用した暗号方式の総称で、RSA暗号などと比べて
同レベルの安全性をより短い鍵で実現でき、処理速度も速いことがメリットとなります。

証明書の作成

サーバ証明書の作成は、
「秘密鍵の作成」
 ↓
「証明書署名要求(CSR / Certificate Signing Request)の作成」
 ↓
「サーバ証明書の作成」 という順に行われます。
作成に必要なパッケージ及び作成方法を、説明します。

1.使用モジュール

今回の楕円曲線暗号方式のサーバ証明書の作成には、以下のパッケージが必要です。
※CentOSのパッケージを使用します。
 ・openssl-1.0.2k-12.el7.x86_64
 ・mod_ssl-2.4.6-80.el7.centos.1.x86_64
 ・httpd-2.4.6-80.el7.centos.1.x86_64

2.opensslのバージョン確認

以下のコマンドで、OpenSSLのバージョンを確認します。

# openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017

3.使用可能な楕円曲線の確認

利用可能な楕円曲線は、openssl のバージョンによって異なりますので、
「-list_curves」オプションを利用して確認を行います。

# openssl ecparam -list_curves
  secp256k1 : SECG curve over a 256 bit prime field
  secp384r1 : NIST/SECG curve over a 384 bit prime field
  secp521r1 : NIST/SECG curve over a 521 bit prime field
  prime256v1: X9.62/SECG curve over a 256 bit prime field

※ビットコインでは、署名に楕円曲線暗号secp256k1が使われているようです。

4.秘密鍵の作成

openssl の「-genkey」オプションで秘密鍵を作成します。
今回は、暗号化アルゴリズムとして「prime256v1」を使用します。

# openssl ecparam -name prime256v1 -genkey > localhost.key

秘密鍵の確認をします。

# openssl ec -in localhost.key -text -noout
read EC key
Private-Key: (256 bit)
priv:
    68:da:12:d4:a3:52:e7:ae:20:c5:67:b1:ec:33:dc:
    ce:73:63:99:0f:b7:67:b2:10:92:ba:e7:b1:a8:4a:
    75:7b
pub:
    04:5b:d6:20:4d:3d:29:42:90:99:21:a1:3c:37:32:
    ab:27:5d:f7:54:48:0c:ef:79:c8:e5:9f:fb:cf:69:
    71:3b:b1:f9:cb:71:61:86:bc:61:51:67:16:02:21:
    85:7f:30:54:2a:51:e1:3d:96:3b:0e:e4:22:47:a2:
    b6:4d:d5:0a:e5
ASN1 OID: prime256v1
NIST CURVE: P-256

5.証明書署名要求の作成

作成した「秘密鍵」を元に、証明書署名要求(CSR)を作成します。

# openssl req -new -sha256 -key localhost.key > localhost.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Shinagawa-ku
Organization Name (eg, company) [Default Company Ltd]:qoous
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:qoous.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:

証明書署名要求の確認をします。

# openssl req -text -noout -in localhost.csr
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=JP, ST=Tokyo, L=Shinagawa-ku, O=qoous, CN=qoous.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:5b:d6:20:4d:3d:29:42:90:99:21:a1:3c:37:32:
                    ab:27:5d:f7:54:48:0c:ef:79:c8:e5:9f:fb:cf:69:
                    71:3b:b1:f9:cb:71:61:86:bc:61:51:67:16:02:21:
                    85:7f:30:54:2a:51:e1:3d:96:3b:0e:e4:22:47:a2:
                    b6:4d:d5:0a:e5
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            a0:00
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:7e:8d:de:8c:eb:af:4e:2f:b1:3b:d4:98:20:7e:
         5b:c1:f9:d7:39:6f:7b:58:f9:70:c0:71:3e:dd:8d:86:3b:3f:
         02:20:1c:6a:43:28:72:ae:43:eb:3a:a4:b9:07:ec:8e:1e:97:
         cc:60:0f:af:47:51:22:ea:61:1d:20:31:b8:2b:ec:be

6.サーバ証明書の作成

作成した「秘密鍵」と「証明書署名要求」で、「サーバ証明書」を作成します。
「-signkey」オプションを使用します。
※自己証明書(オレオレ証明書)になります。

# openssl x509 -req -signkey localhost.key < localhost.csr > localhost.crt
Signature ok
subject=/C=JP/ST=Tokyo/L=Shinagawa-ku/O=qoous/CN=qoous.com
Getting Private key

サーバ証明書の確認

# openssl x509 -text -noout -in localhost.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            86:73:67:19:46:b1:2a:e9
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=JP, ST=Tokyo, L=Shinagawa-ku, O=qoous, CN=qoous.com
        Validity
            Not Before: Oct 13 14:52:16 2018 GMT
            Not After : Nov 12 14:52:16 2018 GMT
        Subject: C=JP, ST=Tokyo, L=Shinagawa-ku, O=qoous, CN=qoous.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:5b:d6:20:4d:3d:29:42:90:99:21:a1:3c:37:32:
                    ab:27:5d:f7:54:48:0c:ef:79:c8:e5:9f:fb:cf:69:
                    71:3b:b1:f9:cb:71:61:86:bc:61:51:67:16:02:21:
                    85:7f:30:54:2a:51:e1:3d:96:3b:0e:e4:22:47:a2:
                    b6:4d:d5:0a:e5
                ASN1 OID: prime256v1
                NIST CURVE: P-256
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:59:04:d8:cd:74:3b:6e:12:e6:14:ce:03:e6:8f:
         df:64:e3:f9:0d:e7:d9:bb:ca:f8:9c:05:14:5f:10:3a:94:c0:
         02:20:64:25:07:16:a4:5c:29:50:c6:43:e0:79:34:8d:c5:f2:
         fa:3a:b6:e4:46:24:6f:7b:98:70:8a:df:69:5d:d5:7a

Apacheの設定

作成した楕円曲線志向な証明書を利用して、ApacheのSSL設定を行います。
ssl.confの設定
デフォルトでは、「/etc/httpd/conf.d」ディレクトリにあります。 サーバ証明書と暗号鍵の場所を指定します。

# 変更前
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
# 変更後
SSLCertificateFile /etc/httpd/conf/localhost.crt
SSLCertificateKeyFile /etc/httpd/conf/localhost.key

セキュリティの強化のため、以下の設定をします。

# 変更前
SSLProtocol all -SSLv2 -SSLv3
#SSLHonorCipherOrder on
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
# 変更後
SSLProtocol -all +TLSv1.2
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:!RC4:!LOW:!MD5:!aNULL:!eNULL:!3DES:!EXP:!PSK:!SRP:!DSS:!ADH:!DH

※設定後は、Apacheを再起動してください。

TLS1.2の動作確認

opensslの「s_client」オプションで、TLS1.2のみ許可されていることを確認します。

# openssl s_client -connect localhost:443 -tls1_2
CONNECTED(00000003)
**** 省略 ****
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 924 bytes and written 415 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-AES256-GCM-SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2 # TLS1.2が使用されている事が確認できます。
    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384 # 暗号化方式が表示されます。
**** 省略 **** 

TLS1.2以外(TLS1.1の場合)のプロトコルの場合は以下のように失敗します。

# openssl s_client -connect localhost:443 -tls1_1
CONNECTED(00000003)
**** 省略 ****
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.1 # TLS1.1が使用されている事が確認できます。
    Cipher    : 0000 # 暗号化方式が表示されません
**** 省略 ****

HTTPS接続確認

ウェブブラウザーでの確認
IEにApacheの接続URLを入力して、接続を行います。

コマンドツールでの確認
・curl
以下のコマンドを実行します。

# curl --cacert /etc/httpd/conf/localhost.crt --tlsv1.2 -v https://qoous.com/index.html > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to qoous.com port 443 (#0)
*   Trying 192.168.11.99...
* Connected to qoous.com (192.168.11.99) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/httpd/conf/localhost.crt
  CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*       subject: CN=qoous.com,O=qoous,L=Shinagawa-ku,ST=Tokyo,C=JP
*       start date: 10月 13 15:30:29 2018 GMT
*       expire date: 11月 12 15:30:29 2018 GMT
*       common name: qoous.com
*       issuer: CN=qoous.com,O=qoous,L=Shinagawa-ku,ST=Tokyo,C=JP
> GET /index.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: qoous.com
> Accept: */*
>
< HTTP/1.1 200 OK # HTTPステータスコードが200である事を確認します。
< Date: Sun, 14 Oct 2018 01:24:36 GMT
< Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
< Last-Modified: Sun, 14 Oct 2018 01:19:01 GMT
< ETag: "64-578261b14aaf4"
< Accept-Ranges: bytes
< Content-Length: 100
< Content-Type: text/html; charset=UTF-8
<
{ [data not shown]
100   100  100   100    0     0   2495      0 --:--:-- --:--:-- --:--:--  2564
* Connection #0 to host qoous.com left intact

・wget
以下のコマンドを実行します。

# wget --spider --secure-protocol=TLSv1_2  -S -d --ca-certificate=/etc/httpd/conf/localhost.crt https://qoous.com/index.html
Setting --ca-certificate (cacertificate) to /etc/httpd/conf/localhost.crt
DEBUG output created by Wget 1.14 on linux-gnu.

URI encoding = `UTF-8'
Converted file name 'index.html' (UTF-8) -> 'index.html' (UTF-8)
Converted file name 'index.html' (UTF-8) -> 'index.html' (UTF-8)
スパイダーモードが有効です。リモートファイルが存在してるか確認します。
--2018-10-14 10:27:03--  https://qoous.com/index.html
qoous.com (qoous.com) をDNSに問いあわせています... 192.168.11.99
Caching qoous.com => 192.168.11.99
qoous.com (qoous.com)|192.168.11.99|:443 に接続しています... 接続しました。
Created socket 3.
Releasing 0x0000000002479ed0 (new refcount 1).
Initiating SSL handshake.
Handshake successful; connected socket 3 to SSL handle 0x0000000002489340
certificate:
  subject: /C=JP/ST=Tokyo/L=Shinagawa-ku/O=qoous/CN=qoous.com
  issuer:  /C=JP/ST=Tokyo/L=Shinagawa-ku/O=qoous/CN=qoous.com
X509 certificate successfully verified and matches host qoous.com

---request begin---
HEAD /index.html HTTP/1.1
User-Agent: Wget/1.14 (linux-gnu)
Accept: */*
Host: qoous.com
Connection: Keep-Alive

---request end---
HTTP による接続要求を送信しました、応答を待っています...
---response begin---
HTTP/1.1 200 OK # HTTPステータスコードが200である事を確認します。
Date: Sun, 14 Oct 2018 01:27:03 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
Last-Modified: Sun, 14 Oct 2018 01:19:01 GMT
ETag: "64-578261b14aaf4"
Accept-Ranges: bytes
Content-Length: 100
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

---response end---

  HTTP/1.1 200 OK # HTTPステータスコードが200である事を確認します。
  Date: Sun, 14 Oct 2018 01:27:03 GMT
  Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
  Last-Modified: Sun, 14 Oct 2018 01:19:01 GMT
  ETag: "64-578261b14aaf4"
  Accept-Ranges: bytes
  Content-Length: 100
  Keep-Alive: timeout=5, max=100
  Connection: Keep-Alive
  Content-Type: text/html; charset=UTF-8
Registered socket 3 for persistent reuse.
URI content encoding = `UTF-8'
長さ: 100 
リモートファイルが存在し、さらなるリンクもあり得ますが、再帰が禁止されています -- 取得しません

まとめ

以上で楕円曲線志向な証明書の作成と、Apacheの設定及びHTTPSのテストを行ってみました。

近年、HTTPSを使用するウェブサイトが増加しています。
楕円曲線暗号アルゴリズムの特性から、ECC鍵は短い鍵長でも高い暗号強度があります。
短い鍵長で強度を保てるため、長い鍵長によってコンピュータに過度な負荷をかけることがなくなります。
RSA秘密鍵が多く使用されておりますが、
RSAより優れたECCにてHTTPSを構築してみるのは如何でしょうか。

是非、試して頂ければと思います。
最後までお読みいただき、ありがとうございます。

趙 英熙
CSVIT事業部 LS(リーディングサービス)部 趙 英熙
主にインフラの仕事に携わっています。