Composer Installer Error: OpenSSL failed with a 'certificate verify failed' error.

# 概要

Composerをインストールしようとすると以下エラーで失敗します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620712/e23e253e-4ed0-83f1-b1c8-1aadc78ad5b8.png)

```
The Composer installer script was not successful [exit code 1].

OpenSSL failed with a 'certificate verify failed' error. This indicates a problem with the Certificate Authority file(s) on your system, which may be out of date.

Certificate location [from openssl.cafile ini setting]:
C:\xampp\apache\bin\curl-ca-bundle.crt

The php.ini used by your command-line PHP is: C:\xampp\php\php.ini

Script Output:
The "https://getcomposer.org/versions" file could not be downloaded: SSL operation failed with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed
Failed to enable crypto
Failed to open stream: operation failed
```

コマンドインストール```php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"```も同様のエラーで失敗します。

```
C:\>php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
PHP Warning:  copy(): SSL operation failed with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed in Command line code on line 1

Warning: copy(): SSL operation failed with code 1. OpenSSL Error messages:
error:0A000086:SSL routines::certificate verify failed in Command line code on line 1
PHP Warning:  copy(): Failed to enable crypto in Command line code on line 1

Warning: copy(): Failed to enable crypto in Command line code on line 1
PHP Warning:  copy(https://getcomposer.org/installer): Failed to open stream: operation failed in Command line code on line 1

Warning: copy(https://getcomposer.org/installer): Failed to open stream: operation failed in Command line code on line 1`
```

# 対処方法

XAMPPをクリーンインストールした状態を前提とします。
php.iniで証明書のパスは以下のように設定されているはずです
(```C:\xampp```は環境依存)

```
curl.cainfo="C:\xampp\apache\bin\curl-ca-bundle.crt"
...
openssl.cafile="C:\xampp\apache\bin\curl-ca-bundle.crt"
```

上記証明書をエディタで開き、以下を最終行に追記します。
これはComposerのWebサイトhttps://getcomposer.org/ の証明書(certadmin)の内容です。

```
certadmin ROOT CA
=================
-----BEGIN CERTIFICATE-----
MIID/DCCAuSgAwIBAgICATgwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT
MQswCQYDVQQIEwJDQTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExFjAUBgNVBAoTDU5l
dHNrb3BlIEluYy4xEjAQBgNVBAsTCWNlcnRhZG1pbjESMBAGA1UEAxMJY2VydGFk
bWluMSUwIwYJKoZIhvcNAQkBFhZjZXJ0YWRtaW5AbmV0c2tvcGUuY29tMB4XDTE5
MTAyNTE4MTg1MFoXDTI5MTAyMjE4MTg1MFowgZcxCzAJBgNVBAYTAlVTMQswCQYD
VQQIEwJDQTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExFjAUBgNVBAoTDU5ldHNrb3Bl
IEluYy4xEjAQBgNVBAsTCWNlcnRhZG1pbjESMBAGA1UEAxMJY2VydGFkbWluMSUw
IwYJKoZIhvcNAQkBFhZjZXJ0YWRtaW5AbmV0c2tvcGUuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuYamgJifcWI3j9zv6OHI0hCQnZHj8uuzZ6sw
nfbediwij9X7MTbQZmswXZt4EgJ58uPN8Opt3+eh+XGP1wbQemUIm9ZkL5WzMVxP
3xW/twL5hBBQOXvn6JX5HS8N53fiDDU8LCuc0xj0Kpdl3TiDDpebtJe6UPiwebyz
jtOwD3ddpiIlArvRzUU1Hi9RIey2clf//3NChyvteQ3TIhciwxbViOxPHxXTRI7w
znFlwuDxvx7X5wwDkI2vzV2jpn23uIROjpCYC7kLvGInEKrgVAzoKauaC+tJmiJY
91m2KGN6xGc94JMRawH6Q+wv/7cBsOGVOUVIpxcM1XS5UqngTwIDAQABo1AwTjAM
BgNVHRMEBTADAQH/MB0GA1UdDgQWBBSvIpNrMIV6Lcujo5SCGWw3AGl7VDAfBgNV
HSMEGDAWgBSvIpNrMIV6Lcujo5SCGWw3AGl7VDANBgkqhkiG9w0BAQsFAAOCAQEA
pKVWEFpG7/d0kAhre2eYLwYEf6tVVP2to9Cp8RgBFSG/ScmEqt2/TXXcpMjRI5eG
nOUbPJIQJi2TQEiI/BG/g6CJZWJiE3fR3NTCksbLbcbdl7exkKT/tItebf4qXlca
ASSd0hBTygE7QqOPSENnSrj7r9P0gv0Z2Bf5jKdirhr/clz/ev88O3KYuxqwwl31
vyLDT0hd/Dzka2/ZKMXL5uFAtsYqpU4hz5NeGgNntKAkwcfFgsTh/NZaYjyRhvUp
jRBt2Mt8OwtxJ+vPM4mvpwFMzvfzhdJfKX/p6IWOJjDFHHFRqdFaHvW3zzarzFt6
tLom62fi7946+fyBmEPu5w==
-----END CERTIFICATE-----
```

保存後、Composerのインストールウィザードでretryもしくはインストールコマンド```php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"```を実行し、成功することを確認します。

# 環境

- Windows 10
- XAMPP 8.2.4 (PHP 8.2.4)
- Composer 2.5.5

# 試したこと

以下では解消しませんでした

-  http://curl.haxx.se から証明書を取得し、php.iniの```curl.cainfo``` ```openssl.cafile```で指定する
-  composer.pharを利用する
    -  ```php composer.phar create-project .. ```を実行すると結局証明書エラーで失敗する
    -  証明書の無視 ```php composer.phar config --global -- disable-tls true```や証明書の指定 ```php composer.phar config --global cafile "C:\xampp\php\cacert.pem"``` などを試したが意味なかった(無視してるのに証明書エラーでる始末)

最初、Web上の情報から、XAMPPビルトインの証明書ではだめで、http://curl.haxx.se の証明書が必要と思い込んでいましたが解消しません。php.iniの指定の仕方(ダブルクォーテーション有無とか)が悪いのではないか??など証明書を正しく読み込めていない可能性をあれこれ確認していましたが効果がないため、SSLの基本に立ち返り、証明書チェーンの検証ができていないことの切り分けとして、試しにComposerのWebサイトのルート証明書をXAMPPビルトインの証明書に追加したところ解消しました。この辺、数年前なら証明書チェーンの検証エラー対応(中間証明書/クロスルート証明書など)をよくやっていたのでもっと早く切り分けできていた感です。
XAMPPビルトインの証明書とhttp://curl.haxx.se の証明書を比較したところ、どちらもmozilla製```Certificate data from Mozilla```で、http://curl.haxx.se の方が最新のものに更新されているという程度でした。で、http://curl.haxx.se の証明書を使ってもComposerのWebサイトで利用されている証明書は検証できないことが分かったので、XAMPPビルトインの証明書使えば良いと思います。なので、対処手順では、XAMPPインストール後php.iniに指定されているXAMPPビルトインの証明書にComposerのWebサイトのルート証明書(certadmin)を追加する手順としました。

# 補足

ComposerのWebサイトで利用されているcertadminの証明書の有効期限は2029年でした。証明書が変更されなければ2029年まで上記対応で良いですが、それ以前でも証明書が変更された場合、ComposerのWebサイトから証明書を再取得して、変更された証明書の内容を追加する必要があります。また、もし今後XAMPPのビルトインの証明書(Mozilla製)にcertadmin.crtが組み込まれれば上記のような対応は不要になると考えられます。

# composer create-project実行時の証明書エラー

```composer create-project```を実行したときの証明書エラーも対応は同じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620712/bb23992f-fcef-3f17-44ba-62c616397913.png)

```
>composer create-project "laravel/laravel=9.*" test-dir --prefer-dist
Creating a "laravel/laravel=9.*" project at "./test_dir"

In CurlDownloader.php line 365:

  curl error 60 while downloading https://repo.packagist.org/packages.json: SSL certificate problem: self-signed c
  ertificate in certificate chain


create-project [-s|--stability STABILITY] [--prefer-source] [--prefer-dist] [--prefer-install PREFER-INSTALL] [--repository REPOSITORY] [--repository-url REPOSITORY-URL] [--add-repository] [--dev] [--no-dev] [--no-custom-installers] [--no-scripts] [--no-progress] [--no-secure-http] [--keep-vcs] [--remove-vcs] [--no-install] [--no-audit] [--audit-format AUDIT-FORMAT] [--ignore-platform-req IGNORE-PLATFORM-REQ] [--ignore-platform-reqs] [--ask] [--] [<package> [<directory> [<version>]]]
```

まずcomposerで利用している証明書を確認します

```
composer diagnose -vvv
...
Checked CA file C:\xampp\php\cacert.pem: valid
...
```

上記証明書をエディタで開き、repo.packagist.org のルート証明書の内容を追加します。確認したところ、https://repo.packagist.org のルート証明書はComposerのWebサイトhttps://getcomposer.org/ と同一でした。そのため、composer diagnose -vvvで確認した証明書をエディタで開き、本記事の対処方法と同じ証明書の内容を追記すれば良いです。