生成CA私钥及证书:
使用上面的方法可以生成CA证书并使用,但是如果使用上面的方法直接生成的自签名域名证书,即使你把(CA)证书加入到了受信任的根证书列表,也不会受浏览器信任:
NET::ERR_CERT_COMMON_NAME_INVALID
此服务器无法证实它就是 localhost – 它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。
你还需要把域名加入到SAN。
首先生成OpenSSL的配置文件:
PHP
// Domain name place at common name doesn't work on some browsers, you need to put them into SAN
$dnsNames = [
"localhost",
"127.0.0.1",
"::1",
];
$opensslConfigurationFilePath = sprintf("%s/%s.%s.%s.conf", sys_get_temp_dir(), "openssl", mt_rand(1000000, 9999999), time());
// Create openssl.conf file
$oldUmask = umask(0077);
$opensslConfigurationFilePointer = fopen($opensslConfigurationFilePath, "w+");
umask($oldUmask);
// Write basic configurations
fwrite($opensslConfigurationFilePointer, <<
[req]
req_extensions = extension_section
x509_extensions= extension_section
distinguished_name = dn
[dn]
[extension_section]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
EOF
);
// Write SANs
foreach ($dnsNames as $key => $value) {
fwrite($opensslConfigurationFilePointer, sprintf("\nDNS.%d = %s", $key + 1, $value));
}
// Close configuration pointer
fflush($opensslConfigurationFilePointer);
fclose($opensslConfigurationFilePointer);
$configurationArray = [
"digest_alg" => "sha256",
"config" => $opensslConfigurationFilePath, // Use $opensslConfigurationFilePath as configuration file
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Domain name place at common name doesn't work on some browsers, you need to put them into SAN
$dnsNames=[
"localhost",
"127.0.0.1",
"::1",
];
$opensslConfigurationFilePath=sprintf("%s/%s.%s.%s.conf",sys_get_temp_dir(),"openssl",mt_rand(1000000,9999999),time());
// Create openssl.conf file
$oldUmask=umask(0077);
$opensslConfigurationFilePointer=fopen($opensslConfigurationFilePath,"w+");
umask($oldUmask);
// Write basic configurations
fwrite($opensslConfigurationFilePointer,<<
[req]
req_extensions=extension_section
x509_extensions=extension_section
distinguished_name=dn
[dn]
[extension_section]
basicConstraints=CA:FALSE
keyUsage=nonRepudiation,digitalSignature,keyEncipherment
subjectAltName=@alt_names
[alt_names]
EOF
);
// Write SANs
foreach($dnsNamesas$key=>$value){
fwrite($opensslConfigurationFilePointer,sprintf("\nDNS.%d = %s",$key+1,$value));
}
// Close configuration pointer
fflush($opensslConfigurationFilePointer);
fclose($opensslConfigurationFilePointer);
$configurationArray=[
"digest_alg"=>"sha256",
"config"=>$opensslConfigurationFilePath,// Use $opensslConfigurationFilePath as configuration file
];
通过上一步生成的配置文件生成CSR:
PHP
// $dn = [...];
// $privkey = ...;
// Generate a certificate signing request with configurationArray
$csr = openssl_csr_new($dn, $privkey, $configurationArray);
1
2
3
4
5
// $dn = [...];
// $privkey = ...;
// Generate a certificate signing request with configurationArray
$csr=openssl_csr_new($dn,$privkey,$configurationArray);
对CSR进行签名:
PHP
// $CACertFile = ...;
// $CAPrivateKeyFile = ...;
// Generate a cert
$x509 = openssl_csr_sign($csr, $CACertFile, $CAPrivateKeyFile, 3650, $configurationArray);
1
2
3
4
5
// $CACertFile = ...;
// $CAPrivateKeyFile = ...;
// Generate a cert
$x509=openssl_csr_sign($csr,$CACertFile,$CAPrivateKeyFile,3650,$configurationArray);
最后删除配置文件:
PHP
unlink($opensslConfigurationFilePath);
1
unlink($opensslConfigurationFilePath);
References: