PHP获取SSL证书信息,获取SSL证书序列号,字符串转16进制
<?php
class SslCertService{
public static function certInfo($domain){
$keywordWebsite = 'http://' . str_replace(['https://', 'http://'], '', $domain);
$keywordWebsiteArr = parse_url($keywordWebsite);
$issuerDn = 'Sectigo';
if (empty($keywordWebsiteArr['host'])) {
$cert_info = [];
$cert_info['CN'] = $keywordWebsiteArr['host'];
$cert_info['startTime'] = '';
$cert_info['endTime'] = '';
$cert_info['signature'] = '';
$cert_info['publicKey'] = '';
$cert_info['serialNumber16'] = '';
$cert_info['issuerDn'] = $issuerDn;
return $cert_info;
}
$host = $keywordWebsiteArr['host'];
$cert_info = self::getCertInfo($host);
if (false == $cert_info) {
$cert_info = [];
$cert_info['CN'] = $keywordWebsiteArr['host'];
$cert_info['startTime'] = '';
$cert_info['endTime'] = '';
$cert_info['signature'] = '';
$cert_info['publicKey'] = '';
$cert_info['serialNumber16'] = '';
$cert_info['issuerDn'] = $issuerDn;
return $cert_info;
}
$dn = $cert_info['subject']['CN']; //证书保护域名
$issuerDn = $cert_info['issuer']['CN']; //证书颁发者
$validFrom_time_t = date('Y-m-d H:i:s', $cert_info['validFrom_time_t']); //证书开始时间
$validTo_time_d = date('Y-m-d H:i:s', $cert_info['validTo_time_t']); //证书结束时间
$signatureTypeSN = $cert_info['signatureTypeSN']; //签名算法
$signatureTypeLN = $cert_info['signatureTypeLN']; //公钥
$cert_info['CN'] = Tool::decodeKeyword($dn);
$cert_info['startTime'] = $validFrom_time_t;
$cert_info['endTime'] = $validTo_time_d;
$cert_info['signature'] = $signatureTypeSN;
$cert_info['publicKey'] = strstr($signatureTypeSN, 'RSA') ? 'RSA (2048bits)' : $signatureTypeLN;
$cert_info['issuerDn'] = $issuerDn;
$cert_info['serialNumber16'] = self::strTo16($cert_info['serialNumber']);
$serialNumber16Arr = str_split($cert_info['serialNumber16']);
$cert_info['serialNumber16'] = '';
foreach ($serialNumber16Arr as $index => $value){
if($index !=0 && $index % 2 == 0){
$cert_info['serialNumber16'] .= ':'.$value;
}else{
$cert_info['serialNumber16'] .= $value;
}
}
return $cert_info;
}
public static function getCertInfo($domain){
$domain = str_replace(['https://','http://'], '', $domain);
$domain = Punycode::encode($domain);
$context = stream_context_create(['ssl' => [
'capture_peer_cert' => true,
'capture_peer_cert_chain' => false,
],
]);
$client = @stream_socket_client("ssl://".$domain.":443", $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
if($client==false) {
return false;
}
$params = stream_context_get_params($client);
$cert = $params['options']['ssl']['peer_certificate'];
$cert_info = openssl_x509_parse($cert);
return $cert_info;
}
/**
* 字符串转16进制
* @param $serialNumber
* @return bool|string
*/
public static function strTo16($serialNumber){
$serial = $serialNumber . "";
$base = bcpow("2", "32");
$counter = 100;
$res = "";
$val = $serial;
while($counter > 0 && $val > 0) {
$counter = $counter - 1;
$tmpres = dechex(bcmod($val, $base)) . "";
/* adjust for 0's */
for ($i = 8-strlen($tmpres); $i > 0; $i = $i-1) {
$tmpres = "0$tmpres";
}
$res = $tmpres .$res;
$val = bcdiv($val, $base);
}
if ($counter <= 0) {
return false;
}
return strtoupper($res);
}
}