Edited at

クライアント証明書を要求するサイトの構築(Apache+OpenSSL)その1


参考にしたサイト

クライアント証明書を要求するサイトの構築(Apache+OpenSSL)その2 - Qiita [キータ]書きました。


ランダムパスワード生成方法


  • 多くのパスワードを作る必要があるのでpwgen使うと便利。


サーバ証明書の作成


1. 独自認証局の秘密鍵、ルート証明書(CA)の作成


  • C: 国名 (JP)

  • ST: 都道府県 (Tokyo)

  • O: 会社名 (My Company Ltd)

  • OU: 部署名 (sales)

  • CN:サーバーのドメイン名 (mycompany.co.jp:8000等。証明書の表示名に使われます。)

cd /opt/

mkdir -p demoCA/{private,newcerts}
cd demoCA
echo 01 > serial

openssl req \

-x509 \
-days 3650 \
-newkey rsa:2048 \
-keyout private/cakey.pem \
-out cacert.pem \
-subj "/C=JP/ST=Tokyo/O=localhost/OU=test/CN=$(hostname)"

# cakey.pem のパスワードを入力

file
備考

private/cakey.pem
秘密鍵

cacert.pem
認証局(CA)証明書


2. 秘密鍵とサーバ署名要求(CSR)の作成


サーバ証明書

cd /opt/demoCA/

openssl req \
-newkey rsa:2048 \
-keyout newkey.pem \
-out newreq.pem \
-subj "/C=JP/ST=Tokyo/O=localhost/OU=test/CN=$(hostname)"

# newkey.pem のパスワードを入力


file
備考

newkey.pem
ホストキー(パスワードあり)

newreq.pem
ホスト証明書


3.パスワードなしのホストキー作成

apacheに組みこむ用。


/opt/demoCA/

openssl rsa -in newkey.pem -out nokey.pem

# newkey.pem のパスワードを入力


4. CSRへの署名


/opt/demoCA/

touch index.txt

cd /opt

openssl ca \
-in demoCA/newreq.pem \
-days 3650 \
-out demoCA/cert.pem \
-notext
# /opt/demoCA/private/cakey.pem のパスワードを入力



5. openssl.cnfを編集

cd /opt/demoCA

cp -a /etc/ssl/openssl.cnf .

openssl.cnfを書き換える


openssl.cnf.patch

/opt/demoCA/openssl.cnf--- /etc/ssl/openssl.cnf 2017-05-19 17:31:50.000000000 +0900

+++ openssl.cnf 2018-10-16 09:16:10.628048155 +0900
@@ -39,7 +39,7 @@
####################################################################
[ CA_default ]

-dir = ./demoCA # Where everything is kept
+dir = /opt/demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
@@ -70,9 +70,9 @@
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext

-default_days = 365 # how long to certify for
+default_days = 3650 # how long to certify for
default_crl_days= 30 # how long before next CRL
-default_md = default # use public key default MD
+default_md = sha256 # use public key default MD
preserve = no # keep passed DN ordering

# A few difference way of specifying how similar the request should look
@@ -85,8 +85,8 @@
countryName = match
stateOrProvinceName = match
organizationName = match
-organizationalUnitName = optional
-commonName = supplied
+organizationalUnitName = supplied
+commonName = optional
emailAddress = optional

# For the 'anything' policy
@@ -97,8 +97,8 @@
stateOrProvinceName = optional
localityName = optional
organizationName = optional
-organizationalUnitName = optional
-commonName = supplied
+organizationalUnitName = supplied
+commonName = optional
emailAddress = optional

####################################################################
@@ -126,23 +126,23 @@

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
-countryName_default = AU
+countryName_default = JP
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
-stateOrProvinceName_default = Some-State
+stateOrProvinceName_default = Tokyo

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
-0.organizationName_default = Internet Widgits Pty Ltd
+0.organizationName_default = localhost

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

-organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName = Organizational Unit Name (eg, username)
#organizationalUnitName_default =

commonName = Common Name (e.g. server FQDN or YOUR name)



6. 証明書失効リスト用

echo "00" > crlnumber


クライアント用証明書の作成


p12キーの生成

各クライアントに配布する用にp12キーを生成。

クライアント名.p12 のパスワードも伝える必要がありますので、クライアント名.p12.txtにパスワードを書いときます。

このp12キーはクライアントの端末にインストールすることになります。


/opt/demoCA/create_cert.sh

#!/bin/sh

set -eux

CLNT=$1
CA_ROOT=/opt/demoCA
REPOS=${CA_ROOT}/repository
mkdir -p $REPOS/${CLNT}

# key : 秘密鍵生成
openssl genrsa -rand /var/log/messages -out ${REPOS}/${CLNT}/${CLNT}-client.key -des3 2048

# key -> csr : 署名要求
openssl req -new -key ${REPOS}/${CLNT}/${CLNT}-client.key -out ${REPOS}/${CLNT}/${CLNT}-client.csr -config openssl.cnf

# csr -> pem : 署名(Base64形式)
openssl ca -config openssl.cnf -keyfile ${CA_ROOT}/private/cakey.pem -cert ${CA_ROOT}/cacert.pem -in ${REPOS}/${CLNT}/${CLNT}-client.csr -out ${REPOS}/${CLNT}/${CLNT}-client.pem

# pem -> crt : 証明書
openssl x509 -in ${REPOS}/${CLNT}/${CLNT}-client.pem -out ${REPOS}/${CLNT}/${CLNT}-client.crt

# crl (失効リスト更新)
openssl ca -config openssl.cnf -gencrl -out ${CA_ROOT}/ca.crl -keyfile ${CA_ROOT}/private/cakey.pem -cert ${CA_ROOT}/cacert.pem -verbose -crldays 3650

# p12 (webブラウザ用。秘密鍵と公開鍵(証明書)を PKCS #12ファイルにまとめる)
openssl pkcs12 -export -in ${REPOS}/${CLNT}/${CLNT}-client.crt -inkey ${REPOS}/${CLNT}/${CLNT}-client.key -out ${REPOS}/${CLNT}/${CLNT}-client.p12 -certfile ${CA_ROOT}/cacert.pem -name 'demoCA Client Cert' -caname 'demoCA'

#p12.txt (p12のパスワードをtxtに保存)
echo -n "enter ${CLNT}.p12 pass : "
read P12PASS
echo ${P12PASS} > ${REPOS}/${CLNT}/${CLNT}-client.p12.txt


途中パスワード入力を間違えると手動でのリカバリーが大変なのでバージョン管理で戻せるようにする。

chmod +x create_cert.sh

git init
git add -A && git commit -m "init"


使い方

./create_cert.sh kitamura

# repository/ユーザ名/ユーザ名.key のパスワード
# repository/ユーザ名/ユーザ名.p12 のパスワード
# private/cakey.pemのパスワード

git add -A && git commit -m "add: クライアント名"


Apacheの設定

sudo sh -c "echo ServerName $HOSTNAME" >> /etc/apache2/httpd.conf


/etc/apache2/sites-available/default-ssl.conf

SSLCertificateFile    /opt/demoCA/cert.pem

SSLCertificateKeyFile /opt/demoCA/nokey.pem
SSLCACertificateFile /opt/demoCA/cacert.pem
<Location /owncloud/>
SSLVerifyClient require
</Location>

a2enmod ssl

a2ensite default-ssl

sudo apachectl configtest
sudo /etc/init.d/apache2 restart


(memo) pemファイルの変換

openssl pkcs12 -export -in [input_file] -out [output_file]

openssl x509 -in [input_file] -inform PEM -text -noout