PHPを使ったサーバ証明書周り処理のメモ
職場で管理しているサーバ証明書の関連手続きを効率化するということで、久々のPHPで管理ツールを作りまして。
なかなか1ヶ所にまとめた情報がなかったので、その時のメモ。
1.秘密鍵文字列の取得
$opt = array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA
);
$pkey = openssl_pkey_new($opt);
openssl_pkey_export($pkey, $private_key); // $private_keyに格納される
2.CSR文字列の取得
1.で取得した秘密鍵のリソース"$pkey"を使います。
$dn = array(
"countryName" => $country,
"stateOrProvinceName" => $state_of_province,
"localityName" => $locality,
"organizationName" => $organizational_name,
"organizationalUnitName => $organizational_unit,
"commonName" => $common_name,
"emailAddress" => ""
);
$csr = openssl_csr_new($dn, $pkey);
openssl_csr_export($csr, $csrout, true); // $csroutに格納される
※上記項目のうち"organizationalUnitName"は入力必須ではありませんが、入力がない時は"organizationalUnitName"の要素自体を省略して関数を呼べばOKです。
3.秘密鍵文字列からCSR作成用のリソースIDを取得
秘密鍵とCSRを別々に作成する場合、いったん作成した秘密鍵文字列からCSR作成用のリソースID $pkeyを作成。
$pkey = openssl_pkey_get_private($priv_key);
if ($pkey !== false) {
(上記2.の処理)
・・・・
4.サーバ証明書と中間証明書との整合性チェック
$hash1 = shell_exec("openssl x509 -issuer_hash -noout -in " . [サーバ証明書ファイルパス]);
$hash2 = shell_exec("openssl x509 -subject_hash -noout -in " . [中間証明書ファイルパス]);
で、hash1 = hash2であればOK。
5.サーバ証明書文字列のパース
$ssl = openssl_x509_parse([サーバ証明書データ]);
上記の$sslには連想配列が返りますが、具体的な内容についてはPHP公式のマニュアルにも明記されていません。
https://www.php.net/manual/ja/function.openssl-x509-parse.php
ちなみに、筆者の今の環境(PHP7.3.7/OpenSSL 1.0.2k)では下記の通りです。
[name] =>
[subject] 主体者情報
[C] => 国
[ST] => 都道府県
[L] => 市区町村
[O} => 組織名
[OU] => 部門名
[CN] => サーバ名:ワイルドカード証明書の時は"*.hoge.com"などとなる
[hash]
[issuer] 発行者情報
[C] => 国
[O] => 組織名
[CN] =>
[version] =>
[serialNumber] => シリアルNo
[serialNumberHex] =>
[validFrom] =>
[validTo] =>
[validFrom_time_t] => 有効期限開始日
[validTo_time_t] => 有効期限終了日
[signatureTypeSN] =>
[signatureTypeLN] =>
[signatureTypeNID] =>
[purpases]
[1]
[0] =>
[1] =>
[2] =>
[2]
[0] =>
[1] =>
[2] =>
[3]
[0] =>
[1] =>
[2] =>
[4]
[0] =>
[1] =>
[2] =>
[5]
[0] =>
[1] =>
[2] =>
[6]
[0] =>
[1] =>
[2] =>
[7]
[0] =>
[1] =>
[2] =>
[8]
[0] =>
[1] =>
[2] =>
[9]
[0] =>
[1] =>
[2] =>
[extensions]
[authorityKeyIdentifier] =>
[subjectKeyIdentifier] =>
[subjectAltName] => オブジェクト代替名:"DNS:..."
[keyUsage] =>
[extendedKeyUsage] =>
[csrDistributionPoints] =>
[certificatePolicies] =>
[authorityInfoAccess] =>
[basicConstraints] =>
[ct_precert_scts] =>
6.PKCS#12証明書内容のパース
$ssl_file_data = file_get_contents([PKCS12証明書ファイル名]);
if (openssl_pkcs12_read($ssl_file_data, $pkcs, $password) !== false) {
$ssl = openssl_x509_parse($pkcs["cert"]);
・・・
(以下、5.と同じ)
関数openssl_pkcs12_readで取得した連想配列$pkcsは、次の構造になっています。
[cert] => サーバ証明書文字列
[pkey] => 秘密鍵文字列
{extracerts]
[0] => 中間証明書文字列?
7.PKCS#7証明書内容のパース
$ssl_file_data = file_get_contents([PKCS7証明書ファイル名]);
if (openssl_pkcs7_read($ssl_file_data, $pkcs) !== false) {
$ssl = openssl_x509_parse($pkcs["0"]);
・・・
(以下、5.と同じ)
上記の$sslには連想配列が返りますが、具体的な内容についてはPHP公式のマニュアルにも明記されていません。
https://www.php.net/manual/ja/function.openssl-pkcs7-read.php
ちなみに、筆者の今の環境(PHP7.3.7/OpenSSL 1.0.2k)では下記の通りです。
[0] :サーバ証明書情報
[1] :中間証明書情報
[2] :ルート証明書情報?(未確認)
8. 証明書チェーンの情報を外部サーバーから取得
指定したコモンネームのサーバー証明書~中間証明書の情報を外部サーバーから取得します。
$stm = stream_context_create(array(
'ssl' => array('capture_peer_cert_chain' => true) // ⇒証明書チェーンを指定
));
$rs1 = stream_socket_client(
'ssl://' . $common_name . ':443',
$err_no,
$err_str, // エラー時はここにエラー内容が返る
30,
STREAM_CLIENT_CONNECT,
$stm
);
//***** サーバー証明書の情報取得 *****
$con = stream_context_get_params($rs1);
$inf = openssl_x509_parse($con["options"]["ssl"]["peer_certificate_chain"]["0"]);
・・・
//***** 中間証明書1の情報取得 *****
if (!empty($con["options"]["ssl"]["peer_certificate_chain"]["1"])) {
$inf = openssl_x509_parse($con["options"]["ssl"]["peer_certificate_chain"]["1"]);
・・・・
}
//***** 中間証明書2の情報取得 *****
if (!empty($con["options"]["ssl"]["peer_certificate_chain"]["2"])) {
$inf = openssl_x509_parse($con["options"]["ssl"]["peer_certificate_chain"]["1"]);
・・・・
}
9.(おまけ)証明書をファイルでダウンロード
header("Content-type: application/octet-stream")
header("Content-length: " . filesize([証明書ファイル名]);
header("Content-Disposition: attachment: filename=" . [ダウンロードファイル名]);
// ファイル出力
readfile([証明書ファイル名]);
unlink([証明書ファイル名]);
?>
最終行の"?>"の後に、改行含め余計な文字を加えると、ダウンロードファイルにゴミが混じるので要注意です。
Author And Source
この問題について(PHPを使ったサーバ証明書周り処理のメモ), 我々は、より多くの情報をここで見つけました https://qiita.com/sefp-maru/items/e0ad0d89d2504a1cc98f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .