Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export HTTPS certificate in a format acceptable for PHP SSL context option "cafile"

How do I export certificate in a format that will be acceptable by PHP SSL context option cafile?

My code below uses openssl_x509_export to export a certificate chain of stackoverflow.com to a file. The code is based on How to get SSL certificate info with CURL in PHP?

$context = stream_context_create(["ssl" => ["capture_peer_cert_chain" => true]]);
$h = stream_socket_client(
         "ssl://stackoverflow.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT,
         $context);
$params = stream_context_get_params($h);

$ca = null;

foreach ($params["options"]["ssl"]["peer_certificate_chain"] as $cert)
{
    openssl_x509_export($cert, $output);
    $ca .= $output;
}

file_put_contents("cafile", $ca);

(I'm aware that it's not necessary to export whole chain.)


Then, I try with the following code snippet to connect to the same host using the exported file for verifying the certificate. But the code fails with:

PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:

error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in /path/test.php on line 22

$context = stream_context_create(["ssl" => ["cafile" => "cafile"]]);

file_get_contents("https://stackoverflow.com/", false, $context);

What is wrong with the format of the file?

Interestingly wget is happy with the exported certificate, the following succeeds:

wget --ca-certificate=cafile https://sourceforge.net/

The export is:

-----BEGIN CERTIFICATE-----
MIIHJDCCBgygAwIBAgISA76ZNTywMU3d6zogRjuFkuFnMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDA2MDgxNjI0MDBaFw0y
MDA5MDYxNjI0MDBaMB4xHDAaBgNVBAMMEyouc3RhY2tleGNoYW5nZS5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp1azQ2CMWUtXrIZDFim7tu2xF
NFYSLt+lIjyZJ1MeCJkljjaiNB02guKeFRSuPsMk2J3Xz8OmOoEfbvVQejMcaw6i
BVP1V+QhF+JhgyOORQkZQV8JJ58IcOJ1PwokyMCAMOWvdxHzaj73jXsxC+n/+MU7
yuq+Y2LuZE1hQYtftYia/e0QtnPDUlpnjUSd7YEDvAzNnKY3+r1smFOHChDjAxMs
W+lJfKLscNKspncihsx16JhZcGZbXiPPOd90B/zA5xNFOCUolldtMAdxFHKoKYpN
mgWrQwVvDB7VCGAQ3CiNGRvdcMa/TpB4SVsZc07C6TvD35dr0wLoZN4WqKfrAgMB
AAGjggQuMIIEKjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFM73q8X//0OoBswZWBlG
kTPmW5HPMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUF
BwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNy
eXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNy
eXB0Lm9yZy8wggHkBgNVHREEggHbMIIB14IPKi5hc2t1YnVudHUuY29tghIqLmJs
b2dvdmVyZmxvdy5jb22CEioubWF0aG92ZXJmbG93Lm5ldIIYKi5tZXRhLnN0YWNr
ZXhjaGFuZ2UuY29tghgqLm1ldGEuc3RhY2tvdmVyZmxvdy5jb22CESouc2VydmVy
ZmF1bHQuY29tgg0qLnNzdGF0aWMubmV0ghMqLnN0YWNrZXhjaGFuZ2UuY29tghMq
LnN0YWNrb3ZlcmZsb3cuY29tghUqLnN0YWNrb3ZlcmZsb3cuZW1haWyCDyouc3Vw
ZXJ1c2VyLmNvbYINYXNrdWJ1bnR1LmNvbYIQYmxvZ292ZXJmbG93LmNvbYIQbWF0
aG92ZXJmbG93Lm5ldIIUb3BlbmlkLnN0YWNrYXV0aC5jb22CD3NlcnZlcmZhdWx0
LmNvbYILc3N0YXRpYy5uZXSCDXN0YWNrYXBwcy5jb22CDXN0YWNrYXV0aC5jb22C
EXN0YWNrZXhjaGFuZ2UuY29tghJzdGFja292ZXJmbG93LmJsb2eCEXN0YWNrb3Zl
cmZsb3cuY29tghNzdGFja292ZXJmbG93LmVtYWlsghFzdGFja3NuaXBwZXRzLm5l
dIINc3VwZXJ1c2VyLmNvbTBMBgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLf
EwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCC
AQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AF6nc/nfVsDntTZIfdBJ4DJ6kZoMhKES
EoQYdZaBcUVYAAABcpT136gAAAQDAEYwRAIhAP68FqsHN7WAMY3gio0PiAX1o0ID
d9G35wA7pgn/OetjAh9f9JkgTdN4U58fsIVcZAPstOIoKOblbzAof32fixlAAHUA
B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohwAAAFylPXfyQAABAMARjBE
AiArXFv1bOQ2wDYjJvVjSm13AnPCQmbkRRgw6YEaSDhP7gIgJQPAbeBEhu44aJQe
Ih4j33U59OY4Ux2f02dWw3oqhNIwDQYJKoZIhvcNAQELBQADggEBAHyW5+Ss+0vt
jKPFOL9atcI3WZYlwp7Djg3dXByWFBgVEzhrRGGJKEZyK9N178cG9zGXXXbxrxGY
L81pxfZNGiPBYueQ191bTKRS0/9NyCfQhSjFG9SUy7BHDC8OTX5OxEZfnG4wglCf
vPcBkdZ49b0TsTiDrRfCltQvqkeY+/6CfJnayFV/RuZcfRV2bcnu2lLE3da57mA0
TEc9hSW/AefP5ad4noqhSsPISPPbo8S1U4JAFnn1M0KnoEKr5/awHenQeqKgPSKr
DmtDcoy8Tf0RpqSMUwIKqBZEERthO6FC506E64wcuYww3EqA7Um7MM1MkQ8hosFN
WK9ZLI8ylk4=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----

Some background: I'm using certificate bundle from https://curl.se/docs/caextract.html.

For some reason PHP is not able to validate certificates issued by "USERTrust RSA Certification Authority", although the root certificate seems to be present in the bundle. For example a certificate sectigo.com itself. This is a part of my attempt to find the root cause or a workaround.

like image 371
Martin Prikryl Avatar asked Jun 18 '20 10:06

Martin Prikryl


People also ask

What is SSL certificate in PHP?

A Secure Socket Layer (SSL) certificate encrypts the connection between the customer and your web server. The information is rendered unreadable by all third parties (identity thieves and hackers).


Video Answer


1 Answers

stackoverflow only provides the server cert, and the intermediate ca cert. not the root ca cert.

openssl cafile only works if the full chain (to a self signed root ca) can by verified,

so you either have to trust the ROOT CA your self by downloading it, or use some kind of pki so you have all the global trusted root CAs.

on Debian GNU / Linux based machines you can install the ca-certificates package, sudo apt-get install ca-certificates

or you can use the cacert from mozilla https://curl.haxx.se/docs/caextract.html

like image 70
on8tom Avatar answered Oct 08 '22 04:10

on8tom