2

私はこれを実装していますが、安全であることを確認したいと考えています。目標は、SSLStream を使用し、特定の RSA キーによって署名されたサーバーからの SSL 証明書のみを受け入れることです。

これが私の接続コードです:

        var client = new TcpClient("server_address", port_number);
        var sslStream = new SslStream(client.GetStream(), false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
        sslStream.AuthenticateAsClient("SpeechGrid");

そして、これがValidateServerCertificateの私の実装です:

    private static bool ValidateServerCertificate(object sender, X509Certificate certificate,
            X509Chain chain, SslPolicyErrors sslPolicyErrors) {

        // Only accept our specific key pair
        foreach (var cert in chain.ChainElements) {
            if (cert.Certificate.GetPublicKeyString() == k_prodPublicKey) {
                return true;
            }
        }

        return false;
    }

X509Chain オブジェクトが豊富であるため、X509ChainStatusFlags.NotSignatureValid などをチェックする必要がないことを確認したいと思います。

たとえば、攻撃者が私の公開鍵で署名されていることを「主張」し、無効な署名を送信することは可能でしょうか?

ありがとう!!

更新: OK、これまでのところ、元の foreach の上に次のチェックを入れることにしました。これは多少アプリケーション固有であることに注意してください。たとえば、証明書を期限切れにしたい場合は、NotTimeValid などをチェックします。

        foreach (var status in chain.ChainStatus) {
            switch (status.Status) {
                case X509ChainStatusFlags.Cyclic:
                case X509ChainStatusFlags.NotSignatureValid:
                case X509ChainStatusFlags.PartialChain:
                    return false;
            }
        }
4

2 に答える 2

1

質問の更新で追加したチェックのロジックを逆にします。何が間違っているのかを探して他のすべてを受け入れる代わりに:

foreach (thing that I can think of that might be wrong)
 return false;

if (public key matches regardless of other policy errors)
 return true;

...代わりに、間違っているが許容できるものを探し、他のポリシーエラーを拒否します。

if (policy errors)
{
 foreach (error that is acceptable: remote name mismatch, untrusted root, etc.)
   policy errors -= that particular error
}

if (any policy errors left)
 return false;
else if (public key matches)
 return true;
else
 return false;

最初の部分ではこのようなもの(私はこれをテストまたはコンパイルしませんでした):

if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
{
    sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
}

if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
{
    var otherFlagsFound =
        from i in chain.ChainStatus
        where (i.Status & ~X509ChainStatusFlags.UntrustedRoot) != X509ChainStatusFlags.NoError
        select i;

    if (otherFlagsFound.Count() == 0)
    {
        sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
    }
}
于 2011-03-09T07:53:09.720 に答える
0

sslPolicyErrors パラメーターで、期限切れなどのその他のエラーがないか、または証明書が信頼されていないかどうかを確認できます。すべて問題なければ、SslPolicyErrors.None が返されます。公開鍵から秘密鍵を導出することは計算上実行不可能であるため、他の誰かが同じ鍵ペアを作成して署名することを心配する必要はありません。

于 2011-03-07T21:33:38.630 に答える