How to Add Self-Signed SSL Certificate to cURL’s Trusted CAs on Windows


5 views

When working with self-signed certificates in development environments, cURL's strict SSL verification often becomes an obstacle. Unlike browsers which allow temporary certificate exceptions, cURL requires proper certificate chain configuration.

First ensure your self-signed certificate is properly generated and installed in the Windows certificate store. The key steps:

# Example OpenSSL command to generate cert
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

Modern cURL installations on Windows typically look for certificates in these locations:

  1. The Windows certificate store
  2. A specified CA bundle file (cacert.pem)

To add your certificate to an existing bundle:

# Concatenate your cert with the existing bundle
type cert.pem >> cacert.pem

# Verify the certificate was added
openssl x509 -in cacert.pem -text -noout

For PHP applications using cURL, update php.ini with:

curl.cainfo = "C:\\path\\to\\modified\\cacert.pem"

Or alternatively at runtime:

$ch = curl_init();
curl_setopt($ch, CURLOPT_CAINFO, 'C:\\path\\to\\modified\\cacert.pem');
curl_setopt($ch, CURLOPT_CAPATH, 'C:\\path\\to\\modified\\');

Create a test script to verify the configuration:

<?php
$ch = curl_init('https://your-dev-server.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$response = curl_exec($ch);

if(curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo 'Connection successful!';
}
curl_close($ch);
?>

For temporary development purposes, you might consider:

# Disable verification (NOT recommended for production)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

# Or specify just your certificate
curl_setopt($ch, CURLOPT_SSLCERT, 'C:\\path\\to\\cert.pem');
curl_setopt($ch, CURLOPT_SSLKEY, 'C:\\path\\to\\key.pem');

When working with self-signed certificates in local development environments, cURL will reject them by default because they aren't issued by a trusted Certificate Authority (CA). This is particularly common when testing HTTPS endpoints before deploying to production.

First, you'll need to create or obtain your self-signed certificate. The certificate should be in PEM format. If you generated it using OpenSSL, it likely already is. Here's an example of generating one:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

Modern cURL installations on Windows use the cacert.pem file from Mozilla as the trust store. To add your certificate:

  1. Download the latest CA bundle from curl.se
  2. Open the file in a text editor
  3. Append your certificate contents at the end of the file
  4. Save the modified bundle

In your php.ini, point to your modified CA bundle:

curl.cainfo = "C:\\path\\to\\modified_cacert.pem"

For testing purposes only, you can temporarily disable certificate verification in PHP/cURL:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://yoursite.test");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);

Create a test script to verify your certificate is trusted:

$ch = curl_init('https://yoursite.test');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if(curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo 'Success! Certificate is trusted.';
}
curl_close($ch);
  • Ensure the certificate chain is complete if using intermediate certificates
  • Verify file permissions on the CA bundle
  • Check that the certificate hasn't expired
  • Confirm the certificate's Subject Alternative Names (SANs) match your domain