7

HttpWebRequestを使用して、 nginx を実行しているリモート サーバーにクエリを実行しようとしています。接続を完了するには、クライアント証明書を提供する必要があります。

私は次のことをしています:

Dim Request As HttpWebRequest = DirectCast(WebRequest.Create(Url), HttpWebRequest)
Dim Cert = SSL.GetClientCertificate()
Request.ClientCertificates.Clear()
Request.ClientCertificates.Add(Cert)
Dim Response As WebResponse = Request.GetResponse()

(は、ローカル マシンでストアを開き、適切な証明書を (として) 取得するSSL.GetClientCertificate単なるヘルパー メソッドです。正しい証明書が返されています。また、ファイルから証明書を読み込んで同じ結果が得られました。)MyX509Certificate2

現状では、に到達しDim Response As...て実際に接続を開こうとすると、次の本文で 400 Bad Request が返されます。

400 Bad Request
No required SSL certificate was sent
-----------------------------------
nginx/1.0.10

私たちはLocalMachine\TrustedRootCertificationAuthorities自分のマシンに証明書を持つ独自の CA を使用しています。クライアント証明書は有効ですが、CA がOCSPエンドポイントを公開していないため、検証に失敗します。X509Chain を作成し、取り消しをチェックせずにチェーンを検証するように依頼すると、すべてがパスします。

私の質問は... 証明書がリクエストと共に送信されないのはなぜですか? クライアント証明書を送信する前に検証しようとするべきではないと思います(それはサーバーの仕事です)。

Wireshark のログで大騒ぎすることはありませんが、クライアントが証明書を送信していません。要するに、私は...

  • [アウト] クライアントこんにちは
  • [で] サーバーこんにちは
  • [中]証明書
  • [で] サーバーこんにちは完了
  • [アウト] 証明書、クライアント キー交換、暗号仕様の変更、暗号化されたハンドシェイク メッセージ
  • [In] 暗号仕様の変更、暗号化されたハンドシェイク メッセージ
  • [Out] Application Data (おそらくGETリクエスト)
  • [In] アプリケーション データ (おそらく 400)
  • [In] 暗号化アラート (チャネルを終了)

nginxは、証明書の送信に失敗したときに死ぬのではなく、(最初にチャネルの作成に失敗するのではなく)400レスポンスボディの送信を許可するように再ネゴシエートするという賢いことをしていると思います。

いずれにせよ、本当の問題である証明書を送信していません。誰かが理由を知っていますか?

それが役立つ場合、nginx のログは証明書が送信されていないと主張します (証明書が無効であるのとは対照的に):

2012/11/22 14:16:26 [情報] 27755#0: *799 クライアントは、クライアント要求ヘッダーの読み取り中に必要な SSL 証明書を送信しませんでした。クライアント: 10.0.0.200、サーバー: 10.0.0.100、要求: "GET /state HTTP /1.1"、ホスト: "10.0.0.100"

以下のコードは使用しないでください - 非効率的で信頼性が低く、テストのみに使用されました

Re: 証明書の取得:

Public Shared Function GetClientCertificate() As X509Certificate2
    Dim Store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
    Dim Ret As X509Certificate2 = Nothing

    Try
        Store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
        For Each Certificate In Store.Certificates
            If Certificate.SubjectName.Name = "The subjectname of our certificate" Then
                Ret = Certificate
                Exit For
            End If
        Next
    Finally
        Store.Close()
    End Try
    Return Ret
End Function
4

1 に答える 1

4

クライアント(またはサーバー)証明書として使用できるようにするには、アクセス可能な秘密鍵を含む証明書が必要です。

証明書を使用する必要があるユーザーに秘密鍵へのアクセスを許可する限り、証明書をマシンの証明書ストアに保存してもかまいません。.cer には公開鍵しか含まれていないため、.cer を使用してクライアントを認証することはできません。ユーザーのクライアント証明書をインストールし、ブラウザーを使用して URL にアクセスすることで、すべてをテストできます。証明書を選択するためのポップアップが表示された場合、証明書は (そのユーザーに対して) 正しくインストールされています。

于 2012-12-01T11:30:26.447 に答える