質問

通信に TCP/IP ソケットを使用するさまざまなプロセス間で安全な通信を提供する必要があります。認証と暗号化の両方が必要です。車輪を再発明するのではなく、SSL、SslStream クラス、および自己署名証明書を使用したいと考えています。私がやりたいのは、ローカル アプリケーションの既知のコピーに対してリモート プロセスの証明書を検証することです。(証明書を手動でコピーするつもりなので、認証局は必要ありません)。

これを行うには、アプリケーションが初回実行時に新しい証明書を自動的に生成できるようにする必要があります。makecert.exe に加えて、次のようになります このリンク は、自己署名証明書を自動的に生成する方法を示しているので、それが始まりです。

SslStream の AuthenticateAsServer メソッドと AuthenticateAsClient メソッドを調べました。検証用のコールバックを提供できるので、可能のようです。しかし、今、その詳細に取り組んでいると、これは本当に不可能だと思います。

私は正しい方向に進んでいますか?もっと良い代替手段はありますか?これまでにこのようなことをした人はいますか (基本的にクライアント/サーバーではなくピアツーピア SSL)。

役に立ちましたか?

解決

ステップ1: 自己署名証明書の生成:

  • ダウンロードしたのは、 Certificate.cs クラス 投稿者: ダグ・クック
  • このコードを使用して .pfx 証明書ファイルを生成しました。

    byte[] c = Certificate.CreateSelfSignCertificatePfx(
            "CN=yourhostname.com", //host name
            DateTime.Parse("2000-01-01"), //not valid before
            DateTime.Parse("2010-01-01"), //not valid after
            "mypassword"); //password to encrypt key file
    
        using (BinaryWriter binWriter = new BinaryWriter(
            File.Open(@"testcert.pfx", FileMode.Create)))
        {
            binWriter.Write(c);
        }
    

ステップ2: 証明書のロード

    X509Certificate cert = new X509Certificate2(
                            @"testcert.pfx", 
                            "mypassword");

ステップ 3: それを一緒に入れて

  • 私はそれをもとにしました この非常に単純な SslStream の例
  • SslProtocolType 列挙に関するコンパイル時エラーが発生します。それを SslProtocolType.Default から SslProtocols.Default に変更するだけです。
  • 非推奨の関数に関する警告が 3 件ありました。提案された代替品とすべて交換しました。
  • Server Program.cs ファイル内のこの行を、ステップ 2 の行に置き換えました。

    X509証明書証明書 = getServerCert();

  • Client Program.cs ファイルで、serverName = yourhostname.com を設定していることを確認してください (また、それが証明書内の名前と一致していることも確認してください)。

  • Client Program.cs では、sslPolicyErrors に RemoteCertificateChainErrors が含まれているため、CertificateValidationCallback 関数が失敗します。もう少し詳しく見てみると、これは、証明書に署名した発行局が信頼されたルートではないためです。
  • ユーザーにルート ストアなどに証明書をインポートさせることにはしたくないので、このために特別なケースを作成し、certificate.GetPublicKeyString() がファイルにある公開キーと等しいことを確認します。そのサーバーの場合。一致する場合、その関数から True を返します。それはうまくいくようです。

ステップ 4: クライアント認証

私のクライアントの認証方法は次のとおりです (サーバーとは少し異なります)。

TcpClient client = new TcpClient();
client.Connect(hostName, port);

SslStream sslStream = new SslStream(client.GetStream(), false,
    new RemoteCertificateValidationCallback(CertificateValidationCallback),
    new LocalCertificateSelectionCallback(CertificateSelectionCallback));

bool authenticationPassed = true;
try
{
    string serverName = System.Environment.MachineName;

    X509Certificate cert = GetServerCert(SERVER_CERT_FILENAME, SERVER_CERT_PASSWORD);
    X509CertificateCollection certs = new X509CertificateCollection();
    certs.Add(cert);

    sslStream.AuthenticateAsClient(
        serverName,
        certs,
        SslProtocols.Default,
        false); // check cert revokation
}
catch (AuthenticationException)
{
    authenticationPassed = false;
}
if (authenticationPassed)
{
    //do stuff
}

CertificateValidationCallback はサーバーの場合と同じですが、AuthenticateAsClient が 1 つの証明書だけではなく証明書のコレクションを取得する方法に注意してください。したがって、次のように LocalCertificateSelectionCallback を追加する必要があります (この場合、クライアント証明書は 1 つだけなので、コレクション内の最初の証明書を返すだけです)。

static X509Certificate CertificateSelectionCallback(object sender,
    string targetHost,
    X509CertificateCollection localCertificates,
    X509Certificate remoteCertificate,
    string[] acceptableIssuers)
{
    return localCertificates[0];
}

他のヒント

あなたも、この例を見ることができます サンプル非同期SslStreamクライアント/サーバの実装 ます。http:// blogs.msdn.com/joncole/archive/2007/06/13/sample-asynchronous-sslstream-client-server-implementation.aspxする

証明書が正しく生成されない場合は、サーバモードのSSLは、関連する秘密鍵と証明書を使用しなければならない例外を取得することができます。

基本的な証明書の例

makecert -SR LOCALMACHINE -ssマイ-n CN =テスト-sky交換-sk 123456

または

外部ファイルとして

makecert -SR LOCALMACHINE -ssマイ-n CN =テスト-sky為替-sk 123456 C:\ Test.cer

証明書作成ツール(Makecert.exe)
http://msdn.microsoft.com/en-私たち/ライブラリ/ bfsktky3%28VS.80%29.aspxする

それはあなたがコールバックが証明書を生成するために呼び出されるまで待つために探しているように聞こえることを除いて、

あなたが提案しているのは、私には罰金聞こえます。私はそれが飛ぶとは思いません。私の知る限り、あなたはAuthenticateAsXを起動する際に有効な証明書を提供するために、持ってます。

しかし、これらのクラスはオーバーライドされています。その理論的には、あなたが必要であれば、証明書を生成する必要があるかどうかを確認するために最初のチェックは、それを生成し、派生クラスを作成することができ、その後、親AuthenticateAsXメソッドを呼び出します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top