Dépannage OpenSSL : Corriger l’erreur unable to get local issuer certificate
Lorsque vous utilisez OpenSSL pour établir des connexions sécurisées (par exemple, lors de requêtes réseau en PHP, avec les commandes openssl
ou curl
, ou lors de connexions SSL/TLS dans des applications Node.js/Python), il est possible que vous rencontriez le message d’erreur 20:unable to get local issuer certificate
. Il s’agit d’un problème connu lié à la validation du certificat par OpenSSL.
Pour des raisons de sécurité, OpenSSL exige de connaître explicitement les autorités de certification (CA) racines de confiance lors de la validation d’une chaîne de certificats. Si ces ancres de confiance ne sont ni trouvées ni définies, OpenSSL ne peut pas valider la légitimité du certificat serveur et retourne cette erreur.
Cet article explique en détail la cause de cette erreur et propose des solutions adaptées à l’environnement ServBay, notamment la configuration du stockage de confiance d’OpenSSL pour PHP, Python, Node.js et la commande curl
.
Message d’erreur 20:unable to get local issuer certificate
Description du problème
Lorsque OpenSSL tente de valider le certificat SSL/TLS d’un serveur distant, il construit une chaîne de certificats depuis le certificat du serveur jusqu’à une CA racine de confiance. Si OpenSSL ne trouve pas localement la CA racine appropriée ou un certificat intermédiaire requis, ou si aucun stockage de confiance (CAFile ou CAPath) n’est configuré, la validation échoue et l’erreur 20:unable to get local issuer certificate
s’affiche.
En d’autres termes, OpenSSL ne sait pas à quelle autorité de certification faire confiance et ne peut donc pas garantir l’identité du serveur cible.
Version d’OpenSSL et chemins des certificats CA dans ServBay
ServBay, environnement de développement web local intégré, est livré avec OpenSSL préinstallé et un ensemble de certificats racine publics standards. La version d’OpenSSL utilisée dépend de la puce de votre appareil :
- ServBay pour Apple Silicon (puces série M) : OpenSSL version 3.2.1.
- ServBay pour processeurs Intel : OpenSSL version 1.1.1u.
Les fichiers de certificats CA (cacert.pem
) et les dossiers de certificats (certs
) associés se trouvent dans le répertoire dédié du logiciel ServBay. Repérez les chemins suivants selon votre version :
# Fichier bundle avec tous les certificats racine de confiance
cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
# Répertoire contenant les certificats individuels (normalement inutilisé, mais parfois requis)
capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
3
4
# Fichier bundle avec tous les certificats racine de confiance
cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
# Répertoire contenant les certificats individuels
capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
3
4
La clé pour résoudre l’erreur unable to get local issuer certificate
consiste à indiquer explicitement à OpenSSL le chemin vers le fichier cafile
ou le dossier capath
afin de lui permettre de trouver les CA de confiance.
Exemples de résolution
Voici comment configurer le stockage de confiance OpenSSL dans différents outils et langages.
Exemple 1 : Tester la connexion avec la commande openssl
Si vous obtenez une erreur en testant une connexion avec la commande openssl s_client
:
openssl s_client -quiet -connect gmail.com:443
Un message d’erreur similaire à celui-ci, contenant verify error:num=20:unable to get local issuer certificate
, apparaîtra alors :
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C=US, O=Google Trust Services, CN=WR2
verify return:1
depth=0 CN=gmail.com
verify return:1
# ... autres informations de connexion ...
2
3
4
5
6
7
8
Solution :
Ajoutez le paramètre -CAfile
en indiquant le chemin du fichier CA fourni par ServBay :
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/3.2/cacert.pem
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
Lorsque la connexion et la validation du certificat sont réussies, la valeur verify return
dans la sortie sera 1
et la ligne verify error:num=20
n’apparaîtra plus :
depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1
verify return:1
depth=1 C=US, O=Google Trust Services, CN=WR2
verify return:1
depth=0 CN=gmail.com
verify return:1
# ... autres informations de connexion ...
2
3
4
5
6
7
Exemple 2 : Utilisation d’OpenSSL dans PHP
De nombreuses fonctions de réseau de PHP (par exemple file_get_contents
sur une URL HTTPS, stream_socket_client
pour les connexions SSL, l’extension cURL, etc.) reposent sur OpenSSL. Vous pouvez définir le stockage de confiance CA via le fichier php.ini
ou dans le code avec les options de contexte de flux.
Méthode A : Modifier le fichier php.ini
(recommandé)
C’est la méthode globale la plus simple. Éditez le fichier php.ini
associé à la version de PHP en cours (l’interface de ServBay facilite cela), et dans la section [openssl]
, ajoutez ou modifiez les lignes suivantes :
[openssl]
; Fichier bundle CA de confiance
openssl.cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
; Répertoire des certificats CA (optionnel mais recommandé)
openssl.capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
3
4
5
[openssl]
; Fichier bundle CA de confiance
openssl.cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
; Répertoire des certificats CA (optionnel mais recommandé)
openssl.capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
3
4
5
Après avoir modifié le php.ini
, redémarrez le service PHP dans ServBay (ou l’ensemble de ServBay) pour appliquer la configuration.
Méthode B : Configurer dans le code (limité à la connexion courante)
Si vous ne souhaitez pas modifier la configuration globale, vous pouvez spécifier le fichier CA via l’option ssl
lors de la création du contexte avec stream_context_create
:
<?php
// Exemple : connexion à un serveur SMTP via SSL/TLS
$server = 'ssl0.ovh.net';
$port = 465;
// Chemin du CA ServBay selon la version :
// Apple Silicon :
$caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
// Intel :
// $caCertFile = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem';
$contextOptions = [
'ssl' => [
'verify_peer' => true, // Activer la vérification du certificat du pair
'verify_peer_name' => true, // Vérifier que le nom du certificat correspond à l’hôte
'allow_self_signed' => false, // Refuser les certificats auto-signés sauf confiance explicite
'cafile' => $caCertFile, // Fichier bundle CA
// 'capath' => '/Applications/ServBay/package/common/openssl/3.2/certs', // Optionnel, dossier CA
],
];
$context = stream_context_create($contextOptions);
// Établir la connexion SSL/TLS avec les options spécifiées
$connection = @stream_socket_client(
"ssl://$server:$port",
$errno,
$errstr,
30, // Timeout de connexion
STREAM_CLIENT_CONNECT,
$context // Passage du contexte
);
if ($connection) {
echo "Connection établie avec $server:$port\n";
// Exemple : envoyer la commande EHLO
fwrite($connection, "EHLO servbay.demo\r\n"); // Utilise un domaine d’exemple lié à ServBay
while (!feof($connection)) {
echo fgets($connection);
}
fclose($connection);
} else {
echo "Échec de la connexion à $server:$port. Erreur : $errstr ($errno)\n";
}
?>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Exemple 3 : Utiliser OpenSSL dans Python (module ssl)
Le module Python ssl
permet également de créer un contexte SSL/TLS et de définir le certificat CA de confiance.
import ssl
import socket
server = 'ssl0.ovh.net'
port = 465
# Indiquez ici le fichier CA approprié selon votre version ServBay
# Pour Apple Silicon :
ca_cert_file = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem'
# Pour Intel :
# ca_cert_file = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem'
# Création du contexte SSL par défaut avec le fichier CA spécifié
context = ssl.create_default_context(cafile=ca_cert_file)
# Il est aussi possible de définir un dossier : context = ssl.create_default_context(capath='/Applications/ServBay/package/common/openssl/3.2/certs')
try:
# Ouverture de la connexion socket classique
with socket.create_connection((server, port)) as sock:
# Encapsulation de la socket dans SSL
with context.wrap_socket(sock, server_hostname=server) as ssock:
print(f"Connexion SSL établie. Protocole négocié : {ssock.version()}")
# Exemple : envoi de la commande EHLO
ssock.sendall(b"EHLO servbay.demo\r\n") # Usage du domaine d’exemple ServBay
while True:
data = ssock.recv(4096)
if not data:
break
print(data.decode())
except Exception as e:
print(f"Échec de la connexion ou erreur SSL : {e}")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Exemple 4 : Utiliser OpenSSL dans Node.js (module tls)
Dans Node.js, le module tls
permet d’instancier des connexions TLS/SSL. Le certificat CA de confiance est spécifié dans l’option ca
, passant le contenu du fichier cacert.pem
délivré par ServBay.
const tls = require('tls');
const fs = require('fs');
const server = 'www.google.com'; // Exemple avec un site web standard et de confiance
const port = 443;
// Chemin du fichier CA en fonction de ServBay
// Apple Silicon :
const caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
// Intel :
// const caCertFile = '/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem';
const options = {
host: server,
port: port,
// Charger le contenu du fichier CA
ca: fs.readFileSync(caCertFile),
// Le module tls de Node.js effectue une vérification du hostname (checkServerIdentity) par défaut :
// Si le CA est bien défini et que le certificat serveur est valide, la vérification passera.
// Ne désactivez pas checkServerIdentity sauf raison absolument nécessaire ET en connaissance des risques.
// checkServerIdentity: () => { return null; } // <-- Extrêmement risqué, n’utilisez pas cette option !
};
const socket = tls.connect(options, () => {
console.log('Connexion SSL établie');
// Pour une requête HTTPS : socket.write('GET / HTTP/1.1\r\nHost: ' + server + '\r\n\r\n');
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('close', () => {
console.log('Connexion fermée');
});
socket.on('error', (error) => {
console.error('Erreur :', error.message); // Affichage du message d’erreur
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Remarque : L’option checkServerIdentity: () => { return null; }
n’apparaît plus dans cet exemple, car elle désactive une vérification essentielle de la sécurité. L’erreur OpenSSL unable to get local issuer certificate
concerne la chaîne de confiance, et non la vérification du nom d’hôte (verify_peer_name
). En indiquant correctement l’option ca
et avec un certificat serveur valide, la vérification par défaut de Node.js ne pose généralement pas problème. Si une erreur liée au nom d’hôte apparaît, il s’agit probablement d’un défaut du certificat serveur, et non d’une configuration CA.
Exemple 5 : Utiliser OpenSSL avec la commande curl
La commande curl
exploite également OpenSSL (ou d’autres bibliothèques SSL) pour les requêtes HTTPS. Indiquez le fichier CA avec l’option --cacert
:
# Utiliser le fichier CA de ServBay pour visiter un site HTTPS
# Choisissez le chemin adapté à votre environnement :
# Apple Silicon :
curl --cacert /Applications/ServBay/package/common/openssl/3.2/cacert.pem https://example.com
# Intel :
# curl --cacert /Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem https://example.com
2
3
4
5
6
7
Si la configuration est correcte et le certificat serveur valide, curl
téléchargera la page sans erreur de validation de certificat.
Résumé
L’erreur 20:unable to get local issuer certificate
est courante lors des connexions SSL/TLS via OpenSSL. Ce problème survient car OpenSSL requiert une référence explicite à un stockage de confiance pour valider les certificats serveur. ServBay fournit à cet effet un fichier cacert.pem
prédéfini rassemblant les principales autorités de certification publiques.
Pour corriger ce problème, il suffit de spécifier dans votre environnement de développement (dans le php.ini
, dans les options de votre contexte SSL, ou via les arguments en ligne de commande comme -CAfile
pour OpenSSL ou --cacert
pour curl) le chemin exact vers le fichier cacert.pem
fourni par ServBay. Veillez à choisir le bon chemin selon le type de puce macOS (Apple Silicon ou Intel) correspondant à la version OpenSSL de votre installation ServBay. Avec une configuration correcte du stockage de confiance CA, votre environnement de développement local pourra communiquer de manière sécurisée et fiable avec les services SSL/TLS externes.