Skip to content
ecdsa.com

Public key from a certificate · PHP

How to extract the public key from an X.509 certificate in PHP

To extract the public key from an X.509 certificate in PHP, pass the certificate to openssl_pkey_get_public and read the 'key' entry of openssl_pkey_get_details: it is the SubjectPublicKeyInfo as a "BEGIN PUBLIC KEY" PEM. This recipe also computes the key's SHA-256 fingerprint and base64 pin, and checks a private key with openssl_x509_check_private_key.

Tested with PHP 8.5.11 (ext/openssl, OpenSSL 3.5.7).

extract.php — SPKI PEM, fingerprint, pin and the key-pair check
<?php
$cert = openssl_x509_read(file_get_contents('cert.pem'));
$details = openssl_pkey_get_details(openssl_pkey_get_public($cert));
$spkiPem = $details['key']; // "-----BEGIN PUBLIC KEY-----", SubjectPublicKeyInfo
echo $spkiPem;
// The DER of the SPKI is the base64 inside the PEM
$spkiDer = base64_decode(preg_replace('/-----[^-]+-----|\s/', '', $spkiPem), true);
$digest = hash('sha256', $spkiDer, true);
echo 'SPKI SHA-256: ', implode(':', str_split(bin2hex($digest), 2)), "\n";
echo 'SPKI pin (base64): ', base64_encode($digest), "\n";
// Does key.pem belong to this certificate?
echo 'key.pem matches: ', var_export(openssl_x509_check_private_key($cert, file_get_contents('key.pem')), true), "\n";

How it works

  1. openssl_pkey_get_public($cert) accepts a certificate and returns its public key; openssl_pkey_get_details(...)['key'] is the SPKI PEM.
  2. The DER is the base64 inside the PEM; SHA-256 over it is the key fingerprint (45:ca:a7:e3:…:7b:5f), and its base64 (Rcqn43J0…e18=) the SPKI pin.
  3. openssl_x509_check_private_key($cert, $key) returns true when the private key belongs to the certificate.
  4. The same calls work for RSA and Ed25519 certificates; details['type'] tells the algorithms apart.

Gotchas

  • openssl_x509_fingerprint($cert, 'sha256') hashes the whole certificate (cdb1a140…), not the key; it changes at every renewal, the SPKI hash does not.
  • details['ec']['x'] and ['y'] are the raw 32-byte coordinates, without the SPKI wrapper; hash the DER of details['key'] for fingerprints and pins.

Related recipes