1. ホーム
  2. c#

[解決済み] .NETのHttpWebRequest/Responseで自己署名証明書を使用する場合

2023-05-20 14:20:38

質問

自己署名SSL証明書を使用するAPIに接続しようとしています。.NETのHttpWebRequestとHttpWebResponseオブジェクトを使用してそうしています。そして、次のような例外が発生しました。

基礎となる接続は閉じられました。SSL/TLSセキュアチャネルの信頼関係を確立できませんでした。

これが何を意味するかは理解しています。そして、私は なぜ .NETは私に警告し、接続を閉じるべきだと感じています。しかし、この場合、私はとにかく API に接続したいだけであり、中間者攻撃など知ったことではありません。

では、この自己署名証明書の例外を追加するには、どうすればよいでしょうか。または、証明書をまったく検証しないように HttpWebRequest/Response に指示するアプローチでしょうか。どのようにすればよいのでしょうか?

どのように解決するのですか?

@Domster: これはうまくいきますが、証明書のハッシュが期待したものと一致するかどうかをチェックすることで、ちょっとしたセキュリティを強化したいと思うかもしれません。そのため、拡張バージョンは次のようになります (私たちが使用しているいくつかのライブ コードに基づいています)。

static readonly byte[] apiCertHash = { 0xZZ, 0xYY, ....};

/// <summary>
/// Somewhere in your application's startup/init sequence...
/// </summary>
void InitPhase()
{
    // Override automatic validation of SSL server certificates.
    ServicePointManager.ServerCertificateValidationCallback =
           ValidateServerCertficate;
}

/// <summary>
/// Validates the SSL server certificate.
/// </summary>
/// <param name="sender">An object that contains state information for this
/// validation.</param>
/// <param name="cert">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the
/// remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote
/// certificate.</param>
/// <returns>Returns a boolean value that determines whether the specified
/// certificate is accepted for authentication; true to accept or false to
/// reject.</returns>
private static bool ValidateServerCertficate(
        object sender,
        X509Certificate cert,
        X509Chain chain,
        SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None)
    {
        // Good certificate.
        return true;
    }

    log.DebugFormat("SSL certificate error: {0}", sslPolicyErrors);

    bool certMatch = false; // Assume failure
    byte[] certHash = cert.GetCertHash();
    if (certHash.Length == apiCertHash.Length)
    {
        certMatch = true; // Now assume success.
        for (int idx = 0; idx < certHash.Length; idx++)
        {
            if (certHash[idx] != apiCertHash[idx])
            {
                certMatch = false; // No match
                break;
            }
        }
    }

    // Return true => allow unauthenticated server,
    //        false => disallow unauthenticated server.
    return certMatch;
}