3

C#.NET SSL 接続は、IE (ツール/インターネット オプション/コンテンツ/証明書) で証明書を手動でインポートすると機能しますが、コードで証明書を読み込むにはどうすればよいですか? これが私のコードです:

TcpClient client = new TcpClient(ConfigManager.SSLSwitchIP, Convert.ToInt32(ConfigManager.SSLSwitchPort));

SslStream sslStream = new SslStream(
                client.GetStream(),
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null
                );
sslStream.AuthenticateAsClient("Test");

Internet Explorer で証明書ファイルを手動でインポートすると、上記のコードは正常に機能します。しかし、IE から証明書を削除し、代わりに次のコードを使用すると、認証例外が発生します。

sslStream.AuthenticateAsClient("Test", GetX509CertificateCollection(), SslProtocols.Default, false);

ここに「GetX509CertificateCollection」メソッドがあります:

public static X509CertificateCollection GetX509CertificateCollection()
        {
            X509Certificate2 certificate1 = new X509Certificate2("c:\\ssl.txt");
            X509CertificateCollection collection1 = new X509CertificateCollection();
            collection1.Add(certificate1);
            return collection1;
        }

証明書を動的にロードするにはどうすればよいですか?

4

3 に答える 3

5

owlsteadの回答に基づいて構築するために、検証コールバックで単一のCA証明書とカスタムチェーンを使用して、Microsoftのストアを回避する方法を次に示します.

コールバックが必要ないように、デフォルトでこのチェーン(以下)を使用する方法を理解していません。chain2つまり、ssl ソケットにインストールすると、接続が「正常に機能する」ようになります。そして、コールバックに渡されるようにインストールする方法を理解していません。つまり、コールバックの呼び出しごとにチェーンを構築する必要があります。これらは .Net のアーキテクチャ上の欠陥だと思いますが、明らかな何かが欠けている可能性があります。

関数名は問いません。以下VerifyServerCertificateは、 と同じコールバックRemoteCertificateValidationCallbackです。ServerCertificateValidationCallbackインにも使えますServicePointManager

static bool VerifyServerCertificate(object sender, X509Certificate certificate,
    X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    try
    {
        String CA_FILE = "ca-cert.der";
        X509Certificate2 ca = new X509Certificate2(CA_FILE);

        X509Chain chain2 = new X509Chain();
        chain2.ChainPolicy.ExtraStore.Add(ca);

        // Check all properties
        chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

        // This setup does not have revocation information
        chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

        // Build the chain
        chain2.Build(new X509Certificate2(certificate));

        // Are there any failures from building the chain?
        if (chain2.ChainStatus.Length == 0)
            return true;

        // If there is a status, verify the status is NoError
        bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError;
        Debug.Assert(result == true);

        return result;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }

    return false;
}
于 2014-03-28T00:31:14.243 に答える
3

簡単な Google で、Microsoft のSslStreamクラスのテキストが表示されました。

認証は、セキュリティ サポート プロバイダー (SSPI) チャネル プロバイダーによって処理されます。RemoteCertificateValidationCallbackクライアントには、SslStream の作成時にデリゲートを指定することで、サーバーの証明書の検証を制御する機会が与えられます 。RemoteCertificateValidationCallbackサーバーは、デリゲートを提供することによって検証を制御することもできます 。デリゲートによって参照されるメソッドには、リモート パーティの証明書と、証明書の検証中に SSPI で発生したエラーが含まれます。サーバーがデリゲートを指定する場合、サーバーがクライアント認証を要求したかどうかに関係なく、デリゲートのメソッドが呼び出されることに注意してください。サーバーがクライアント認証を要求しなかった場合、サーバーのデリゲート メソッドは null 証明書と証明書エラーの空の配列を受け取ります。

したがって、デリゲートを実装して、自分で検証を行うだけです。

于 2012-10-08T19:29:30.533 に答える
2

SSLStreamオブジェクトを介してクライアントとして認証を試みる前に、信頼されたルート証明機関(root)に証明書を追加する別の方法を作成しました。

public static void InstallCertificate()
    {
        X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadWrite);
        string fileName = "sslcert.pem";
        X509Certificate2 certificate1;
        try
        {
            certificate1 = new X509Certificate2(fileName);
        }
        catch (Exception ex)
        {
            throw new Exception("Error loading SSL certificate file." + Environment.NewLine + fileName);
        }

        store.Add(certificate1);
        store.Close();
    }

その後:

InstallCertificate();
sslStream.AuthenticateAsClient("Test");

警告やエラーなしで正常に動作します。しかし、基本的な質問はまだ解決されていません。

証明書を使用して、Windowsにインストールせずにクライアントとして認証するにはどうすればよいですか?

于 2012-10-01T06:38:31.183 に答える