public static function calculateThumbprint($certificate, $hash) { if (function_exists('openssl_x509_fingerprint')) { $cert = openssl_x509_read($certificate); return openssl_x509_fingerprint($cert, $hash); } $cert = preg_replace('#-.*-|\\r|\\n#', '', $certificate); $bin = base64_decode($cert); return hash($hash, $bin); }
/** * @param resource $res * * @throws \Exception * * @return array */ public static function loadKeyFromX509Resource($res) { $key = openssl_get_publickey($res); $details = openssl_pkey_get_details($key); if (isset($details['key'])) { $values = self::loadKeyFromPEM($details['key']); if (function_exists('openssl_x509_fingerprint')) { $values['x5t'] = Base64Url::encode(openssl_x509_fingerprint($res, 'sha1', true)); $values['x5t#256'] = Base64Url::encode(openssl_x509_fingerprint($res, 'sha256', true)); } else { openssl_x509_export($res, $pem); $values['x5t'] = Base64Url::encode(self::calculateX509Fingerprint($pem, 'sha1', true)); $values['x5t#256'] = Base64Url::encode(self::calculateX509Fingerprint($pem, 'sha256', true)); } return $values; } throw new \InvalidArgumentException('Unable to load the certificate'); }
/** * createAdminPerson() Create a person-object based on the certificate * credentials passed via the client certificate. * * Ideally, this should be done via Confusa_Auth, however, since we do not have * a live Feide-session, but are basing the authetnication on an X.509 * certificate, the case is a corner, thus we do it here. * * @return Person|NULL the decorated person or NULL if the creation failed. */ function createAdminPerson() { global $log_error_code; /* * Try to find the certificate in the robot_certs-table. If we have a * match, we have a legit user and create a proxy-admin. * * If the query fails for some reason, we jumb out, returning null */ $fingerprint = openssl_x509_fingerprint($_SERVER['SSL_CLIENT_CERT'], true); if (is_null($fingerprint)) { return null; } try { $cert_res = MDB2Wrapper::execute("SELECT * FROM robot_certs WHERE fingerprint = ?", array('text'), array(trim($fingerprint))); } catch (DBStatementException $dbse) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) (line: " . __LINE__ . ")Error with syntax for robot_certs-query.(" . $dbse->getMessage() . ")"); return null; } catch (DBQueryException $dbqe) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Error with params (line (" . __LINE__ . ") in robot_certs-query.(" . $dbqe->getMessage() . ")"); return null; } switch (count($cert_res)) { case 0: Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}): Unauthenticated client connected. Refusing to establish connection. " . $_SERVER['SSL_CLIENT_I_DN']); echo "[{$log_error_code}] You are not authorized to use this API. This incident has been logged.\n"; return null; case 1: /* * We have to do the compare in a rather awkward way to ensure * that differences in spaces, newlines, tabs and whatnot are * removed. */ openssl_x509_export(openssl_x509_read($_SERVER['SSL_CLIENT_CERT']), $stored_admin_dump); openssl_x509_export(openssl_x509_read($cert_res[0]['cert']), $stored_client_dump); if ($stored_admin_dump != $stored_client_dump) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Got matching fingerprint ({$fingerprint}) " . "but actual certificates differ! Aborting"); echo "[{$code}] There were issues with your certificate. Cannot continue using this cert.\n"; echo "Please use another certificate for the time being.\n"; echo "This event has been logged.\n"; return null; } break; default: Logger::log_event(LOG_ALERT, "[RI] ({$log_error_code}) Several certs (" . count($cert_res) . ") in DB matching fingerprint ({$fingerprint}), cannot auth client."); return null; } /* * Get the details for the owner of the certificate, use this as a * basis for authenticating the person. * * It does not really matter which IdP-map we use, as long as we get one * that points to the correct NREN. This is probably not the 'correct' * way of using the idp_map, but atm, this is the only 'correct' way of * decorating the NREN-object. */ try { /* get admin */ $ares = MDB2Wrapper::execute("SELECT * FROM admins WHERE admin_id=?", array('text'), array($cert_res[0]['uploaded_by'])); if (count($ares) != 1) { /* no admin found. This should not be possible, but be * safe and test nevertheless */ return null; } /* get Subscriber */ $sres = MDB2Wrapper::execute("SELECT * FROM subscribers WHERE subscriber_id=?", array('text'), array($cert_res[0]['subscriber_id'])); if (count($sres) != 1) { /* No subscriber found */ return null; } /* get NREN */ $nres = MDB2Wrapper::execute("SELECT n.*,im.idp_url FROM nrens n LEFT JOIN idp_map im ON im.nren_id = n.nren_id WHERE n.nren_id=?", array('text'), array($sres[0]['nren_id'])); if (count($nres) < 1) { /* No nrens found at all, which means that the * subscriber is bogus. Since this is a foreign-key * constraint, we've run into a corrupt db. Let's hope * this'll never happen :-) */ Logger::log_event(LOG_EMERG, "Found subscriber (" . $sres[0]['subscriber_id'] . ":" . $sres[0]['name'] . ") without a corresponding NREN (" . $sres[0]['nren_id'] . "), you have a corrupt database"); } } catch (DBStatementException $dbse) { $msg = "[{$log_error_code}] Problem executing query. Is the database-schema outdated?. "; Logger::log_event(LOG_INFO, $msg . " Server said: " . $dbse->getMessage()); echo $msg . "<br />\nServer said: " . htmlentities($dbse->getMessage()) . "<br />\n"; return null; } catch (DBQueryException $dbqe) { /* FIXME */ $msg = "Could not find owner-details for certificate, probably issues with supplied data. "; $msg .= "Admin_id: " . htmlentities($cert_res[0]['uploaded_by']); Logger::log_event(LOG_INFO, $msg . " Server said: " . $dbqe->getMessage()); echo $msg . "<br />\nServer said: " . htmlentities($dbqe->getMessage()) . "<br />\n"; return null; } /* * Decorate person. */ $person = new Person(); if (isset($ares[0]['admin_name']) && $ares[0]['admin_name'] != "") { $person->setName($ares[0]['admin_name']); } else { $person->setName($ares[0]['admin']); } try { $person->setEPPN($ares[0]['admin']); } catch (CGE_CriticalAttributeException $cae) { echo "[{$log_error_code}] Problems with setting the unique identifier for robot-admin.<br />\n"; echo "Check the data in admins (admin_id: " . htmlentities($cert_res[0]['uploaded_by']) . ")<br />\n"; Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Internal error? Suddenly provided admin-uid is not available."); return null; } $person->setAuth(true); $person->setNREN(new NREN($nres[0]['idp_url'])); $person->setSubscriber(new Subscriber($sres[0]['name'], $person->getNREN())); $person->setName($ares[0]['admin_name']); $person->setEmail($ares[0]['admin_email']); /* Robot authenticated, we can return the person and live happily ever * after */ Logger::log_event(LOG_NOTICE, "[RI]: Authenticated robot-client via cert {$fingerprint} belonging to " . $person->getEPPN()); return $person; }
function load_cert_from_string($export_text) { $certificate = openssl_x509_read($export_text); if (!$certificate) { return FALSE; } $cert_output = ''; openssl_x509_export($certificate, $cert_output); $sha256 = openssl_x509_fingerprint($certificate, 'sha256'); ssl_store_cert($cert_output, $sha256); }
$cert_meta['sha512'] = openssl_x509_fingerprint($cert_meta['cert'], 'sha512'); $cert_meta['sha1'] = openssl_x509_fingerprint($cert_meta['cert'], 'sha1'); $cert_meta['md5'] = openssl_x509_fingerprint($cert_meta['cert'], 'md5'); $cert_meta['parsed'] = openssl_x509_parse($cert_meta['cert']); $cert_meta['hex_only_content'] = str_replace("\n", "", substr($cert_meta['content'], strlen('-----BEGIN CERTIFICATE-----'), -strlen('-----END CERTIFICATE-----'))); $cert_meta['pub_key'] = openssl_pkey_get_details(openssl_pkey_get_public($cert_meta['cert']))['key']; $cert_meta['pub_key_hex_only_content'] = str_replace("\n", "", substr($cert_meta['pub_key'], strlen('-----BEGIN PUBLIC KEY-----'), -strlen('-----END PUBLIC KEY-----'))); $pub_key_raw_content = base64_decode($cert_meta['pub_key_hex_only_content']); $cert_meta['pub_key_sha256'] = hash('sha256', $pub_key_raw_content); $cert_meta['pub_key_sha512'] = hash('sha512', $pub_key_raw_content); $current = $cert_meta; $chain[] = $current; while ($current['parent']) { $current = ssl_load_cert_sha256($current['parent']); if ($current) { $current['sha512'] = openssl_x509_fingerprint($current['cert'], 'sha512'); $current['hex_only_content'] = str_replace("\n", "", substr($current['content'], strlen('-----BEGIN CERTIFICATE-----'), -strlen('-----END CERTIFICATE-----'))); $current['pub_key'] = openssl_pkey_get_details(openssl_pkey_get_public($current['cert']))['key']; $current['pub_key_hex_only_content'] = str_replace("\n", "", substr($current['pub_key'], strlen('-----BEGIN PUBLIC KEY-----'), -strlen('-----END PUBLIC KEY-----'))); $pub_key_raw_content = base64_decode($current['pub_key_hex_only_content']); $current['pub_key_sha256'] = hash('sha256', $pub_key_raw_content); $current['pub_key_sha512'] = hash('sha512', $pub_key_raw_content); $chain[] = $current; } } } // echo "<pre>" . print_r(, 1) . "</pre>"; $errors = ob_get_clean(); if ($tlsa) { $usages_list = array('CA constraint', 'Service certificate constraint', 'Trust anchor assertion', 'Domain-issued certificate'); $selector_list = array('Full certificate', 'SubjectPublicKeyInfo');
<?php $cert = "file://" . dirname(__FILE__) . "/cert.crt"; echo "** Testing with no parameters **\n"; var_dump(openssl_x509_fingerprint()); echo "** Testing default functionality **\n"; var_dump(openssl_x509_fingerprint($cert)); echo "** Testing hash method md5 **\n"; var_dump(openssl_x509_fingerprint($cert, 'md5')); echo "**Testing raw output md5 **\n"; var_dump(bin2hex(openssl_x509_fingerprint($cert, 'md5', true))); echo "** Testing bad certification **\n"; var_dump(openssl_x509_fingerprint('123')); echo "** Testing bad hash method **\n"; var_dump(openssl_x509_fingerprint($cert, 'xx45'));
/** * */ public function getKeyFingerprint() { return openssl_x509_fingerprint($this->publicKey); }
/** * @param string $algorithm * * @return Hash */ public function getFingerprint(string $algorithm = 'SHA1') : Hash { $value = openssl_x509_fingerprint($this->getHandle(), $algorithm, TRUE); if (!$value) { throw new RuntimeException(OpenSSL::getLastError()); } $hash = new Hash($algorithm); $hash->setValue($value); return $hash; }