openssl:CA

[トップ][一覧][最近の更新]

長いので、真面目にCAを立てるつもりが無ければ、「結論」だけ読めばok。



用語定義

CA, 認証局

『証明書』を必要とする人が提出した『リクエスト』から、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。

プライベートCAを作る

opensslを使って、プライベートCAを作った時の手順メモ。

コレが正しいかどうかは怪しげ。

  1. 先にCA専用アカウントを用意し、suしておく。
  2. CAの名前、設置するディレクトリ、サイトURL, 証明書URL, 失効リストURLを決めておく。
    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
    
  3. CA用ディレクトリに入っておく。
    cd ${CA_DIR}
    
  4. 設定ファイルを作成する。
    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
    
  5. その他のファイルとディレクトリを作成する。
    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
    
  6. このCA自身の秘密鍵(ca.key.pem)を作る。
    openssl genrsa -des3 -out private/ca.key.pem 1024 \
      && chmod 400 private/ca.key.pem
    
  7. 秘密鍵から、このCA自身の証明書を作る為のリクエスト(ca.request.pem)を作る。
    openssl req \
      -config ~/openssl.req.conf \
      -new \
      -key private/ca.key.pem \
      -out work/ca.request.pem
    
  8. リクエストから、このCA自身の証明書(ca.cert.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
    
  9. リクエストはもう不要なので消しておく。
    rm work/ca.request.pem
    
  10. このCAから発行した証明書の失効リストを作る。
    openssl ca \
      -config ~/openssl.ca.conf \
      -gencrl \
      -out ./ca.crl.pem
    
  11. 証明書と失効リストを、配布URLに設置する。
  12. hash linkを作る。
    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

コレで、簡単に証明書が作れるようになった。

秘密鍵を作る

リクエストを作る

(作った秘密鍵の身元を保証する為の)証明書をCAに作ってもらう為に必要になるリクエストは、以下の手順で作成する。

  1. まず最初に、設定ファイルを作っておく。
  2. 秘密鍵からリクエストを生成する。
    openssl req \
      -config ~/openssl.req.conf \
      -new \
      -key path/to/ssl.tir.jp.key.pem \
      -out path/to/ssl.tir.jp.request.pem
    

証明書を作る

秘密鍵と証明書を合成する

pkcs#12形式のクライアント証明書を作る

  1. 予め、先に述べた手順で、クライアント用の秘密鍵、リクエスト、証明書を作っておき、秘密鍵と証明書を合成しておく。
  2. 合成された秘密鍵と証明書を、ブラウザに組み込める形に変換する
    openssl pkcs12 \
      -export \
      -in path/to/client.keycert.pem \
      -out path/to/client.p12 \
      -name "certificate of user yamada for ssl.tir.jp"
    

生成したCA証明書、サーバ証明書、クライアント証明書を使ってみる

apacheでの例 : apache:mod_ssl

その他おぼえがき

プライベートCAのデメリット

結論

参考にしたリンク



最終更新 : 2009/12/24 12:37:01 JST