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