web-dev-qa-db-ja.com

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

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

enter image description here

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

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

これを解決するには?

30
Cheeso

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

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

  2. http://curl.haxx.se/docs/caextract.html から、cacert.pemファイルをダウンロードします。

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

  4. cacert.pemファイルの名前をcurl-ca-bundle.crtに変更します

  5. Curl.exeを再実行してください!


編集:

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

37
Cheeso

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

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]::AuthRoot, $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-----"
}
6
Ramon de Klein

実際、Typheous/Rubyでも同じ問題がありました。ソリューションは cacert.pem をダウンロードし、それをC:\ Windows\System32(またはWindowsの任意の場所)に保存しました。その後、グローバル環境変数を設定します ここで説明したように ここで、「変数名」はCURL_CA_BUNDLEおよび "変数値"ファイルへのパス%SystemRoot%\System32\cacert.pem

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

2
Martin