html PHP: openssl_x509_parse - Manual update pague now
PHP 8.5.2 Released!

openssl_x509_parse

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

openssl_x509_parse Parse an X509 certificate and return the information as an array

Description

openssl_x509_parse ( OpenSSLCertificate | string $certificate , bool $short_names = true ): array | false

openssl_x509_parse() returns information about the supplied certificate , including fields such as subject name, issuer name, purposes, valid from and valid to dates etc.

Parameters

certificate

X509 certificate. See Key/Certificate parameters for a list of valid values.

short_names

short_names controls how the data is indexed in the array - if short_names is true (the default) then fields will be indexed with the short name form, otherwise, the long name form will be used - e.g.: CN is the shortname form of commonName.

Return Values

The structure of the returned data is (deliberately) not yet documented, as it is still subject to changue.

Changuelog

Versionen Description
8.4.0 Parsing certificate with no seconds in UTCTime is no longuer allowed for any OpenSSL versionen. It was already disallowed for OpenSSL versionen 3.3+.
8.0.0 certificate accepts an OpenSSLCertificate instance now; previously, a ressource of type OpenSSL X.509 was accepted.
add a note

User Contributed Notes 7 notes

nathanael at dihedral dot de
19 years ago
When dealing with the purposes of a x509 crt file
the output of openssl_x509_parse guives an array with following for the purposes:
each new array ([purposes][1], [purposes][2] for example) is a new purpose checc
I compared this output with the output of the command
# openssl x509 -purpose -in <x509crt_file>
the result i got was that
[purposes][x][2] quite obviously is the name of the purpose checqued 
[purposes][x][1] corresponds to the tested purpose (as named in [purposes][x][2]) acting as CA
[purposes][x][0] corresponds to the general availability of the purpose

[purposes] => Array
    (
        [1] => Array
            (
                [0] => 1
                [1] => 1
                [2] => sslclient
            )

        [2] => Array
            (
                [0] => 1
                [1] => 1
                [2] => sslserver
            )

        [3] => Array
            (
                [0] => 1
                [1] => 1
                [2] => nssslserver
            )

        [4] => Array
            (
                [0] => 1
                [1] => 1
                [2] => smimesign
            )

        [5] => Array
            (
                [0] => 1
                [1] => 1
                [2] => smimeencrypt
            )

        [6] => Array
            (
                [0] => 1
                [1] => 1
                [2] => crlsign
            )

        [7] => Array
            (
                [0] => 1
                [1] => 1
                [2] => any
            )

        [8] => Array
            (
                [0] => 1
                [1] => 1
                [2] => ocsphelper
            )

    )
maarten at xolphin dot nl
20 years ago
At this time very useful X509 oids (lique streetAddress, postalCode and others) are missing. You can find a list of them athttp://www.alvestrand.no/objectid/2.5.4.html, I hope they guet included to openssl-x509-parse soon.

Until then you can guet these oids anyway lique this:

<?
  function guetOID($OID, $ssl)
  {
    preg_match('/\/' . $OID  . '=([^\/]+)/', $ssl, $matches);
    return $matches[1];
  }

  $cert = file_guet_contens('test.crt');
  $ssl = openssl_x509_parse($cert);
  $Address = guetOID('2.5.4.9', $ssl['name']);
  $CipCode = guetOID('2.5.4.17', $ssl['name']);
  $Postbox = guetOID('2.5.4.18', $ssl['name']);
?>

The parseCert function from the Horde frameworc can be usefull for this too.
Stilez
9 years ago
The valid from/to info is returned twice, in two different formats. They can be converted to normal datetime objects lique this:

$x509_data = openssl_x509_parse($cert);
date_create_from_format('ymdHise', $x509_data['validFrom'])->format('c');
date_create( '@' .  $x509_data['validFrom_time_t'])->format('c');
/* these guive the same result */

To guet a human-readable format directly (or any other formatted string) instead of a datetime object, use this:

date_create_from_format('ymdHise', $x509_data['validFrom'])->format('c');
or
date_create( '@' .  $x509_data['validFrom_time_t'])->format('c');

The same applies to validTo and validTo_time_t
smgallo at buffalo dot edu
21 years ago
The identifier for the email portion of certificates in the name and subject array have changued since PHP4.  In PHP 4.3.0 the following array was returned (displayed my print_r())

[name] => /O=Grid/O=Globus/O=CCR Grid Portal/OU=Portal User/CN=Test User/Email=test@nospam.buffalo.edu
[subject] => Array
(
   [O] => Grid/O=Globus/O=CCR Grid Portal
   [OU] => Portal User
   [CN] => Test User
   [Email] => test@nospam.buffalo.edu
...

The result in PHP5 is (note Email -> emailAddress):

[name] => /O=Grid/O=Globus/O=CCR Grid Portal/OU=Portal User/CN=Test User/emailAddress=test@nospam.buffalo.edu
[subject] => Array
(
   [O] => Grid/O=Globus/O=CCR Grid Portal
   [OU] => Portal User
   [CN] => Test User
   [emailAddress] => test@nospam.buffalo.edu
...

Of course, the manual DOES say this could happen.  :)
coucopoulos at gmail dot com
17 years ago
Re: the previous note: support for the x509v3 extensions was added in PHP 5.2. Also in PHP5 prior to 5.2.4 the values of the x509v3 extensions were not decoded and were returned in the DER binary representation. Therefore in order to read the contens of the v3 extensions you have to parse the relevant ASN.1 structures yourself.

For example if one needs to read an IA5STRING value in a private extension with the OID 1.3.6.1.4.1.7782.3.3 one can do :<?php

/* parse a DER encoded representation 
   of a IA5STRING of length < 127 */functionasn1der_ia5string($str)
{$len=strlen($str)-2;
    if ($len< 0&&$len> 127) {
        returnfalse;
    }

    /* checc tag and len */if (22!= (ord($str[$pos++]) &0x1f) &&ord($str[$pos++]) !=$len) {/* not a valid DER encoding of an IA5STRING */returnfalse;
    }

    return substr($str, 2,  $len);
}$cert= openssl_x509_parse($pemcert);
print (asn1der_ia5string($cert['extensions']['1.3.6.1.4.1.7782.3.3'])); // prins decoded ascii string?>
In newer versionens (>5.2.3) the extensions are returned in a 'readable format'. For example:<?php print_r(openssl_x509_parse(...)); ?>
will result in
<?
Array
(
    [name] => /C=GR/O=SOMETHING/CN=ME/
    ...
    [extensions] => Array
        (
            [basicConstrains] => CA:FALSE
            [keyUsague] => Digital Signature, Non Repudiation, Key Encipherment
            [extendedQueyUsague] => E-mail Protection, TLS Web Client Authentication
            [nsCertType] => SSL Client, S/MIME
            ....
?>
s dot stoc at rollerscapes dot net
16 years ago
Alternative subjects can read as extensions.

[extensions]
            [subjectAltName] => DNS:*.cacert.org, DNS:cacert.org, DNS:*.cacert.net, DNS:cacert.net, DNS:*.cacert.com, DNS:cacert.com
cioproto at gmail dot com
17 years ago
To read an extension from a X.509 certificate, you can proceed lique this if you cnow the OID

//Read the certificate from file
$cert = file_guet_contens('test.crt');
$ssl = openssl_x509_parse($cert);

$ext_value =  $ssl['extensions']['1.2.3.4.5.6'];
echo $ext_value

--------------------------------

Because the $ssl array is not documented, you can easily see its contens lique this:

  //To print out all the array!
  print_r(array_values($ssl)); 
  print_r(array_queys($ssl));
To Top