ま、そんなところで。

ニッチな技術系メモとか、車輪を再発明してみたりとか.

OpenSSLでx509証明書 (1) 〜 ルート認証局を作る 〜

OpenSSLを使って自己署名証明書認証局(CA)を作ってみたのでメモ.

1. 自己署名証明書によるルート認証局を作る手順

1-1. 認証局ディレクトリ構造とファイルの配置

まず最初に証明書を作成する手順で必要なファイルの準備を行う ここでは認証局ディレクトリを「rootCA」とする.
以下の構造でディレクトリ/ファイルを配置.

認証局(CA)のディレクトリ・ファイル配置
rootCA/
  ├── certs/                // <- 生成した証明書格納用ディレクトリ
  ├── conf/                 // <- 設定ファイル配置ディレクトリ
  │     ├── signCA.cnf    // /etc/ssl/openssl.cnf をコピー
  │     └── signCert.cnf  // /etc/ssl/openssl.cnf をコピー
  ├── crl/                  // 証明書失効リスト配置用
  ├── crlnumber            // 空ファイル. CAが使用する
  ├── index.txt            // 空ファイル. CAが使用する. 証明書データベースファイル.
  ├── keys/                // 生成した秘密鍵を配置する
  ├── newcerts/            // 署名した証明書の控え
  ├── private/             // CAの秘密鍵を配置する
  ├── serial               // テキストファイル. 00とだけ入力. 次の証明書のシリアル値.
  └── site/                // CAが使用する

ディレクトリ構造を一発で配置するスクリプト.

makeCAdirs.sh
#!/bin/sh
#
# "CA用のディレクトリを生成します.."
#
 
if [ $# -ne 1 ]; then
        echo "CAのディレクトリ構造を指定したDirectory以下に生成します."
        echo "[Usage] ./makeCAdirs.sh [Directoryパス]"
        exit 1
fi
 
echo "CAのディレクトリ構造を生成しています"
CADIR=$1 # rootCA
echo "CADIR=${CADIR}"
 
mkdir -p ${CADIR}/certs
mkdir -p ${CADIR}/conf
mkdir -p ${CADIR}/crl
mkdir -p ${CADIR}/keys
mkdir -p ${CADIR}/newcerts
mkdir -p ${CADIR}/site
mkdir -p ${CADIR}/private
 
touch ${CADIR}/index.txt
touch ${CADIR}/crlnumber
echo 00 > ${CADIR}/serial
 
echo "設定ファイルテンプレートを配置しています.."
cp /etc/ssl/openssl.cnf ${CADIR}/conf/signCA.cnf
cp /etc/ssl/openssl.cnf ${CADIR}/conf/signCert.cnf
 
echo "完了!"

コレを実行.

$ ./makeCAdirs.sh rootCA



1-2. 設定ファイルの編集

認証局作成用、秘密鍵/証明書ペア作成用にそれぞれ設定ファイルを変更します.
ファイルの用途は以下の通り.

  • signCA.cnf → 自己署名ルートCA/中間CAの秘密鍵/証明書作成用
  • signCert.cnf → 一般の秘密鍵/証明書作成用


1-2-1. 認証局(CA)作成用設定ファイル(signCA.cnf)の編集

CAの秘密鍵生成と証明書作成に使用するsignCA.cnfを書き換える.

 

signCA.cnf (書き換え箇所のみ抜粋)
        :
[ CA_default ] # CAとして証明書署名要求へ署名するときに使用する設定
dir             = /backup/sample/rootCA   # ← 認証局ディレクトリ(絶対パス)
certs           = $dir/certs           
crl_dir         = $dir/crl             
database        = $dir/index.txt       
new_certs_dir   = $dir/newcerts        
 
certificate     = $dir/cacert.pem         # CAの証明書
serial          = $dir/serial      
crlnumber       = $dir/crlnumber   
crl             = $dir/crl.pem     
private_key     = $dir/private/cakey.pem  # CAの秘密鍵
RANDFILE        = $dir/private/.rand    
         :
         :
[ usr_cert ] # 中間認証局向けv3拡張設定です
# 認証局=True
basicConstraints=CA:TRUE
# 証明書のタイプ.
# SSL 認証局, メール認証局, コードの署名者
nsCertType  = sslCA, emailCA, objCA
# 証明書の用途
# 証明書の署名, CRL の署名者
keyUsage = cRLSign, keyCertSign
# 証明書コメント.
nsComment = "Sample Intermidiate CA Certificate"
 
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
         :
         :
[ v3_ca ] # 自己署名時に使用するv3拡張設定
# 認証局=True
basicConstraints=CA:TRUE
# 証明書のタイプ.
# SSL 認証局, メール認証局, コードの署名者
nsCertType  = sslCA, emailCA, objCA
# 証明書の用途
# 証明書の署名, CRL の署名者
keyUsage = cRLSign, keyCertSign
# 証明書コメント
nsComment = "Sample Root CA Certificate"
                   
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
                  :



1-2-2. 証明書作成用設定ファイル(signCert.cnf)の編集

実際に使用する証明書/秘密鍵を生成するための設定ファイル.(修正箇所のみ抜粋)
後ほどこのファイルを使って証明書署名要求(CSR)の作成と証明書への署名を行う.

2017年5月の Chrome version 58 以降、サーバ証明書のCommonNameが無視されてsubjectAltName(SAN)が参照されるようになり、subjectAltName(SAN)が指定されていないとhttpsサーバで証明書エラーとなり暗号化されないらしい.
https用のサーバ証明書としては、マルチドメイン証明書対応が必須.
ここではマルチドメインに対応した証明書を作成できるように設定する

 

 

signCert.cnf(書き換え箇所のみ抜粋)
        :
[ CA_default ] # CAとして証明書署名要求へ署名するときに使用する設定
dir             = /backup/sample/rootCA   # ← 認証局ディレクトリ(絶対パス)
certs           = $dir/certs          
crl_dir         = $dir/crl            
database        = $dir/index.txt      
new_certs_dir   = $dir/newcerts       
  
certificate     = $dir/cacert.pem         # CAの証明書
serial          = $dir/serial     
crlnumber       = $dir/crlnumber  
crl             = $dir/crl.pem    
private_key     = $dir/private/cakey.pem  # CAの秘密鍵
RANDFILE        = $dir/private/.rand            
         :
         :
[ usr_cert ]
# CAではない
basicConstraints=CA:FALSE
# 証明書タイプ指定
# SSLサーバ証明書, SSLクライアント証明書, コード署名用証明書, S/MIME証明書
nsCertType = server, client, objsign, email
# 証明書の用途
# 否認防止, 署名, キーの暗号化
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# 証明書のコメント
nsComment           = "Sample Certificate with Sample CA"
# CN代替名の挿入
subjectAltName   = @dummy_names
 
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
 
# CNの代替名リストのダミーです
# ** 使用時にコマンドで置換します **
[dummy_names]
# DNS.1, DNS.2, ... と入力していきます.
# DNSはFDQN, IPはIPアドレスを入力します
DNS.1=localhost
#DNS.2=p1234.hogehoge.co.jp
#DNS.3=localhost
#IP.1=192.168.11.128
         :
         :

1-3. ルート認証局(CA)の秘密鍵自己署名証明書の生成

以下のコマンドを実行
鍵ビット長はセキュリティ上、RSA 2048bit を指定するのが推奨されているらしい.

$ openssl req -new -newkey rsa:[鍵ビット長] \
  -x509 -sha256 -days [有効日数]\
  -config {rootCAのDir}/conf/signCA.cnf  \
  -keyout {rootCAのDir}/private/cakey.pem \
  -out {rootCAのDir}/cacert.pem

 

      以下の順で入力を求められるので対応.

 

  • (1)秘密鍵のパスワードを尋ねられるので入力.
    ※ このパスワードは証明書署名要求(CSR)への署名時に必要になる.
  • (2)証明書のSubject情報(C/ST/O/OU/CN/E)を尋ねられるので適当に入力.

コマンド実行後は以下のディレクトリ構成になる.

CA証明書生成後のルートCAディレクトリ内容
rootCA/
├── cacert.pem   // <-- 生成したrootCAの自己署名証明書
├── certs/
├── conf/
│    ├── signCA.cnf
│    └── signCert.cnf
├── crl/
├── crlnumber
├── index.txt
├── keys/
├── newcerts/
├── private/
│    └── cakey.pem  // <-- 生成したrootCAの秘密鍵
├── serial
└── site/

ルート認証局は以上で完成。