一 概念
公钥和私钥属于非对称加密。参考:对称加密和非对称加密、公钥和私钥、单向认证和双向认证、数字签名、数字证书、根证书_公钥、私钥及数字签名-CSDN博客
使用场景:数字签名、加密通信(api)、数字证书
数字签名,例如微信支付请求中使用商户私钥对签名串进行SHA256 with RSA签名,即为应答签名。若签名正确微信的返回数据头中添加应答签名,用户通过校验应答签名,保证数据来源正确。
加密通信,例如微信敏感信息加密。使用公钥信息加密,使用私钥进行解密。
数字证书,个人认为可以基于数字证书的登录验证。比如客户端使用公钥加密数据或签名,api端作对应处理。客户端仅保留公钥私钥。大概和数字签名原理相同,但应包括有效期等。
二 PEM相关函数
2.1 openssl_get_md_methods(bool $aliases
= false
)
获取可用的摘要算法。
$arr1 = openssl_get_md_methods();
$arr2 = openssl_get_md_methods(true);
var_dump($arr1, $arr2);
测试结果
[0]=>
string(10) "blake2b512"
[1]=>
string(10) "blake2s256"
[2]=>
string(3) "md4"
[3]=>
string(3) "md5"
[4]=>
string(8) "md5-sha1"
[5]=>
string(4) "mdc2"
[6]=>
string(9) "ripemd160"
[7]=>
string(4) "sha1"
[8]=>
string(6) "sha224"
[9]=>
string(6) "sha256"
[10]=>
string(8) "sha3-224"
[11]=>
string(8) "sha3-256"
[12]=>
string(8) "sha3-384"
[13]=>
string(8) "sha3-512"
[14]=>
string(6) "sha384"
[15]=>
string(6) "sha512"
[16]=>
string(10) "sha512-224"
[17]=>
string(10) "sha512-256"
[18]=>
string(8) "shake128"
[19]=>
string(8) "shake256"
[20]=>
string(3) "sm3"
[21]=>
string(9) "whirlpool"
}
array(59) {
[0]=>
string(7) "RSA-MD4"
[1]=>
string(7) "RSA-MD5"
[2]=>
string(8) "RSA-MDC2"
[3]=>
string(13) "RSA-RIPEMD160"
[4]=>
string(8) "RSA-SHA1"
[5]=>
string(10) "RSA-SHA1-2"
[6]=>
string(10) "RSA-SHA224"
[7]=>
string(10) "RSA-SHA256"
[8]=>
string(12) "RSA-SHA3-224"
[9]=>
string(12) "RSA-SHA3-256"
[10]=>
string(12) "RSA-SHA3-384"
[11]=>
string(12) "RSA-SHA3-512"
[12]=>
string(10) "RSA-SHA384"
[13]=>
string(10) "RSA-SHA512"
[14]=>
string(14) "RSA-SHA512/224"
[15]=>
string(14) "RSA-SHA512/256"
[16]=>
string(7) "RSA-SM3"
[17]=>
string(10) "blake2b512"
[18]=>
string(10) "blake2s256"
[19]=>
string(34) "id-rsassa-pkcs1-v1_5-with-sha3-224"
[20]=>
string(34) "id-rsassa-pkcs1-v1_5-with-sha3-256"
[21]=>
string(34) "id-rsassa-pkcs1-v1_5-with-sha3-384"
[22]=>
string(34) "id-rsassa-pkcs1-v1_5-with-sha3-512"
[23]=>
string(3) "md4"
[24]=>
string(20) "md4WithRSAEncryption"
[25]=>
string(3) "md5"
[26]=>
string(8) "md5-sha1"
[27]=>
string(20) "md5WithRSAEncryption"
[28]=>
string(4) "mdc2"
[29]=>
string(11) "mdc2WithRSA"
[30]=>
string(6) "ripemd"
[31]=>
string(9) "ripemd160"
[32]=>
string(16) "ripemd160WithRSA"
[33]=>
string(6) "rmd160"
[34]=>
string(4) "sha1"
[35]=>
string(21) "sha1WithRSAEncryption"
[36]=>
string(6) "sha224"
[37]=>
string(23) "sha224WithRSAEncryption"
[38]=>
string(6) "sha256"
[39]=>
string(23) "sha256WithRSAEncryption"
[40]=>
string(8) "sha3-224"
[41]=>
string(8) "sha3-256"
[42]=>
string(8) "sha3-384"
[43]=>
string(8) "sha3-512"
[44]=>
string(6) "sha384"
[45]=>
string(23) "sha384WithRSAEncryption"
[46]=>
string(6) "sha512"
[47]=>
string(10) "sha512-224"
[48]=>
string(27) "sha512-224WithRSAEncryption"
[49]=>
string(10) "sha512-256"
[50]=>
string(27) "sha512-256WithRSAEncryption"
[51]=>
string(23) "sha512WithRSAEncryption"
[52]=>
string(8) "shake128"
[53]=>
string(8) "shake256"
[54]=>
string(3) "sm3"
[55]=>
string(20) "sm3WithRSAEncryption"
[56]=>
string(8) "ssl3-md5"
[57]=>
string(9) "ssl3-sha1"
[58]=>
string(9) "whirlpool"
}
从结果上看,不带参数返回二维数组,带参数返回一维数组。其次返回可加密的算法貌似是非对称加密,而openssl_get_cipher_methods()返回对称加密。
2.2 openssl_pkey_new(?array $options
= null
)
成一个新的私钥和公钥对。成功时返回 OpenSSLAsymmetricKey 实例,错误则返回 false
。
options 键 |
类型 | 等同于 openssl.conf |
描述 |
---|---|---|---|
digest_alg | string | default_md | 摘要算法或签名哈希算法,通常是 openssl_get_md_methods() 之一。 |
x509_extensions | string | x509_extensions | 选择在创建 x509 证书时应该使用哪些扩展 |
req_extensions | string | req_extensions | 创建 CSR 时,选择使用哪个扩展 |
private_key_bits | int | default_bits | 指定应该使用多少位来生成私钥 |
private_key_type | int | none | 选择在创建 CSR 时应该使用哪些扩展。可选值有 OPENSSL_KEYTYPE_DSA 、 OPENSSL_KEYTYPE_DH 、 OPENSSL_KEYTYPE_RSA 或 OPENSSL_KEYTYPE_EC 。 默认值是 OPENSSL_KEYTYPE_RSA 。 |
encrypt_key | bool | encrypt_key | 是否应该对导出的密钥(带有密码短语)进行加密? |
encrypt_key_cipher | int | none | cipher constants 常量之一。 |
curve_name | string | none | openssl_get_curve_names() 之一。 |
config | string | N/A | 自定义 openssl.conf 文件的路径。 |
2.3 openssl_pkey_get_public(
OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key)
返回 OpenSSLAsymmetricKey 实例,失败返回false。
OpenSSLAsymmetricKey 类型,适用于openssl_pkey_new()返回的对象。
string 类型,适用于file://path/to/file.pem格式的字符串。文件名必须包含一个 PEM 编码的证书或者密钥(也许二者都有).
OpenSSLCertificate 类型,大概适用于一个Pem格式的公钥。
2.4 openssl_pkey_get_details(OpenSSLAsymmetricKey $key
)
该函数返回密钥详情(位长度,密钥,类型)。失败时返回 false
。
返回的数组中包含了如下索引: bits
(位数)、 key
(表示公钥的字符串)和 type
(如下密钥类型之一: OPENSSL_KEYTYPE_RSA
、 OPENSSL_KEYTYPE_DSA
、 OPENSSL_KEYTYPE_DH
、 OPENSSL_KEYTYPE_EC
或者是 -1,代表未知类型)。
2.5 openssl_pkey_get_private(OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key
, ?string $passphrase
= null
)
成功时现在返回 OpenSSLAsymmetricKey 实例,即私钥。失败时返回 false
。
$private_key 与openssl_pkey_get_public()相同。
passphrase 若指定的密钥已被加密,即受密码保护,则必填。
2.6
openssl_pkey_export
将 key
当作 PEM 编码字符串导出并且将之保存到output
(通过引用传递的)中。成功时返回 true
, 或者在失败时返回 false
。
参数:
- $key 密钥,可用类型 OpenSSLAsymmetickey|OpenSSLCertificate|array|string,与
openssl_pkey_get_public()相同。
- &$output 输出内容
- ?$passphrase 为受密码保护密钥必填
- ?$options 可用导出参数,参考openssl_pkey_new()
output输出内容为私钥。
2.7 openssl_pkey_export_to_file
将密钥导出到文件中。成功时返回 true
, 或者在失败时返回 false
。
参数:
- $key 密钥
- $output_filename 输出文件的路径
- ?passphrase 为受密码保护密钥必填
- ?options 可用导出参数,参考openssl_pkey_new()
三 CSR相关函数
3.1 openssl_csr_new
根据 distinguished_names
提供的信息生成新的 CSR(证书签名请求)。成功返回 CSR ,失败时返回 false
。
参数:
- $distinguished_names 在证书中使用的专有名称或主题字段。
- private_key OpenSSLAsymmetricKey类型的私钥
- ?$options 参考openssl_pkey_new()
- ?$extra_attributes 用于为 CSR 指定额外的配置选项。
distinguished_names
和 extra_attributes
都是关联数组它们的键被转换成 OID,并应用到请求的相关部分。
3.2 openssl_csr_sign
用另一个证书签署 CSR(或者本身)并且生成一个证书。成功时返回 OpenSSLCertificate,失败则返回 false
。
参数:
- $csr 由openssl_csr_new()生成的 OpenSSLCertificateSigningRequest格式csr。或者由证书文件获取的字符串。
- $ca_certificate 用于签名用的数据,为空生成的签名为自签名证书。可用类型为:OpenSSLCertificate|string|null。
- $private_key 私钥。可用类型为:OpenSSLAsymmetricKey|OpenSSLCertificate|string|null。
- $days 指定生成的证书在几天内有效的时间长度。
- ?$options 参考openssl_pkey_new()。
- ?$serial 可选的发行证书编号。如果没有指定默认值为0。
3.3 openssl_csr_export
将 CSR 作为字符串导出。成功时返回 true
, 或者在失败时返回 false
。
参数:
- $csr
openssl_csr_new()创建的OpenSSLCertificateSigningRequest对象,或者从证书中获取的字符串
- &$output 在成功时,该字符串将包含 PEM 编码的 CSR。
- &no_text 影响输出的冗余度。如果设为
false
,输出内容将包含附加的人类可读信息。notext
的缺省值为true
。
3.4 openssl_x509_export
以字符串格式导出证书。成功时返回 true
, 或者在失败时返回 false
。
参数与openssl_csr_export()相同。
3.5 openssl_csr_export_to_file
csr保存为output_filename命名的pem格式文件中。成功时返回 true
, 或者在失败时返回 false
。
参数:
- $csr
openssl_csr_new()创建的OpenSSLCertificateSigningRequest对象,或者从证书中获取的字符串
- $output_filename 输出的文件名
- no_text 影响输出的冗余度。如果设为
false
,输出内容将包含附加的人类可读信息。notext
的缺省值为true
。
3.6 openssl_csr_get_subject(OpenSSLCertificateSigningRequest|string $csr
, bool $short_names
= true
)
返回带有主题描述的关联数组, 或者在失败时返回 false
。
主题信息其中包含了通用名称(CN)、机构名称(O)、国家名(C)等字段。
short_names 为false,返回全称,否者返回简短形式名称。
3.7 openssl_x509_parse(OpenSSLCertificate|string $certificate
, bool $short_names
= true
)
解析一个 X509 证书并作为一个数组返回信息。返回的数据的结构是(故意的)还没有文档化,因为它仍然会发生变化。
$certificate 可用类型为OpenSSLCertificate和string,意思为
openssl_csr_sign()返回的对象或者从其生成的证书中获取的字符串。
$short_names 参考
openssl_csr_get_subject()
四 数字签名
私钥加密,公钥验证。主要用于证明请求者身份。
私钥和公钥需均来自openssl_pkey_new(),否则不匹配。
一个公钥匹配一个私钥。
function getkeys() {
$res = openssl_pkey_new();
$public_key = openssl_pkey_get_details($res)['key'];
openssl_pkey_export($res, $private_key); //生成私钥
$arr = [
'private_key' => $private_key,
'public_key' => $public_key,
];
return $arr;
}
function getsign($msg, $private_key) {
//用私钥签名
openssl_sign($msg, $sign, $private_key, \OPENSSL_ALGO_SHA256);
return $sign;
}
function checksign($msg, $sign, $public_key) {
$result = openssl_verify($msg, $sign, $public_key, \OPENSSL_ALGO_SHA256);
return $result;
}
function test1() {
//签名
$keys = getkeys();
$private_key = $keys['private_key'];
$public_key = $keys['public_key'];
$msg = "qweqwe" . time();
$sign = getsign($msg, $private_key);
$checksign = checksign($msg, $sign, $public_key);
var_dump($checksign); //int(1)
}
test1();
五 加密通信
私钥加密公钥解密,反之公钥加密私钥解密。加密解密padding要相同,否则解密失败。
function publicencrypt($msg) {
var_dump($msg);
$keys = getkeys();
$private_key = $keys['private_key'];
$public_key = $keys['public_key'];
//公钥加密
$encrypted = '';
if (!openssl_public_encrypt($msg, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
throw new Exception('encrypt failed');
}
$str = base64_encode($encrypted);
var_dump($str);
$str1 = base64_decode($str);
if (!openssl_private_decrypt($str1, $newsource, $private_key, OPENSSL_PKCS1_OAEP_PADDING)) {
throw new Exception('decrypt failed');
}
$msg = $newsource;
var_dump($msg);
}
function privateencrypt($msg) {
//私钥加密
var_dump($msg);
$keys = getkeys();
$private_key = $keys['private_key'];
$public_key = $keys['public_key'];
//公钥加密
$encrypted = '';
if (!openssl_private_encrypt($msg, $encrypted, $private_key)) {
throw new Exception('encrypt failed');
}
$str = base64_encode($encrypted);
var_dump($str);
$str1 = base64_decode($str);
if (!openssl_public_decrypt($str1, $newsource, $public_key)) {
throw new Exception('decrypt failed');
}
$msg = $newsource;
var_dump($msg);
}
function test2() {
$msg = "123123";
publicencrypt($msg);
privateencrypt($msg);
}
test2();
测试结果
string(6) "123123"
string(344) "Hwc+xSpx5AwweysPWBbEnZy6IBqqawZ2S0jq1WZqUwOIaRynWvzU8z43ehQouoq1TaBi25O2XsRZCP0D063ZnNIq2w6Er6aUbhB5pYVihILbtMNitq4CTae5PPToQ5KJ9BaSeHrLJh413ORczYPnWZ1/RSKlRP3sRm9rngbxl2oinvOuBWd2u0FudNskSyWiProAG/XKyE6ZCPc1XOZqGz4BaBlXpwDy6hUpPKbjwSynRaYIxqEkXQoKaceiJdvtjpkOulbyiU+ycozxOx1y96wpkJf2x/zA9EvIydXt6icfN3TxNiu/y5PUKDch/6G2VUG9Zv3AiY67EL+yiYcYiA=="
string(6) "123123"
string(6) "123123"
string(344) "I5AgUaBCwiOBXbagJ99LIFr1+K7+zZ7tH3Kfk6BNQmZn8YkanTLZx/a603bUmiF9i0dMFTsxXR6blXEYR7a/iNkliKOVA3vW1ZpKgxLGLiiMKJjD36+bnJquUAwSeqVAWfEGGM4JSdE2x1h0AcZmaTri49GiZtOpH46DbsnoVsit6Q/nbP5mhk49nMiq/cxxDU1c8U9LvnC6B9/f1IGNXDhW0qdwlFU0jmObPJ5k/5eoYZx0u/WvPZ324KCBTyaERyaKgwMiK6J0eLdbnGtb1euVbZ5ECBkV6UF+RnVSeplRlcq0MBzBD+5GLbS5TChYSn28bdEUCyYYWUOiiuIVaw=="
string(6) "123123"
六 数字证书
function createcrs() {
//创建证书
$info = [
"countryName" => "CN",
"stateOrProvinceName" => "Hunan",
"localityName" => "Tiantang",
"organizationName" => "test",
"organizationalUnitName" => "test",
"commonName" => "test",
"emailAddress" => "test@11.com",
];
$serial = 1;
$pemkey = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
$password = "qweqwe";
$digest_alg = 'sha256';
if (!in_array($digest_alg, openssl_get_md_methods())) {
throw new Exception('digest_alg error');
}
$csr = openssl_csr_new($info, $pemkey, ['digest_alg' => 'sha256']);
$x509 = openssl_csr_sign($csr, null, $pemkey, $days = 365, array('digest_alg' => 'sha256'), $serial);
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($x509, $certout) and var_dump($certout);
openssl_pkey_export($pemkey, $pkeyout, $password) and var_dump($pkeyout);
$info1 = openssl_csr_get_subject($csr, false);
var_dump($info1);
}
createcrs();
测试结果
string(1029) "-----BEGIN CERTIFICATE REQUEST-----
MIICvjCCAaYCAQAweTELMAkGA1UEBhMCQ04xDjAMBgNVBAgMBUh1bmFuMREwDwYD
VQQHDAhUaWFudGFuZzENMAsGA1UECgwEdGVzdDENMAsGA1UECwwEdGVzdDENMAsG
A1UEAwwEdGVzdDEaMBgGCSqGSIb3DQEJARYLdGVzdEAxMS5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqp03PWSYsmXmLJZd9/eThkuWU26nyKxxB
UQmTsd8lriU9UEsS/nOYMd+j6S2o33ep9E/lCFBnl/7H4+OfzOh0047tVKIJQWnq
8nl21IpGF4GhxYehUIwAeVIpPJOKpYtO7ZRpMJq6lq8tW3LpPBIcGejRT/8L8v9G
xaaTWWX3cSqfPLwAfoS0E6cIk1mi3v4c2vlMgmfP5iaYxVZuObpTw9myc73uuuHF
YLy4ixrveOsxDlxe1DKJgvqrYEiCnKBZ/R8JMXXpkgAAkApI0AepTL8td+vuidiL
o0AnLNEZHZD/6OUHLdq9Ofkq2J3o3crCGP/GyZ11zd2a3VJQeIRnAgMBAAGgADAN
BgkqhkiG9w0BAQsFAAOCAQEAinrYLpYIDDXgLxIsl4x3NdErDiXvSCOBhW5E9UyE
/Cp6Ree27D9Mc2Nizqhtx6TWTGQaM92KSxL8CffA6R5lSUyDux3MTLKJSgNbCxnc
+3Orotw8O7E2iwYx03uNAsuKlelWNE1B/zC+tJAgn8DIpXQ8Ga3Pv0OxZQKGiSwS
7NlNa8uvsbk6IvYUddFqw6eAsEVjBnPHvN6kL5jU3sjnq/lUazhGgfRWCoRJBrdT
ibS3I0Zc2BsaZIXN+2DchIYU0iAWepIIcRy/8+lZY0NQtbaE071UTjKQ1N7gJQ4d
6AxFJ6BdEN8Tp4rEB+xOjxtpQo4i9W3q7esi9e0eNiwmew==
-----END CERTIFICATE REQUEST-----
"
string(1363) "-----BEGIN CERTIFICATE-----
MIIDwDCCAqigAwIBAgIBATANBgkqhkiG9w0BAQsFADB5MQswCQYDVQQGEwJDTjEO
MAwGA1UECAwFSHVuYW4xETAPBgNVBAcMCFRpYW50YW5nMQ0wCwYDVQQKDAR0ZXN0
MQ0wCwYDVQQLDAR0ZXN0MQ0wCwYDVQQDDAR0ZXN0MRowGAYJKoZIhvcNAQkBFgt0
ZXN0QDExLmNvbTAeFw0yNDAyMjEwNzEzMzVaFw0yNTAyMjAwNzEzMzVaMHkxCzAJ
BgNVBAYTAkNOMQ4wDAYDVQQIDAVIdW5hbjERMA8GA1UEBwwIVGlhbnRhbmcxDTAL
BgNVBAoMBHRlc3QxDTALBgNVBAsMBHRlc3QxDTALBgNVBAMMBHRlc3QxGjAYBgkq
hkiG9w0BCQEWC3Rlc3RAMTEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAqqdNz1kmLJl5iyWXff3k4ZLllNup8iscQVEJk7HfJa4lPVBLEv5zmDHf
o+ktqN93qfRP5QhQZ5f+x+Pjn8zodNOO7VSiCUFp6vJ5dtSKRheBocWHoVCMAHlS
KTyTiqWLTu2UaTCaupavLVty6TwSHBno0U//C/L/RsWmk1ll93Eqnzy8AH6EtBOn
CJNZot7+HNr5TIJnz+YmmMVWbjm6U8PZsnO97rrhxWC8uIsa73jrMQ5cXtQyiYL6
q2BIgpygWf0fCTF16ZIAAJAKSNAHqUy/LXfr7onYi6NAJyzRGR2Q/+jlBy3avTn5
Ktid6N3Kwhj/xsmddc3dmt1SUHiEZwIDAQABo1MwUTAdBgNVHQ4EFgQU1NLPzfoG
JULG/DoT0S/ABfYgwowwHwYDVR0jBBgwFoAU1NLPzfoGJULG/DoT0S/ABfYgwoww
DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWYDik2oo4neBBBDG
x6onf3HntohqCkcrxZ1WUgmB5t3dPDxDRKH1/eRiHLwHJsP6Iu8aw9E2yqc3283l
/1+ojpYi0VsyrjOV/kI1pI+LVmtgfUAIbiVa4XG2n/j4kpou8CXVynqzax106TFW
aykfTqTIqRiuPsVQ1UubIxCO67fOLYq3/17SnPVgpX2p+ss/jzhgo22h8yzsdHJm
CIt1BfzdxNwa0E7PxLXJ/PZRDt9bxiyUaMYStwLoui66+N4KOS0QoQgK8ci3IoqO
zaGdtMMoCQZKJYmMniUh3ujin5S63VywVvFVVp48FlFlM7O99MJvzYGmgqZybk5X
RFwbIA==
-----END CERTIFICATE-----
"
string(1854) "-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI9cd7sV9GpokCAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECJeMRkekUuxiBIIEyJtmDYBd5PzM
6ZxMhfV4OAvJKSBGiwXSTUOTcmeh8DH9eoRiSuboxpwn34x0NKznNd+JO9cnTxdv
ClVcTmMiCMM9UBCcNjmjTtB1WPzDkCtnWWCp1vobnozSpWaNElnYV3OiRwIwJ879
6nroPcuXiCatXMOt6gTF3fZyLw7Ef+RN89clEMh51QHNjatAmXuAKLkB+hcDVgvx
VrJvr2Hn9+LBtqddROcK9GCfwYLajytaysxANG1bBhf1dhrDy70nZ8tMvY/lQQj+
PNYIi5aDPjr/JdRc9a5V0pt7Qxgo1GGvneMrdioUAtAbThCKWc26SlapnD/IaPDS
d0ydUqsiz8P0Pm3WpGgk8KItPJHI9yQgq4+AdYpT5DhzWPD2TcDkVv1qYUWrK+jQ
ta/SYP+m3RqkLG+mGoiEsTouEhABbPB43O3IcQkKhnY8PDdm/PWHkph3JR/nLjZR
EvJv58vDVu8fe9fdJatplSlahEo4Ov6J3zaxScp3qFSeqlHKM5CQt+rSZUrCrQPE
OCFymlseKlbRpvIXeJ+rReYF/y7AHlwkS4hGl/5ZPSSuHWCOZQfBRbA1imHBthDG
8awy4Vh3iQdtLEpxwjNMQWtpy6R2fbOw+GVTC58WhHhrng3zuH0mCuuayiH0Ga4z
xoGx28HJlJvOk0tqMTM5Z6CJ0cWG+LSaKXzsezldwulCWH9For7pKEOKk7aZeDa4
s+eHljHZJ4kfLtEy7RKKVAlJ8ZAcbpjAtQIfFeCX9JWB4JAblrUIv1r1MyHjLUJW
GN8NH41I5qAmCMPyr7ENMMRohZ6wg/ToydRD5wjHjBxPus38QsnEFMDSOGVywVKl
sT2NtP03q9ytclbhWwtkhLXvKiOV/UZmHil1yhTaHchPcaM0oo89FvZ2zPv+H3uj
6Q0qZh448+IfczcxvCiBy99tAmV97fZtDAa2gyUqj+fim7lU3lBtBAv/UGSx6ckK
J23qyDQ+SnL6FQ96W0rVtJjLO4RSt62PhJp8ChtwsWg1Fu/YaklPX/jr1ODo2MNs
i1DAbb+l9a0RB9rV9GmdJkGBBpXu539VkWg/jQRqfW9TCDSzKJhtaKSNEuJeWJII
f7zGc+u5lAHJ3U5nz58aCHMr9ma1TP+jx32SGbrzrJMNj3DEq1pY/W2P7jAXWgzt
QArsETCdSaAgsuH4ZHZMJcXmrr1Z10uE60z58WsJJsjSgXsqE4AdClltlkqHWG3H
OxyHEB86iLGTk0PKCChnXHCA3jHJrMXxC0TcCXBadNpzeOI/jAhEU+pCYLC/C7GQ
hw+i4meB5CZ7O7kfAZyib1Q1OUB0S8C/6G9eO58CLxDBLFsoKnzqVJ80GOUKH5yd
VP8zrKq1G6YppGHXnbRrSEqx62AWmO6qMufGWBXPxN+XFog4lPZBw1cJOqZjOOFv
NryCI13c5HobbYfdiB53xUlj2JLyCy+fwuXI64a80zjmaavoP+OlFvN7w92zO87g
lYuWtJtpbi0XQ5/aS5QsZQVoCxYTUUBr2W75NlmLiqeohjS9JOuJQFPX6Ofy2Xej
+XNjoytrlSm6Rk9Vy43uxmOWzU5IuxwIAezCJu86MtiL3Na9MdFJ9QiVXO/YFfaD
h2vzdABGNBVPQ2/ex4eoTA==
-----END ENCRYPTED PRIVATE KEY-----
"
array(7) {
["countryName"]=>
string(2) "CN"
["stateOrProvinceName"]=>
string(5) "Hunan"
["localityName"]=>
string(8) "Tiantang"
["organizationName"]=>
string(4) "test"
["organizationalUnitName"]=>
string(4) "test"
["commonName"]=>
string(4) "test"
["emailAddress"]=>
string(11) "test@11.com"
}
将本地时间调快一年,看证书失效效果。
先生成文件。
openssl_pkey_export_to_file($pemkey, 'priv.key');
openssl_csr_export_to_file($csr, 'csr.pem');
openssl_x509_export_to_file($x509, 'sign.crt');
function getcrsinfo() {
$private_key = file_get_contents("priv.key");
$csr_pem = file_get_contents("csr.pem");
$sign_crt = file_get_contents("sign.crt");
$info = openssl_csr_get_subject($csr_pem, false);
var_dump($info);
$parse = openssl_x509_parse($sign_crt, false);
var_dump($parse);
$validTo_time = $parse['validTo_time_t'];
$time = time();
if ($time > $validTo_time) {
var_dump($validTo_time, $time);
var_dump("证书已过期");
}
$pemkey = openssl_pkey_get_private($private_key);
$detail = openssl_pkey_get_details($pemkey);
$public_key = $detail['key'];
var_dump($public_key);
}
getcrsinfo();
系统时间
# date
Wed Feb 21 16:06:12 GMT 2024
# date -s "2026-01-01 11:11:11"
Thu Jan 1 11:11:11 GMT 2026
测试结果
array(7) {
["countryName"]=>
string(2) "CN"
["stateOrProvinceName"]=>
string(5) "Hunan"
["localityName"]=>
string(8) "Tiantang"
["organizationName"]=>
string(4) "test"
["organizationalUnitName"]=>
string(4) "test"
["commonName"]=>
string(4) "test"
["emailAddress"]=>
string(11) "test@11.com"
}
array(16) {
["name"]=>
string(73) "/C=CN/ST=Hunan/L=Tiantang/O=test/OU=test/CN=test/emailAddress=test@11.com"
["subject"]=>
array(7) {
["countryName"]=>
string(2) "CN"
["stateOrProvinceName"]=>
string(5) "Hunan"
["localityName"]=>
string(8) "Tiantang"
["organizationName"]=>
string(4) "test"
["organizationalUnitName"]=>
string(4) "test"
["commonName"]=>
string(4) "test"
["emailAddress"]=>
string(11) "test@11.com"
}
["hash"]=>
string(8) "ff31cf78"
["issuer"]=>
array(7) {
["countryName"]=>
string(2) "CN"
["stateOrProvinceName"]=>
string(5) "Hunan"
["localityName"]=>
string(8) "Tiantang"
["organizationName"]=>
string(4) "test"
["organizationalUnitName"]=>
string(4) "test"
["commonName"]=>
string(4) "test"
["emailAddress"]=>
string(11) "test@11.com"
}
["version"]=>
int(2)
["serialNumber"]=>
string(1) "1"
["serialNumberHex"]=>
string(2) "01"
["validFrom"]=>
string(13) "240221155536Z"
["validTo"]=>
string(13) "250220155536Z"
["validFrom_time_t"]=>
int(1708530936)
["validTo_time_t"]=>
int(1740066936)
["signatureTypeSN"]=>
string(10) "RSA-SHA256"
["signatureTypeLN"]=>
string(23) "sha256WithRSAEncryption"
["signatureTypeNID"]=>
int(668)
["purposes"]=>
array(9) {
[1]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(10) "SSL client"
}
[2]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(10) "SSL server"
}
[3]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(19) "Netscape SSL server"
}
[4]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(14) "S/MIME signing"
}
[5]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(17) "S/MIME encryption"
}
[6]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(11) "CRL signing"
}
[7]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(11) "Any Purpose"
}
[8]=>
array(3) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
string(11) "OCSP helper"
}
[9]=>
array(3) {
[0]=>
bool(false)
[1]=>
bool(true)
[2]=>
string(18) "Time Stamp signing"
}
}
["extensions"]=>
array(3) {
["subjectKeyIdentifier"]=>
string(59) "C4:B7:B8:66:02:BE:D3:7E:F9:95:A7:AB:CE:28:D5:99:C1:5D:35:DB"
["authorityKeyIdentifier"]=>
string(66) "keyid:C4:B7:B8:66:02:BE:D3:7E:F9:95:A7:AB:CE:28:D5:99:C1:5D:35:DB
"
["basicConstraints"]=>
string(7) "CA:TRUE"
}
}
int(1740066936)
int(1767266028)
string(15) "证书已过期"
string(451) "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvauKkIa0G8VlGmMw5O+I
pHNB1yYs5nlEfEqomONrUZ0ZbqlhZMILtb+flZq8OFYtMJcODDrHM4+aeVMCvbxD
H3l/1pq+2AOugHcbffsjqm6yfqbg5hycN8bEUFqDobM90cDzJURKpIfFqEcObKFO
5ucNmotHmhIpNk5lBXIbPM3VBEuhG2gBIsxMnF1jidzWc0cMOYcvtazWUxJfZQbh
xB/fzdXKVbrATNNp7tAdqCJCa3NIyxbXzTUwrAAGKTMLjnWLgh/lygsPAIsDCSxq
KnPlf29W8Rh/o1yPMQ6FZXpmPuISm6MxduZRLfChmYdMuvRwrvQukMNEMNOzvnjB
hQIDAQAB
-----END PUBLIC KEY-----
"