PHPのOpenSSL関数を使ってSSLサーバ証明書を発行する方法

PHPには、OpenSSL関数がモジュールとして用意されています。
このモジュールをインストールすることで、OpenSSL関数が利用可能になり、SSL証明書を発行することができるようになります。


基本的な使い方はPHPのドキュメントページにサンプルが書いてあります。

http://php.benscom.com/manual/ja/function.openssl-csr-new.php

openssl.cnfについて

ただ、このサンプルのとおりプログラムを実行しても、実行環境のopenssl.cnfの設定によっては、SSLサーバ証明書が発行されないことがあります。
自分の環境では、CA証明書が発行されていました。


むしろ、私の開発環境 Fedora8での openssl.cnf のデフォルト位置がどこかすら、最初、わかりませんでした。
# /etc/pki/tls/opnessl.cnf らしい


また、環境に付属しているopenssl.cnfを利用するとシステム独自の定義になっている可能性がありポータビリティが低下します。


ですので、ここでは OpenSSLの本家で配布されているソースの apps/openssl.cnf を利用して説明します。
今回使用したソースのOpenSSLのバージョンは, 0.9.8g です。

http://www.openssl.org/source/openssl-0.9.8g.tar.gz


PHPのOpenSSL関数が、openssl.cnfで利用するのは、[req] と [ v3_ca ] と書かれたセクションです。
この [ v3_ca ] セクション内で、次の項目を変更します。コメントアウトしている方が元の値です。

#basicConstraints = CA:true
basicConstraints = CA:false

#nsCertType = sslCA, emailCA
nsCertType = server

SSL証明書を発行するPHPスクリプト

上記のファイルを使ってSSLサーバ証明書を発行するスクリプトは次のとおりです。

<?php
define("OPENSSL_CNF", "./opnessl.cnf");

$config = array("config"=>OPENSSL_CNF);
$dn = array(
  "countryName" => "JP",
  "stateOrProvinceName" => "XXX",
  "localityName" => "XXX",
  "organizationName" => "XXX",
  "organizationalUnitName" => "XXX",
  "commonName" => "example.com",
  "emailAddress" => "webmaster@example.com");

$privKey = openssl_pkey_new($config);
$csr = openssl_csr_new($dn, $privKey, $config);
$sscert = openssl_csr_sign($csr, null, $privKey, 365, $config);

openssl_x509_export($sscert, $cert_out);
openssl_pkey_export($privKey, $privKey_out);


echo $cert_out;
echo $privKey_out;
?>

openssl_pkey_new() や openssl_csr_new(), openssl_scr_sign() などに $config を渡すことで、参照する openssl.cnf を変更することができます。
$config は 「config」 キーに、opnessl.cnf のパスを指定します。
発行したい証明書の種類を切り替えたい場合は、openssl.cnfを複数用意して、必要に応じて変更するのがいいと思います。


# ソースは動作するソースをみながら手打ちしたので、typoしてるかも



ちなみに、このサンプルでは、openssl_scr_sign() の第二引数を null にしているので発行される証明書は、自己証明になります。