長いので、真面目に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