";
echo "";
echo "Certificate Data | ";
echo "
";
$today = date("Y-m-d");
echo "\n";
echo "\n";
echo "\n";
echo "Hostname | \n";
echo "Not Expired | \n";
echo "Issuer | \n";
echo "CRL | \n";
echo "OCSP | \n";
echo "Signing Type | \n";
echo " \n\n\n";
// hostname validation
if ($data["hostname_in_san_or_cn"] == "true") {
echo ' | ';
} elseif ($data["hostname_in_san_or_cn"] == "false") {
echo ' | ';
} elseif ($data["hostname_in_san_or_cn"] == "n/a; ca signing certificate") {
echo " | ";
} else {
echo " | ";
}
// expired
if ( $today > date(DATE_RFC2822,$data['cert_data']['validFrom_time_t']) || strtotime($today) < strtotime(date(DATE_RFC2822,$data['cert_data']['validTo_time_t'])) ) {
echo ' | ';
} else {
echo ' | ';
}
// issuer
if (!empty($data["issuer_valid"])) {
if ($data["issuer_valid"] == true) {
echo ' | ';
} else {
echo ' | ';
}
} else {
echo ' | ';
}
// crl
if ( !empty($data['crl'][1]['status']) ) {
if ($data['crl'][1]['status'] == "ok") {
echo " | ";
} else {
echo ' | ';
}
} else {
echo ' | ';
}
// ocsp
if (!empty($data['ocsp'][1]['ocsp_uri'])) {
echo "";
if ($data['ocsp'][1]["status"] == "good") {
echo ' ';
} else if ($data['ocsp'][1]["status"] == "revoked") {
echo ' ';
} else {
echo ' ';
}
echo " | ";
} else {
echo " | ";
}
// self signed/ca/ca root
if (strpos($data['cert_data']['extensions']['basicConstraints'], "CA:TRUE") !== false && $data['cert_data']['issuer']['CN'] == $data['cert_data']['subject']['CN'] ) {
echo 'CA Root Certificate | ';
} else if (strpos($data['cert_data']['extensions']['basicConstraints'], "CA:TRUE") !== false) {
echo 'CA Certificate | ';
} else if ($data['cert_data']['issuer']['CN'] == $data['cert_data']['subject']['CN']) {
echo 'Self Signed | ';
} else {
echo "Signed by CA | ";
}
echo " ";
echo " ";
echo " |
";
if (!empty($data['cert_data']['subject']) ) {
foreach ($data['cert_data']['subject'] as $key => $value) {
echo "";
switch ($key) {
case 'C':
echo "Country";
break;
case 'ST':
echo "State";
break;
case 'L':
echo "City";
break;
case 'O':
echo "Organization";
break;
case 'OU':
echo "Organizational Unit";
break;
case 'CN':
echo "Common Name";
break;
case 'mail':
echo "Email Address";
break;
case 'businessCategory':
echo "Business Type";
break;
default:
echo htmlspecialchars($key);
break;
}
echo " | ";
switch ($key) {
case 'C':
echo htmlspecialchars($value);
echo ' ';
break;
case 'DC':
foreach ($value as $key => $value) {
echo htmlspecialchars($value) . ".";
}
break;
default:
if (is_array($value)) {
foreach ($value as $key => $value) {
echo htmlspecialchars($value) . " ";
}
} else {
echo htmlspecialchars($value);
}
break;
}
echo " | ";
echo "
";
}
}
// san
if (!empty($data['cert_data']['extensions']['subjectAltName'])) {
echo "";
echo "Subject Alternative Names | ";
echo "";
foreach ( explode("DNS:", $data['cert_data']['extensions']['subjectAltName']) as $altName ) {
if ( !empty(str_replace(',', " ", "$altName"))) {
echo htmlspecialchars(str_replace(',', " ", "$altName"));
echo " ";
}
}
echo " | ";
echo "
";
}
// validation type
echo "";
echo "Type | ";
echo "";
if ($data["validation_type"] == "extended") {
echo 'Extended Validation';
} elseif ($data["validation_type"] == "organization") {
echo "Organization Validation";
} elseif ($data["validation_type"] == "domain") {
echo "Domain Validation";
}
// full subject
echo " | ";
echo "
";
echo "";
echo "Full Subject | ";
echo "";
echo htmlspecialchars($data['cert_data']['name']);
echo " | ";
echo "
";
echo "";
echo "Issuer | ";
echo "
";
if (!empty($data['cert_data']['issuer']) ) {
foreach ($data['cert_data']['issuer'] as $key => $value) {
echo "";
switch ($key) {
case 'C':
echo "Country";
break;
case 'ST':
echo "State";
break;
case 'L':
echo "City";
break;
case 'O':
echo "Organization";
break;
case 'OU':
echo "Organizational Unit";
break;
case 'CN':
echo "Common Name";
break;
case 'mail':
echo "Email Address";
break;
case 'emailAddress':
echo "Email Address";
break;
default:
echo htmlspecialchars($key);
break;
}
echo " | ";
switch ($key) {
case 'C':
echo htmlspecialchars($value);
echo ' ';
break;
case 'DC':
foreach ($value as $key => $value) {
echo htmlspecialchars($value) . ".";
}
break;
default:
if (is_array($value)) {
foreach ($value as $key => $value) {
echo htmlspecialchars($value) . " ";
}
} else {
echo htmlspecialchars($value);
}
break;
}
echo " | ";
echo "
";
}
}
// valid from
echo "";
echo "Validity | ";
echo "
";
if ( !empty($data['cert_data']['validFrom_time_t']) ) {
echo "";
echo "Valid From | ";
echo "";
if ( $today < date(DATE_RFC2822,$data['cert_data']['validFrom_time_t']) ) {
echo '';
echo ' - ';
} else {
echo '';
echo ' - ';
}
echo htmlspecialchars(date(DATE_RFC2822,$data['cert_data']['validFrom_time_t']));
echo "";
echo " | ";
echo "
";
}
// issued to expired
if ( !empty($data['cert_data']['validTo_time_t']) ) {
echo "";
echo "Valid Until | ";
echo "";
if ( strtotime($today) < strtotime(date(DATE_RFC2822,$data['cert_data']['validTo_time_t'])) ) {
echo '';
echo ' - ';
} else {
echo '';
echo ' - ';
}
echo htmlspecialchars(date(DATE_RFC2822,$data['cert_data']['validTo_time_t']));
echo "";
echo " | ";
echo "
";
};
if ( is_array($data['crl']) ) {
echo "";
echo "CRL | ";
echo "";
foreach ($data['crl'] as $key => $value) {
if ($value) {
if ($value["status"] == "ok") {
echo "";
echo " - Not on CRL: " . htmlspecialchars($value["crl_uri"]) . " ";
echo "Last update: " . htmlspecialchars($value['crl_last_update']) . " \n";
echo "Next update: " . htmlspecialchars($value['crl_next_update']) . " \n";
} elseif ($value["status"] == "revoked") {
echo "";
echo " - Revoked on CRL: " . htmlspecialchars($value["crl_uri"]) . " \n";
echo "Revocation date: " . htmlspecialchars($value["revoked_on"]) . " \n";
echo " Last update: " . htmlspecialchars($value['crl_last_update']) . " \n";
echo "Next update: " . htmlspecialchars($value['crl_next_update']) . " \n";
} else {
echo "";
echo " - CRL invalid: (" . htmlspecialchars($value["crl_uri"]) . ") ";
echo " " . htmlspecialchars($value["error"]) . " ";
}
}
if (count($data['ocsp']) > 1) {
echo " ";
}
}
echo " | ";
echo "
";
} else {
echo "CRL | No CRL URI found in certificate |
";
}
// ocsp
if ( is_array($data['ocsp'])) {
echo "";
echo "OCSP | ";
echo "";
foreach ($data['ocsp'] as $key => $value) {
if ($value) {
if ($value["status"] == "good") {
echo ' ';
echo ' - OK: ';
echo htmlspecialchars($value['ocsp_uri']);
echo " ";
echo "Last update: " . htmlspecialchars($value["this_update"]) . " \n";
echo "Next update: " . htmlspecialchars($value["next_update"]) . " \n";
} else if ( $value["status"] == "revoked") {
echo '';
echo ' - REVOKED: ';
echo htmlspecialchars($value['ocsp_uri']);
echo " ";
echo "Revocation Time: " . htmlspecialchars($value["revocation_time"]) . " \n";
echo "Revocation Reason: " . htmlspecialchars($value["reason"]). " ";
echo " Last update: " . htmlspecialchars($value["this_update"]) . " \n";
echo "Next update: " . htmlspecialchars($value["next_update"]) . " \n";
} else {
echo '';
echo ' - UNKNOWN: ';
echo " - " . htmlspecialchars($value['ocsp_uri']) . " ";
echo "" . htmlspecialchars($value["error"]) . " ";
}
}
if (count($data['ocsp']) > 1) {
echo " ";
}
}
} else {
if ($data["ocsp"] == "No issuer cert provided. Unable to send OCSP request.") {
echo " |
OCSP | No issuer certificate provided. Unable to send OCSP request. |
";
} else {
echo "OCSP | No OCSP URI found in certificate |
";
}
}
echo "";
echo "Hostname Validation | ";
echo "";
// hostname validation
if ($data["hostname_in_san_or_cn"] == "true") {
echo "\n - ";
echo htmlspecialchars($data['hostname_checked']);
echo " found in CN or SAN.";
} elseif ($data["hostname_in_san_or_cn"] == "false") {
echo ' - ';
echo htmlspecialchars($data['hostname_checked']);
echo ' NOT found in CN or SAN.';
} elseif ($data["hostname_in_san_or_cn"] == "n/a; ca signing certificate") {
echo "Not applicable, this seems to be a CA signing certificate.";
} else {
echo "Not applicable, this seems to be a CA signing certificate.";
}
echo " | ";
echo "
";
// details
echo "";
echo "Details | ";
echo "
";
if ( !empty($data['cert_data']['purposes']) ) {
echo "";
echo "Purposes | ";
echo "";
foreach ($data['cert_data']['purposes'] as $key => $purpose) {
if ($purpose["general"]) {
echo htmlspecialchars($key);
echo " ";
}
}
echo " | ";
echo "
";
echo "";
echo "Purposes CA | ";
echo "";
foreach ($data['cert_data']['purposes'] as $key => $purpose) {
if ($purpose["ca"]) {
echo htmlspecialchars($key);
echo " ";
}
}
echo " | ";
echo "
";
}
// serial number
if (!empty($data['serialNumber']) ) {
echo "";
echo "Serial | ";
echo "";
echo htmlspecialchars($data['serialNumber']);
echo " | ";
echo "
";
}
echo "";
echo "Key Size / Type | ";
echo "";
// key details
echo htmlspecialchars($data["key"]['bits']);
echo " bits ";
echo htmlspecialchars($data["key"]['type']);
echo " | ";
echo "
";
echo "";
echo "Signature Algorithm | ";
echo "";
echo $data["key"]["signature_algorithm"];
echo " | ";
echo "
";
if (count($data['cert_data']['extensions']) >= 1) {
echo "";
echo "Extensions | ";
echo "";
?>
$extension) {
if ( !empty(str_replace(',', " ", "$extension"))) {
echo " " . htmlspecialchars("$name") . "";
echo " ";
echo htmlspecialchars($extension);
echo " ";
}
}
echo " ";
echo " ";
echo " ";
echo " ";
echo " | ";
echo "
";
} else {
echo "";
echo "Extensions | ";
echo "";
echo "None";
echo " | ";
echo "
";
}
if(!empty($data["key"]["certificate_pem"])) {
echo "";
echo "Certificate PEM | ";
echo "";
?>
";
echo htmlspecialchars($data["key"]["certificate_pem"]);
echo "";
echo " ";
echo " ";
echo " ";
echo " ";
echo " | ";
echo "
";
}
if(!empty($data['key']['public_key_pem'])) {
echo "";
echo "Public Key PEM | ";
echo "";
?>
";
echo htmlspecialchars($data['key']['public_key_pem']);
echo "";
echo " ";
echo " ";
echo " ";
echo " ";
echo " | ";
echo "
";
echo "";
echo "SPKI Hash | ";
echo "";
print(htmlspecialchars($data['key']['spki_hash']));
echo " | ";
echo "
";
}
echo "";
echo "
";
}
function csr_parse_json($csr) {
$result = array();
if (strpos($csr, "BEGIN CERTIFICATE REQUEST") !== false) {
$cert_data = openssl_csr_get_public_key($csr);
$cert_details = openssl_pkey_get_details($cert_data);
$cert_key = $cert_details['key'];
$cert_subject = openssl_csr_get_subject($csr);
$result["subject"] = $cert_subject;
$result["key"] = $cert_key;
$result["details"] = $cert_details;
} elseif (strpos($csr, "BEGIN CERTIFICATE") !== false) {
$result = cert_parse_json($csr);
} else {
$result = array("error" => "data not valid csr");
}
return $result;
}
function cert_parse_json($raw_cert_data, $raw_next_cert_data=null, $host=null, $validate_hostname=false) {
global $random_blurp;
global $ev_oids;
$result = array();
$cert_data = openssl_x509_parse($raw_cert_data);
if (isset($raw_next_cert_data)) {
$next_cert_data = openssl_x509_parse($raw_next_cert_data);
}
$today = date("Y-m-d");
//cert
if (isset($cert_data) ) {
// purposes
$purposes = array();
foreach ($cert_data['purposes'] as $key => $purpose) {
$purposes[$purpose[2]]["ca"] = $purpose[1];
$purposes[$purpose[2]]["general"] = $purpose[0];
}
unset($cert_data['purposes']);
$cert_data['purposes'] = $purposes;
$result["cert_data"] = $cert_data;
}
// valid from
if ( !empty($result['cert_data']['validFrom_time_t']) ) {
if ( $today < date(DATE_RFC2822,$result['cert_data']['validFrom_time_t']) ) {
$result['cert_issued_in_future'] = false;
} else {
$result['cert_issued_in_future'] = true;
$result['warning'][] = "Certificate issue date is in the future: " . date(DATE_RFC2822,$data['cert_data']['validFrom_time_t']);
}
}
// expired
if (!empty($cert_data['validTo_time_t'])) {
if ($today > date(DATE_RFC2822,$cert_data['validFrom_time_t']) || strtotime($today) < strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t']))) {
$result['cert_expired'] = false;
} else {
$result['cert_expired'] = true;
$result['warning'][] = "Certificate expired! Expiration date: " . date(DATE_RFC2822,$cert_data['validTo_time_t']);
}
}
// almost expired
if (!empty($cert_data['validTo_time_t'])) {
$certExpiryDate = strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t']));
$certExpiryDiff = $certExpiryDate - strtotime($today);
if ($certExpiryDiff < 2592000) {
$result['cert_expires_in_less_than_thirty_days'] = true;
$result['warning'][] = "Certificate expires in " . round($certExpiryDiff / 84600) . " days!. Expiration date: " . date(DATE_RFC2822,$certExpiryDate);
} else {
$result['cert_expires_in_less_than_thirty_days'] = false;
}
}
if ( array_search(explode("Policy: ", explode("\n", $cert_data['extensions']['certificatePolicies'])[0])[1], $ev_oids) ) {
$result["validation_type"] = "extended";
} else if ( isset($cert_data['subject']['O'] ) ) {
$result["validation_type"] = "organization";
} else if ( isset($cert_data['subject']['CN'] ) ) {
$result["validation_type"] = "domain";
}
// issuer
if ($raw_next_cert_data) {
if (verify_cert_issuer_by_subject_hash($raw_cert_data, $raw_next_cert_data) ) {
$result["issuer_valid"] = true;
} else {
$result["issuer_valid"] = false;
$result['warning'][] = "Provided certificate issuer does not match issuer in certificate. Sent chain order wrong.";
}
}
// crl
if (isset($cert_data['extensions']['crlDistributionPoints']) ) {
$result["crl"] = crl_verify_json($raw_cert_data);
if (is_array($result["crl"])) {
foreach ($result["crl"] as $key => $value) {
if ($value["status"] == "revoked") {
$result['warning'][] = "Certificate revoked on CRL: " . $value['crl_uri'] . ". Revocation time: " . $value['revoked_on'] . ".";
}
}
}
} else {
$result["crl"] = "No CRL URI found in certificate";
}
// ocsp
if (isset($cert_data['extensions']['authorityInfoAccess'])) {
$ocsp_uris = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess']);
unset($ocsp_uris[0]);
if (isset($ocsp_uris) ) {
if (isset($raw_next_cert_data)) {
foreach ($ocsp_uris as $key => $ocsp_uri) {
$ocsp_uri = explode("\n", $ocsp_uri)[0];
$ocsp_uri = explode(" ", $ocsp_uri)[0];
$result["ocsp"]["$key"] = ocsp_verify_json($raw_cert_data, $raw_next_cert_data, $ocsp_uri);
if ($result['ocsp'][$key]["status"] == "revoked") {
$result['warning'][] = "Certificate revoked on OCSP: " . $result['ocsp'][$key]['ocsp_uri'] . ". Revocation time: " . $result['ocsp'][$key]['revocation_time'] . ".";
} elseif ($result['ocsp'][$key]["status"] == "unknown") {
$result['warning'][] = "OCSP error on: " . $result['ocsp'][$key]['ocsp_uri'] . ".";
}
}
} else {
$result["ocsp"] = "No issuer cert provided. Unable to send OCSP request.";
}
} else {
$result["ocsp"] = "No OCSP URI found in certificate";
}
} else {
$result["ocsp"] = "No OCSP URI found in certificate";
}
// hostname validation
if ($validate_hostname == true) {
$result["hostname_checked"] = $host;
if (isset($cert_data['subject']['CN'])) {
if ( verify_certificate_hostname($raw_cert_data, $host) ) {
$result["hostname_in_san_or_cn"] = "true";
} else {
$result["hostname_in_san_or_cn"] = "false";
$result['warning'][] = "Hostname " . $host . " not found in certificate.";
}
}
} else {
$result["hostname_in_san_or_cn"] = "n/a; ca signing certificate";
}
//serial number
if ( isset($cert_data['serialNumber']) ) {
$serial = [];
$sn = str_split(strtoupper(bcdechex($cert_data['serialNumber'])), 2);
$sn_len = count($sn);
foreach ($sn as $key => $s) {
$serial[] = htmlspecialchars($s);
if ( $key != $sn_len - 1) {
$serial[] = ":";
}
}
$result["serialNumber"] = implode("", $serial);
}
// key details
$key_details = openssl_pkey_get_details(openssl_pkey_get_public($raw_cert_data));
$export_pem = "";
openssl_x509_export($raw_cert_data, $export_pem);
if (isset($key_details['rsa'])) {
$result["key"]["type"] = "rsa";
$result["key"]["bits"] = $key_details['bits'];
if ($key_details['bits'] < 2048) {
$result['warning'][] = $key_details['bits'] . " bit RSA key is not safe. Upgrade to at least 4096 bits.";
}
} else if (isset($key_details['dsa'])) {
$result["key"]["type"] = "dsa";
$result["key"]["bits"] = $key_details['bits'];
} else if (isset($key_details['dh'])) {
$result["key"]["type"] = "dh";
$result["key"]["bits"] = $key_details['bits'];
} else if (isset($key_details['ec'])) {
$result["key"]["type"] = "ecdsa";
$result["key"]["bits"] = $key_details['bits'];
} else {
$result["key"]["type"] = "unknown";
$result["key"]["bits"] = $key_details['bits'];
}
// signature algorithm
$result["key"]["signature_algorithm"] = cert_signature_algorithm($raw_cert_data);
if ($result["key"]["signature_algorithm"] == "sha1WithRSAEncryption") {
$result['warning'][] = "SHA-1 certificate. Upgrade (re-issue) to SHA-256 or better.";
}
if(isset($export_pem)) {
$result["key"]["certificate_pem"] = $export_pem;
}
if(isset($key_details['key'])) {
$result["key"]["public_key_pem"] = $key_details['key'];
$result["key"]["spki_hash"] = spki_hash($export_pem);
}
return $result;
}
?>