cURL が Windows 上で証明書を適切に検証できないのはなぜですか?

cURL が Windows 上で証明書を適切に検証できないのはなぜですか?

Windows で Curl を使用して URL を取得しようとするとhttps、恐ろしい「接続エラー (60)」が発生します。

ここに画像の説明を入力してください

正確なエラーメッセージは次のとおりです。

curl: (60) SSL 証明書の問題です。CA 証明書が正常であることを確認してください。詳細:
エラー:14090086:SSL ルーチン:SSL3_GET_SERVER_CERTIFICATE:証明書の検証に失敗しました。
詳細はこちら:http://curl.haxx.se/docs/sslcerts.html

これを解決するにはどうすればよいですか?

答え1

理由はわかりませんが、この情報をすべて 1 か所で見つけることができませんでした。

  1. SSL 対応バージョンの Curl をダウンロードするか、SSL 対応バージョンを自分でビルドします。

  2. からcaextract は、C++ のネイティブ API です。cacert.pem ファイルをダウンロードします。

  3. curl.exe と .pem ファイルを同じディレクトリに配置します。

  4. ファイル名cacert.pemcurl-ca-bundle.crt

  5. curl.exe を再実行してください。


編集:

問題を解決する方法は他にもあります。この特定の方法は、Curl のメーカーが作成した cacert に依存しています。これは、必要な方法ではないかもしれません。特に、SSL サイトで使用される証明書の認証機関があまり知られていない (たとえば、あなたの会社だけが知っている機関) 場合は機能しない可能性があります。その場合は、独自のcurl-ca-bundle.crtファイルを生成する必要があります。certreq.exe と openssl.exe を使用して、このような証明書を IE/Windows ストアからエクスポートし、それぞれ pem 形式に変換できます。

答え2

Windows 証明書ストア (CurrentUser または LocalMachine) にインストールされている CA 証明書に基づいてファイルを書き込むことができる PowerShell スクリプトを作成しましたca-cert.crt。次のようにスクリプトを実行します。

CreateCaCert.ps1 -StoreLocation CurrentUser | Out-File -Encoding utf8 curl-ca-cert.crt

curl-ca-cert.crtこれにより、 と同じディレクトリに保存されるファイルが作成されcurl.exe、Windows アプリケーションで実行できるのと同じサイトを検証できるようになります (このファイルは によっても使用されることに注意してくださいgit)。

「公式」スクリプトは以下にありますGitHubただし、参考までに初期バージョンをここに記載します。

[CmdletBinding()]
Param(
    [ValidateSet(
        [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser,
        [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)]
    [string]
    $StoreLocation = [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
)

$maxLineLength = 77

# Open the store
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store ([System.Security.Cryptography.X509Certificates.StoreName]::Root, $StoreLocation)
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly);

# Write header
Write-Output "# Root certificates ($StoreLocation) generated at $(Get-Date)"

# Write all certificates
Foreach ($certificate in $store.Certificates)
{
    # Start with an empty line
    Write-Output ""

    # Convert the certificate to a BASE64 encoded string
    $certString = [Convert]::ToBase64String($certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert));

    # Write the actual certificate
    Write-Output "# Friendly name: $($certificate.FriendlyName)"
    Write-Output "# Issuer:        $($certificate.Issuer)"
    Write-Output "# Expiration:    $($certificate.GetExpirationDateString())"
    Write-Output "# Serial:        $($certificate.SerialNumber)"
    Write-Output "# Thumbprint:    $($certificate.Thumbprint)"
    Write-Output "-----BEGIN CERTIFICATE-----"
    For ($i = 0; $i -lt $certString.Length; $i += $maxLineLength)
    {
        Write-Output $certString.Substring($i, [Math]::Min($maxLineLength, $certString.Length - $i))
    }
    Write-Output "-----END CERTIFICATE-----"
}

答え3

実はTypheous/Rubyでも同じ問題がありました。解決策はcacert.pemこれをC:\Windows\System32(またはWindowsがある場所)に保存します。その後、グローバル環境変数を設定します。ここで説明したようにここで、「変数名」は でありCURL_CA_BUNDLE、「変数値」はファイルへのパスである必要があります%SystemRoot%\System32\cacert.pem

新しい CMD セッションを開始するときに、Typheous/Libcurl を使用して SSL 接続を認証できるようになりました。私は Windows 8.1 でこれを試して成功しました。

関連情報