長いので、真面目にCAを立てるつもりが無ければ、「結論」だけ読めばok。
『証明書』を必要とする人が提出した『リクエスト』から、CAの署名入り『証明書』を生成する、何らかのシステム。
認証を行うシステムなので、CA自身にも信用/信頼といった物が必要。
認証局は、大会社だったり、単にファイル一式が入っただけのディレクトリだったりする。
尚、CAが、『リクエスト』から署名入り『証明書』を発行する為には、CA自分自身の秘密鍵と証明書が必要となる。
コレがあると、公開鍵によって暗号化されたデータを、復号化して取り出す事が出来る鍵ファイル。
コレが他人の手に渡ると、せっかく暗号化した内容を解読されてしまう。バレないようにする必要がある。
この秘密鍵自体にパスフレーズを付け、秘密鍵を使う際にはパスフレーズを要求するようにする事も出来る。
ファイルの拡張子は通常pemまたはkey。
データを暗号化する為の鍵ファイル。
秘密鍵から生成される。
基本的には、コレが無いとSSL暗号化通信ができないので、ssh等では、サーバに接続後真っ先にこの公開鍵が送られてくる。
ファイルの拡張子は通常pemまたはpub。
CAの署名入り『証明書』を、CAに作ってもらう為に必要になるファイル。
秘密鍵から作成する。
証明書に記述されている各種の情報は、この時点で、X.509形式でリクエストに含めておく。
ファイルの拡張子は通常pemまたはcsr。
『秘密鍵』(の保有者)の身元を証明するファイル。CAによって生成される。
内容的には、証明書は、CAによって署名(サイン)されただけの『リクエスト』そのもの、と考えて良いようだ。
証明書には公開鍵が含まれている為、証明書を使ってSSL暗号化通信を行う事が出来る。
ファイルの拡張子は通常pemまたはcrt。
証明書は通常、用途によって、使い途が限定されている(限定されないように作る事も出来る)。
よく使われる証明書として、以下のものがある。
CAによって署名された証明書は、CAによって何時でも(署名を)失効させる事が出来る。その、(署名を)失効させた証明書のリストが書かれたファイル。
尚、指定された期限が切れても、署名は失効する。
ファイルの拡張子は通常pemまたはcrl。
opensslを使って、プライベートCAを作った時の手順メモ。
コレが正しいかどうかは怪しげ。
CA_DIR=/var/lib/ca CA_URL=http://ca.tir.jp/ CA_CRT_URL=http://ca.tir.jp/ca.tir.jp.crt CA_CRL_URL=http://ca.tir.jp/ca.tir.jp.crl
cd ${CA_DIR}
cat > openssl.ca.conf <<EOF
RANDFILE = \$ENV::HOME/.rnd
oid_file = \$ENV::HOME/.oid
oid_section = new_oids
[ new_oids ]
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = ${CA_DIR}
certs = \$dir/certs
crl_dir = \$dir/crl
database = \$dir/index.txt
new_certs_dir = \$dir/newcerts
certificate = \$dir/ca.cert.pem
serial = \$dir/serial
crl = \$dir/ca.crl.pem
private_key = \$dir/private/ca.key.pem
RANDFILE = \$dir/private/.rand
x509_extensions = cert_plain
crl_extensions = crl_ext
name_opt = ca_default
cert_opt = ca_default
default_days = 365
default_crl_days = 7
default_md = sha1
preserve = no
policy = policy_anything
[ policy_match ]
countryName = match
stateOrProvinceName = optional
localityName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ cert_plain ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
[ cert_ca ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = cRLSign, keyCertSign
issuerAltName = URI:${CA_CRT_URL}
crlDistributionPoints = URI:${CA_CRL_URL}
[ cert_server ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
nsCertType = server
keyUsage = digitalSignature, keyEncipherment
issuerAltName = URI:${CA_CRT_URL}
crlDistributionPoints = URI:${CA_CRL_URL}
[ cert_client ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
nsCertType = client, email
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
issuerAltName = URI:${CA_CRT_URL}
crlDistributionPoints = URI:${CA_CRL_URL}
[ crl_ext ]
#issuerAltName = issuer:copy
authorityKeyIdentifier = keyid:always,issuer:always
EOF
cat > openssl.req.conf <<EOF
RANDFILE = \$ENV::HOME/.rnd
oid_file = \$ENV::HOME/.oid
oid_section = new_oids
[ new_oids ]
[ req ]
default_bits = 1024
distinguished_name = req_distinguished_name
attributes = req_attributes
default_md = sha1
x509_extensions = v3_plain
string_mask = nombstr
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = JP
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Hyogo
localityName = Locality Name (eg, city)
localityName_default = Kawanishi
0.organizationName = Organization Name (eg, company)
0.organizationName_default = tir.jp
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = ca
commonName = Common Name (***IMPORTANT***)
commonName_max = 64
emailAddress = Email Address
emailAddress_default = yamada@tir.jp
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ v3_plain ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
# use only create to self-signed certificate of CA
[ v3_self_ca ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = cRLSign, keyCertSign
nsCertType = sslCA, emailCA
issuerAltName = URI:${CA_CRT_URL}
crlDistributionPoints = URI:${CA_CRL_URL}
nsBaseUrl = ${CA_URL}
nsCaRevocationUrl = ${CA_CRL_URL}
nsRevocationUrl = ${CA_URL}
nsRenewalUrl = ${CA_URL}
nsCaPolicyUrl = ${CA_URL}
EOF
touch index.txt echo '01' > serial chmod 644 ca.conf index.txt serial mkdir -p certs crl newcerts private work chmod 755 . certs crl newcerts chmod 700 private work
openssl genrsa -des3 -out private/ca.key.pem 1024 \ && chmod 400 private/ca.key.pem
openssl req \ -config ~/openssl.req.conf \ -new \ -key private/ca.key.pem \ -out work/ca.request.pem
openssl req \ -config ~/openssl.req.conf \ -extensions v3_self_ca \ -x509 \ -key private/ca.key.pem \ -in work/ca.request.pem \ -out ./ca.cert.pem \ -days 3650
rm work/ca.request.pem
openssl ca \ -config ~/openssl.ca.conf \ -gencrl \ -out ./ca.crl.pem
openssl crl -in ca.crl.pem -text
AddType application/x-x509-ca-cert .crt AddType application/pkix-crl .crl
ln -sf ca.cert.pem `openssl x509 -noout -hash < ca.cert.pem`.0 ln -sf ca.crl.pem `openssl crl -noout -hash < ca.crl.pem`.r0
以上で、CAとして機能する為に必要な準備は完了。
しかし、毎回コマンドを入力するのは面倒なので、スクリプトを用意しておく。
cat > server_keycertgen.sh <<EOF
#!/bin/sh
EXTENSIONS=cert_server
if [ \$1 ]; then
cd ${CA_DIR} || exit 1
if [ -e private/\$1.keycert.pem ]; then
echo "'private/\$1.keycert.pem' already exists!" 1>&2
exit 1
else
openssl genrsa -out work/\$1.key.pem 1024 \\
&& chmod 400 work/\$1.key.pem \\
&& openssl req \\
-config ~/openssl.req.conf \\
-new \\
-key work/\$1.key.pem \\
-out work/\$1.request.pem \\
&& openssl ca \\
-config ~/openssl.ca.conf \\
-policy policy_anything \\
-extensions \${EXTENSIONS} \\
-out work/\$1.cert.pem \\
-days 365 \\
-infiles work/\$1.request.pem \\
&& cat work/\$1.key.pem work/\$1.cert.pem \\
> private/\$1.keycert.pem \\
&& chmod 400 private/\$1.keycert.pem \\
&& echo "'private/\$1.keycert.pem' created."
rm -f work/\$1.key.pem work/\$1.request.pem work/\$1.cert.pem
fi
else
echo "usage : \$0 target-name" 1>&2
exit 1
fi
EOF
cat > client_keycertgen.sh <<EOF
#!/bin/sh
EXTENSIONS=cert_client
if [ \$1 ]; then
cd ${CA_DIR} || exit 1
if [ -e private/\$1.keycert.pem ]; then
echo "'private/\$1.keycert.pem' already exists!" 1>&2
exit 1
else
openssl genrsa -out work/\$1.key.pem 1024 \\
&& chmod 400 work/\$1.key.pem \\
&& openssl req \\
-config ~/openssl.req.conf \\
-new \\
-key work/\$1.key.pem \\
-out work/\$1.request.pem \\
&& openssl ca \\
-config ~/openssl.ca.conf \\
-policy policy_anything \\
-extensions \${EXTENSIONS} \\
-out work/\$1.cert.pem \\
-days 365 \\
-infiles work/\$1.request.pem \\
&& cat work/\$1.key.pem work/\$1.cert.pem \\
> private/\$1.keycert.pem \\
&& chmod 400 private/\$1.keycert.pem \\
&& echo "'private/\$1.keycert.pem' created."
rm -f work/\$1.key.pem work/\$1.request.pem work/\$1.cert.pem
fi
else
echo "usage : \$0 target-name" 1>&2
exit 1
fi
EOF
cat > ca_keycertgen.sh <<EOF
#!/bin/sh
EXTENSIONS=cert_ca
if [ \$1 ]; then
cd ${CA_DIR} || exit 1
if [ -e private/\$1.keycert.pem ]; then
echo "'private/\$1.keycert.pem' already exists!" 1>&2
exit 1
else
openssl genrsa -out work/\$1.key.pem 1024 \\
&& chmod 400 work/\$1.key.pem \\
&& openssl req \\
-config ~/openssl.req.conf \\
-new \\
-key work/\$1.key.pem \\
-out work/\$1.request.pem \\
&& openssl ca \\
-config ~/openssl.ca.conf \\
-policy policy_anything \\
-extensions \${EXTENSIONS} \\
-out work/\$1.cert.pem \\
-days 365 \\
-infiles work/\$1.request.pem \\
&& cat work/\$1.key.pem work/\$1.cert.pem \\
> private/\$1.keycert.pem \\
&& chmod 400 private/\$1.keycert.pem \\
&& echo "'private/\$1.keycert.pem' created."
rm -f work/\$1.key.pem work/\$1.request.pem work/\$1.cert.pem
fi
else
echo "usage : \$0 target-name" 1>&2
exit 1
fi
EOF
chmod a+x server_keycertgen.sh
chmod a+x client_keycertgen.sh
chmod a+x ca_keycertgen.sh
コレで、簡単に証明書が作れるようになった。
./server_keycertgen.sh fqdnで、幾つかの質問とCAのパスフレーズを入力するだけで、
private/fqdn.keycert.pemが生成される。この内容については後述。
./client_keycertgen.sh client_nameで、幾つかの質問とCAのパスフレーズを入力するだけで、
private/client_name.keycert.pemが生成される。
openssl genrsa -out path/to/ssl.tir.jp.key.pem 1024 \ && chmod 400 path/to/ssl.tir.jp.key.pem
openssl genrsa -des3 -out path/to/ssl.tir.jp.key.pem 1024 \ && chmod 400 path/to/ssl.tir.jp.key.pem
openssl rsa -in path/to/ssl.tir.jp.key.pem -text
(作った秘密鍵の身元を保証する為の)証明書をCAに作ってもらう為に必要になるリクエストは、以下の手順で作成する。
openssl req \ -config ~/openssl.req.conf \ -new \ -key path/to/ssl.tir.jp.key.pem \ -out path/to/ssl.tir.jp.request.pem
openssl req -in path/to/ssl.tir.jp.request.pem -text
openssl ca \ -config ~/openssl.ca.conf \ -policy policy_anything \ -extensions cert_server \ -out work/ssl.tir.jp.cert.pem \ -days 365 \ -infiles work/ssl.tir.jp.request.pem
openssl asn1parse -i -in work/ssl.tir.jp.cert.pem
cat path/to/ssl.tir.jp.key.pem path/to/ssl.tir.jp.cert.pem \ > path/to/ssl.tir.jp.keycert.pem chmod 400 path/to/ssl.tir.jp.keycert.pem
openssl pkcs12 \ -export \ -in path/to/client.keycert.pem \ -out path/to/client.p12 \ -name "certificate of user yamada for ssl.tir.jp"
apacheでの例 : apache:mod_ssl
https://localhost:8888/にアクセスする事で、動作確認が出来る。
openssl s_server -accept 8888 -www \ -cert 秘密鍵込み証明書ファイル
openssl s_server -accept 8888 -www \ -cert 秘密鍵込み証明書ファイル \ -CAfile CA自身の証明書ファイル
openssl s_server -accept 8888 -www \ -cert 秘密鍵込み証明書ファイル \ -CApath ※以下の説明のディレクトリ
ln -s ca.cert.pem `openssl x509 -noout -hash < ca.cert.pem`.0
ln -s ca.crl.pem `openssl crl -noout -hash < ca.crl.pem`.r0