php自动签发,生成双向验证证书
效果:



代码:
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('memory_limit', '-1');
date_default_timezone_set('Asia/Shanghai');
set_time_limit(0);
session_start();
//需要手动去签证书,ca根证书的common name不能和client,server的common name相同
//openssl verify ca.crt
//openssl verify -CAfile ca.crt server.crt
//openssl verify -CAfile ca.crt client.crt
$domain = !empty($_GET['domain']) ? $_GET['domain'] : 'xuxiaobo.com';
$days = 365 * 100;
$strparams = false;
$subjsc = " -subj \"/C=Cn/ST=Beijing/L=Beijing/CN={$domain}\"";
$subjca = " -subj \"/C=Cn/ST=Beijing/L=Beijing/CN=com\"";
if(PHP_OS == 'WINNT'){
$openssl = "D:/software/OpenSSL-Win64/bin/openssl.exe";
$cnf = "D:/software/nginx-1.21.6/conf/ssl/openssl.cnf";
} else {
$openssl = "/usr/bin/openssl";
$cnf = "";
}
//1.1. 生成一个 CA 私钥: ca.key
$input = "{$openssl} genrsa -out ca.key 4096";
runCmd($input);
//1.2. 生成一个 CA 数字证书请求
$input = "{$openssl} req -new -key ca.key -out ca.csr";
$params = $strparams ? $subjca : ['CN', 'Beijing', 'Beijing', 'TDZX', 'YFB', 'com', '', '', ''];
runCmd($input, $params, $cnf);
//1.3. 生成一个 CA 的数字证书: ca.crt(Common Name 随意填写;其它可以填”.”)
//-CAcreateserial 表示创建CA证书序列号
$input = "{$openssl} x509 -req -in ca.csr -signkey ca.key -out ca.crt -days {$days}";
runCmd($input);
//1.4. 生成p12格式ca证书
//{$openssl} pkcs12 -export -clcerts -in ca.crt -inkey ca.key -out ca.p12 -passout pass:123456
$input = "{$openssl} pkcs12 -export -in ca.crt -inkey ca.key -out ca.p12 -passout pass:";
runCmd($input);
//2.1. 生成 server 端的私钥: server.key
$input = "{$openssl} genrsa -out server.key 4096";
runCmd($input);
//2.2. 生成 server 端数字证书请求: server.csr(Common Name填写访问服务器时域名,配置nginx时用到,不能与CA的相同 其它填写”.”)
$input = "{$openssl} req -new -key server.key -out server.csr";
$params = $strparams ? $subjsc : ['CN', 'Beijing', 'Beijing', 'TDZX', 'YFB', 'xuxiaobo.com', '', '', ''];
runCmd($input, $params, $cnf);
//2.3. 用 CA 私钥签发 server 的数字证书: server.crt
//-CAcreateserial 表示创建CA证书序列号
//openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
//$input = "{$openssl} x509 -req -in server.csr -signkey server.key -CA ca.crt -CAkey ca.key -out server.crt -CAcreateserial -days {$days}";
$input = "{$openssl} x509 -req -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -CAcreateserial -days {$days}";
runCmd($input);
//2.4. 生成p12格式服务端证书
//{$openssl} pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12 -passout pass:123456
$input = "{$openssl} pkcs12 -export -in server.crt -inkey server.key -out server.p12 -passout pass:";
runCmd($input);
//3.1. 生成客户端的私钥与证书: client.key
$input = "{$openssl} genrsa -out client.key 4096";
runCmd($input);
//3.2. 生成 client 端数字证书请求: client.csr(Common Name填写访问服务器时域名,配置nginx时用到,不能与CA的相同 其它填写”.”)
$input = "{$openssl} req -new -key client.key -out client.csr";
$params = $strparams ? $subjsc : ['CN', 'Beijing', 'Beijing', 'TDZX', 'YFB', 'xuxiaobo.com', '', '', ''];
runCmd($input, $params, $cnf);
//3.3. 用 CA 私钥签发 client 的数字证书: client.crt
//$input = "{$openssl} x509 -req -in client.csr -signkey client.key -CA ca.crt -CAkey ca.key -out client.crt -CAcreateserial -days {$days}";
$input = "{$openssl} x509 -req -in client.csr -CA ca.crt -CAkey ca.key -out client.crt -CAcreateserial -days {$days}";
runCmd($input);
//3.4. 生成p12格式客户端证书
//{$openssl} pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 -passout pass:123456
$input = "{$openssl} pkcs12 -export -in client.crt -inkey client.key -out client.p12 -passout pass:";
runCmd($input);
function runCmd($input, $params = null, $cnf = '')
{
$myinput = !empty($cnf) ? "{$input} -config {$cnf}" : "{$input}";
if(!empty($params)){
if(is_string($params)){
$myinput = !empty($cnf) ? "{$input} {$params} -config {$cnf}" : "{$input} {$params}";
}
}
echo "{$myinput}\n";
if(!empty($params)){
if(is_array($params)){
print_r($params);
echo "\n\n";
}
}
$pipes = [];
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
// $proc为false,表明命令执行失败
$flag = proc_open($myinput, $descriptorspec, $pipes, null, null);
if ($flag == false) {}
else{
if(!empty($params) && is_array($params)){
foreach($params as $param){
fwrite($pipes[0], "{$param}\n");
}
}
$stdin = stream_get_contents($pipes[0]);
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$status = proc_close($flag); // 释放proc
}
$output = [
'stdin' => printrs($stdin),
'stdout' => printrs($stdout),
'stderr' => printrs($stderr),
'retval' => $status,
];
print_r($output);
echo "\n\n";
if($output['retval'] == 0){
return $output;
}
else{
exit;
}
}
/**
* 输出
*/
function printrs($str)
{
return iconv('gbk', 'utf-8//IGNORE', $str);
}
执行过程:
D:/software/OpenSSL-Win64/bin/openssl.exe genrsa -out ca.key 4096
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe req -new -key ca.key -out ca.csr -config D:/software/nginx-1.21.6/conf/ssl/openssl.cnf
Array
(
[0] => CN
[1] => Beijing
[2] => Beijing
[3] => TDZX
[4] => YFB
[5] => com
[6] =>
[7] =>
[8] =>
)
Array
(
[stdin] =>
[stdout] =>
[stderr] => You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:State or Province Name (full name) [Some-State]:Locality Name (eg, city) []:Organization Name (eg, company) [Internet Widgits Pty Ltd]:Organizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:An optional company name []:
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 36500
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe pkcs12 -export -in ca.crt -inkey ca.key -out ca.p12 -passout pass:
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe genrsa -out server.key 4096
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe req -new -key server.key -out server.csr -config D:/software/nginx-1.21.6/conf/ssl/openssl.cnf
Array
(
[0] => CN
[1] => Beijing
[2] => Beijing
[3] => TDZX
[4] => YFB
[5] => xuxiaobo.com
[6] =>
[7] =>
[8] =>
)
Array
(
[stdin] =>
[stdout] =>
[stderr] => You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:State or Province Name (full name) [Some-State]:Locality Name (eg, city) []:Organization Name (eg, company) [Internet Widgits Pty Ltd]:Organizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:An optional company name []:
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe x509 -req -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -CAcreateserial -days 36500
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe pkcs12 -export -in server.crt -inkey server.key -out server.p12 -passout pass:
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe genrsa -out client.key 4096
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe req -new -key client.key -out client.csr -config D:/software/nginx-1.21.6/conf/ssl/openssl.cnf
Array
(
[0] => CN
[1] => Beijing
[2] => Beijing
[3] => TDZX
[4] => YFB
[5] => xuxiaobo.com
[6] =>
[7] =>
[8] =>
)
Array
(
[stdin] =>
[stdout] =>
[stderr] => You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:State or Province Name (full name) [Some-State]:Locality Name (eg, city) []:Organization Name (eg, company) [Internet Widgits Pty Ltd]:Organizational Unit Name (eg, section) []:Common Name (e.g. server FQDN or YOUR name) []:Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:An optional company name []:
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe x509 -req -in client.csr -CA ca.crt -CAkey ca.key -out client.crt -CAcreateserial -days 36500
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
D:/software/OpenSSL-Win64/bin/openssl.exe pkcs12 -export -in client.crt -inkey client.key -out client.p12 -passout pass:
Array
(
[stdin] =>
[stdout] =>
[stderr] =>
[retval] => 0
)
执行后结果:

nginx配置:

本文来自博客园,作者:河北大学-徐小波,转载请注明原文链接:https://www.cnblogs.com/xuxiaobo/p/17045832.html

浙公网安备 33010602011771号