それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

php で 自己署名CAを使って証明書certificateを作成する例。

sample for generate certificate

php で certificate 作成する例。

証明書作成の手順

  • 発行人の秘密鍵の作成
  • 発行人の証明書の作成(自己署名・署名リクエスト)
  • 被発行人の秘密鍵の作成
  • 被発行人の証明書の作成(自己署名・署名リクエスト)
  • 発行人が署名リクエストに署名する。

詳しくは、サンプルコードを参照

phpでの秘密鍵の作成

$key = openssl_pkey_new();
openssl_pkey_export($key,$pkey_pem);

自己署名証明書の作成

$dn = ['C' => 'JP', 'ST' => 'Kyoto', 'L' => 'Kyoto City', 'O' => 'alice'];
$csr = openssl_csr_new( $dn, $key, $conf );
$cert = openssl_csr_sign( $csr, null, $key, 365, $conf );

署名リクエストへ署名

$opt = [
  'config'          => $path,
  'x509_extensions' => 'usr_cert',
];
$cert = openssl_csr_sign( $userCSR, $issuerCrt, $issuerPkey, $days=30, $opt, time() );

設定の作成

$conf = [
'config'          => $path,
'req_extensions'  => 'v3_req',
'x509_extensions' => 'v3_req',
];

注意点

php関数openssl_csr_sign() は openssl x509 -reqコマンド相当である。

openssl ca コマンドとは無関係である。

openssl_csr_signを見てみると、 openssl_csr_sign は openssl の X509_sign( int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); ) を用いていることがわかる。

また、openssl_csr_signopenssl_csr_new が受け入れるオプションはかなり制限されているとわかる。

subjectAltName の取り扱い。

上記の注意点に留意すると、subjectAltNameは署名時・リクエスト作成時、それぞれ設定が必要がある。 openssl CAでよくある例の、openssl ca .. copy_extensions=copyのようなコピーは不可能である。

このあたりは不自由であるが、CA機能未使用のため仕方ないものとして受け入れるしかない

リクエスト作成時のSAN指定サンプルは見つかるが、一方でX509_signのSAN指定サンプルは簡単に見つからないので注意したい。

php でのopenssl.cnf

php -i | grep ssl で得られるopenssl.cnf が標準的に使われている。

openssl.cnf の構造

個人的な見解であるが、次のようになっている。

[name]
my_name = my_reference
[my_reference]
my_list = @my_list
[my_list]
item = value
item = value

どのセクションが使われるのかはopensslのどの機能を使うかによる。署名リクエスト(req)のときは[req]セクションが使われる。認証局(CA)のときは、[ca]セクションが使われる。

リクエスト作成時のcnf

リクエスト作成時には [req]が使われる。

distinguished_name = req_distinguished_nameの設定により、[req_distinguished_name]を参照することを明示している #req_extensions=v3_reqコメントアウトしているが、phpではreq_extensionsセクション名はphpから指定するため。openssl コマンドでも同様に、オプションで渡すことが可能。

[ req ]
distinguished_name = req_distinguished_name
# req_extensions = v3_req
[ req_distinguished_name ]

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = DNS:mydomain.tld, DNS:seconddomain.tld
nsComment = "Generated Certificate by plain php"

署名時のopenssl.cnf

署名時には、X509.extensionusr_certという名前で指定して、SubjectAltNameを登録している。

phpではx509_extensions=usr_certとセクション名を関数から指定可能である。openssl コマンドも同様のオプションを渡すことが可能である。

[ usr_cert ]
basicConstraints=CA:FALSE
nsComment = "[php] OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
subjectAltName=DNS: replace.me

openssl のCA機能であれば、SubjectAltNameをcopy_extensionでまるごとコピーが可能であるが、openssl x509 req のときはコピー不可だった。明示する必要があった。