opensslコマンドで認証局(CA)を構築してサーバ証明書を発行する
opensslコマンドとは
OpenSSLはSecure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) のプロトコルとそれに関係する標準的暗号を実装したツールキットです。 OpenSSLの暗号ライブラリの様々な暗号機能をシェルから使うためのコマンドラインです。 次のような機能があります。
- プライベート鍵と公開鍵とそのパラメータの作成と管理
- 公開鍵の暗号化操作
- X.509証明書、認証局(CA)に提出する証明書発行要求ファイル(CSR)、無効となった証明書のリスト(CRL)の作成
- メッセージダイジェストの計算
- 暗号化と暗号文の復号
- SSL/TLSクライアントとサーバのテスト
- S/MIMEサインと暗号化メールの取り扱い
- タイムスタンプの要求、生成と検証
今回は認証局(CA)を構築して、サーバ証明書を発行してみます。
準備
opensslをインストールします。
$ sudo apt-get install openssl
apacheをインストールします。
$ sudo apt-get install apache2
SSL設定の有効化します。
$ sudo a2enmod ssl
$ sudo a2ensite default-ssl
$ sudo /etc/init.d/apache2 restart
認証局(CA)の事前設定
認証局(CA)用のディレクトリを作成して、そのディレクトリを設定ファイルに記述します。 認証局に必要な情報をここに配置します。
$ sudo mkdir /etc/ssl/myCA
$ vi /etc/ssl/openssl.conf
dir = /etc/ssl/myCA
作成したmyCA配下に次のディレクトリを作成します。
$ sudo mkdir -p /etc/ssl/myCA/certs $ sudo mkdir -p /etc/ssl/myCA/private $ sudo mkdir -p /etc/ssl/myCA/crl $ sudo mkdir -p /etc/ssl/myCA/newcerts
privaeteディレクトリには秘密鍵が置かれるのでアクセス制限をかけます。
$ sudo chmod 700 /etc/ssl/myCA/private
認証局が発行する証明書にシリアル番号が付与されますが、それに使われる番号が保存されます。最初に01で初期化します。
# sudo echo “01” > /etc/ssl/myCA/serial
証明書のデータベースを初期化します。newcertsディレクトリ内に保管される証明書の番号(nn)と識別名DN(Distinguished Name)との対応表らしいです。
$ sudo tocuh /etc/ssl/myCA/index.txt
自己署名証明書/秘密鍵生成
認証局の自己署名証明書と秘密鍵を生成します。-daysは有効期限です。365日を設定しています。
$ cd /etc/ssl/myCA $ sudo openssl req -new -x509 -newkey rsa:2048 -out cacert.pem -keyout private/cakey.pem -days 365
パスフレーズを2度聞かれます。
Enter PEM pass phrase: stacktrace
その後に証明書情報を聞かれます。
Country Name (2 letter code) [AU]:JP State or Province Name (full name) []:Tokyo Locality Name (eg, city) []:City1 Organization Name (eg, company) []:Company1 Organizational Unit Name (eg, section) []:Section1 Common Name (eg, YOUR name) []:myCA Email Address []: (Enter)
証明書情報の入力が終わると以下のファイルがされます。
念の為、自己署名証明書の秘密鍵のアクセスを次のように制限しておきます。
$ chown root:root /etc/ssl/myCA/private/cakey.pem $ chmod 600 /etc/ssl/myCA/private/cakey.pem
証明書が正しくできたかを確かめるには次のコマンドを実行することで、証明書情報で入力した値を確認することができます。
$ openssl x509 -in /etc/ssl/myCA/cacert.pem -text
認証局のポリシー[ policy_match ]のorganizationNameをmatchからoptionalに変更します。 これで証明書情報の"Organization Name"が認証局と一致していなくても署名できるようになります。
$ sudo vi /etc/ssl/openssl.cnf organizationName = match ↓ organizationName = optional
サーバ認証とサーバ証明書
サーバ証明書とは
サーバを識別するための証明書です。サーバが証明書の所有者になります。 サーバ証明書は、Webサイトの所有者の情報やSSL/TLS通信における暗号化に必要な公開鍵などを含みます。 これらの情報は、先ほど作成した認証局によって署名をします。 一般的にはWebサーバとWebブラウザとのHTTPS通信において、Webサーバは証明書に記された所有者の公開鍵であることを保証します。 つまり、サーバを認証していることになります。
WebサーバでCSRを作成する
一般的にはこのWebサーバは認証局を構築したサーバとは別です。 準備と同じ手順で別のマシンにapache2のWebサーバを用意して試します。
まず、Webアプリケーション用のディレクトリを作成して、そこに鍵などを作成します。
$ sudo mkdir /etc/ssl/www.app.com
次のコマンドで鍵ペアとCSRファイルを作成します。
$ cd /etc/ssl/www.app.com $ sudo openssl req -x509 -new -keyout appkey.pem -out appcsr.pem
パスフレーズを聞かれるので入力します。
Enter PEM pass phrase: application
次は、証明書情報を入力します。 Common Nameはサーバ証明書を導入してHTTPS通信を行うサイトのURLのことです。 Common NameはWebブラウザにアドレスとして指定するURLと一致している必要があります。 実験なので、ここではマシンのIPアドレスを指定します。
Country Name (2 letter code) [AU]:JP State or Province Name (full name) []:Tokyo Locality Name (eg, city) []:City2 Organization Name (eg, company) []:Company2 Organizational Unit Name (eg, section) []:Section2 Common Name (eg, YOUR name) []:192.168.0.1 Email Address []: (Enter) A challenge password: appcsr An optional company name []: (Enter)
作成が終わると以下のファイルができあがります。
- /etc/ssl/www.app.com/appcsr.pem : 証明書署名要求(CSR)です。認証局で使います。
- /etc/ssl/www.app.com/appkey.pem : サーバ秘密鍵です。大切に保管します。
認証局での署名
ここのでの操作はWebサーバのマシンではなく、認証局を構築したマシンで行います。 上記で作成した証明書署名要求(CSR)を認証局のマシンにコピーして、認証局で次のコマンドを実施し署名します。
$sudo openssl ca -in appcsr.pem -out appcert.pem
Enter PEM pass phrase: stacktrace
署名するかどうか聞かれるので、"y"を入力します。
Certificate is to be certified until Dec 11 00:38:12 2016 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Update
次のファイルができます。
証明書が正しく出来たかを確認するには、以下のコマンドで確認できます。 入力した証明書情報が表示されれば正しくサーバ証明書ができています。
$ openssl x509 -in appcert.pem -text
サーバ証明書と秘密鍵をWebサーバに組み込む
認証局で署名したサーバ証明書(appcert.pem)をWebサーバに組み込みます。 認証局で作成した証明書(appcert.pem)をWebサーバの/etc/ssl/www.app.com/コピーします。 そして、apache2のsslの設定ファイルで、証明書ファイルと秘密鍵をこれまでで作成したファイルに変更します。
$ sudo vi /etc/apache2/sites-available/default-ssl.conf SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem ↓ SSLCertificateFile /etc/ssl/www.app.com/appcert.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key ↓ SSLCertificateKeyFile /etc/ssl/www.app.com/appkey.pem
設定ファイルの変更が終わったら、apache2を再起動します。
$ sudo /etc/init.d/apache2 restart
これでWebサーバに証明書の設定ができました。
Webブラウザに証明書を組み込む
Webブラウザの方に証明書をインストールします。 このとき、サーバ証明書をインストールすることもできたはずですが、証明書チェーンの意味がないので認証局の証明書をインストールします。 認証局の証明書をインストールすることで、インストールした認証局が署名したサーバ証明書を設定しているサーバであることを確認でき、サーバとの通信が暗号化されます。 その前に、Webブラウザ用に証明書をpem形式から、der形式に変換します。 pem形式はテキストでder形式はバイナリです。 認証局サーバで次のコマンドを実行してcacert.derを生成します。
$ sudo openssl x509 -inform PEM -outform DER -in /etc/ssl/myCA/cacert.pem -out /etc/ssl/myCA/cacert.der
WebブラウザとWebサーバの接続
cacert.derをWebブザウザにインストールする前は、httpsでWebサーバに接続すると下記のメッセージが表示されます。
"この接続ではプライバシーが保護されません"
cacert.derをWebブラウザにインストールした後は、httpsでアクセスできるようになります。 また、Webブラウザでサーバ証明書の情報を表示できると思います。 Chromeで証明書情報を確認した場合、次のような内容が表示されます。 証明書を作成した時に入力した値が表示されています。
発行先 一般名(CN) 192.168.0.1 組織(O) Company2 組織単位(OU) Section2 シリアル番号 01 発行元 一般名(CN) myCA 組織(O) Company1 組織単位(OU) Section1
例えば、Wireshakのようなパケットキャプチャーのツールでパケットを見るとTLSプロトコルで通信していることがわかります。