Dépannage OpenSSL
Lors de l'utilisation d'OpenSSL (incluant les environnements PHP, la commande openssl
, et la commande curl
), des erreurs telles que 20:unable to get local issuer certificate
peuvent survenir. Il s'agit d'un problème récurrent avec OpenSSL. Pour des raisons de sécurité, OpenSSL ne fait pas confiance à n'importe quelle autorité de certification (CA) par défaut et nécessite la spécification explicite d'un CAFile ou d'un CAPath. Cet article explique comment résoudre ce problème et fournit des exemples de code en PHP, Python et Node.js.
Erreur 20:unable to get local issuer certificate
Description du problème
Si vous obtenez l'erreur 20:unable to get local issuer certificate
lors de l'utilisation d'OpenSSL, c'est parce qu'OpenSSL ne parvient pas à trouver le certificat de l'autorité de certification locale. La solution consiste à spécifier un CAFile ou un CAPath.
Versions d'OpenSSL dans ServBay
Selon le type de puce utilisé par ServBay, la version d'OpenSSL peut varier :
- Version Intel chez ServBay : utilise OpenSSL version 1.1.1u
- Version Apple Silicon chez ServBay : utilise OpenSSL version 3.2.1
Chemins des fichiers correspondants
cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
Exemple : Utilisation de la commande OpenSSL
Si vous rencontrez une erreur en exécutant la commande suivante :
openssl s_client -quiet -connect gmail.com:443
Vous pourriez voir l'erreur suivante :
Connecting to 172.217.163.37
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
2
3
4
5
6
7
8
Solution
Spécifiez le CAFile pour résoudre ce problème :
openssl s_client -quiet -connect gmail.com:443 -CAfile /Applications/ServBay/package/common/openssl/3.2/cacert.pem
Une fois la connexion réussie, la sortie sera la suivante :
Connecting to 172.217.163.37
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
2
3
4
5
6
7
Exemple : Utilisation d'OpenSSL en PHP
Lors de l'utilisation d'OpenSSL en PHP, vous pouvez résoudre ce problème en modifiant le fichier php.ini
ou en ajoutant la configuration correspondante dans votre code.
Modifier le php.ini
Ajoutez ou modifiez le contenu suivant dans la section [openssl]
du fichier php.ini
:
[openssl]
openssl.cafile=/Applications/ServBay/package/common/openssl/3.2/cacert.pem
openssl.capath=/Applications/ServBay/package/common/openssl/3.2/certs
2
3
[openssl]
openssl.cafile=/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
openssl.capath=/Applications/ServBay/package/common/openssl/1.1.1u/certs
2
3
Ajouter la configuration dans le code
Vous pouvez également spécifier le CAFile dans votre code PHP. Par exemple :
<?php
$server = 'ssl0.ovh.net';
$port = 465;
// Chemin du fichier CA
$caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
$contextOptions = [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
'cafile' => $caCertFile,
],
];
$context = stream_context_create($contextOptions);
$connection = @stream_socket_client(
"ssl://$server:$port",
$errno,
$errstr,
30,
STREAM_CLIENT_CONNECT,
$context
);
if ($connection) {
echo "Connexion établie avec $server:$port\n";
fwrite($connection, "EHLO example.com\r\n");
while ($line = fgets($connection)) {
echo $line;
}
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
Exemple : Utilisation d'OpenSSL en Python
Lors de l'utilisation d'OpenSSL en Python, vous pouvez spécifier le CAFile dans votre code. Par exemple :
import ssl
import socket
server = 'ssl0.ovh.net'
port = 465
ca_cert_file = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem'
context = ssl.create_default_context(cafile=ca_cert_file)
with socket.create_connection((server, port)) as sock:
with context.wrap_socket(sock, server_hostname=server) as ssock:
print(f"SSL établi. Peer: {ssock.getpeercert()}")
ssock.sendall(b"EHLO example.com\r\n")
while True:
data = ssock.recv(4096)
if not data:
break
print(data.decode())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Exemple : Utilisation d'OpenSSL en Node.js
Lors de l'utilisation d'OpenSSL en Node.js, vous pouvez spécifier le CAFile dans votre code. Par exemple :
const tls = require('tls');
const fs = require('fs');
const server = 'ssl0.ovh.net';
const port = 465;
const caCertFile = '/Applications/ServBay/package/common/openssl/3.2/cacert.pem';
const options = {
host: server,
port: port,
ca: fs.readFileSync(caCertFile),
checkServerIdentity: () => { return null; } // Ignorer la vérification de l'identité du serveur
};
const socket = tls.connect(options, () => {
console.log('Connexion SSL établie');
socket.write("EHLO example.com\r\n");
});
socket.on('data', (data) => {
console.log(data.toString());
});
socket.on('error', (error) => {
console.error('Erreur:', error);
});
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
Exemple : Utilisation de curl avec OpenSSL
Si vous rencontrez des problèmes avec la commande curl
, vous pouvez les résoudre en spécifiant le CAFile :
curl --cacert /Applications/ServBay/package/common/openssl/3.2/cacert.pem https://example.com
Conclusion
Lors de l'utilisation d'OpenSSL, si vous rencontrez l'erreur 20:unable to get local issuer certificate
, vous pouvez la résoudre en spécifiant un CAFile ou un CAPath. Selon le type de puce de votre appareil, trouvez les chemins correspondant au CAFile et au CAPath, et configurez-les dans vos commandes OpenSSL, ou dans les configurations PHP, Python, Node.js, ou curl.