Не могу отправить сертификат клиента через SslStream - PullRequest
4 голосов
/ 29 мая 2010

Я делаю рукопожатие SSL3, используя SslStream, но, несмотря на все мои усилия, SslStream никогда не отправляет сертификат клиента от моего имени. Вот код:

SSLConnection = new System.Net.Security.SslStream(SSLInOutStream, false, new System.Net.Security.RemoteCertificateValidationCallback(AlwaysValidRemoteCertificate), new System.Net.Security.LocalCertificateSelectionCallback(ChooseLocalCertificate));

X509CertificateCollection CC = new X509CertificateCollection();
CC.Add(Org.BouncyCastle.Security.DotNetUtilities.ToX509Certificate(MyLocalCertificate));

SSLConnection.AuthenticateAsClient("test", CC, System.Security.Authentication.SslProtocols.Ssl3, false);

и затем AlwaysValidRemoteCertificate просто возвращает значение true, а ChooseLocalCertificate возвращает нулевой элемент массива.

Код, вероятно, выглядит немного странно, потому что проект немного странен, но я думаю, что здесь дело не в этом. Рукопожатие SSL завершено. Проблема заключается в том, что вместо отправки сообщения сертификата от моего имени (в процессе рукопожатия) с закодированным сертификатом ASN.1 (MyLocalCertificate) SslStream отправляет предупреждение с номером SSL 41 (без сертификата) и затем продолжает работу. Я знаю это по пакетному анализу. После того, как рукопожатие завершено, SslStream помечает IsAuthenticated как true, IsMutuallyAuthenticated - как false, а его член LocalCertificate равен null.

Я чувствую, что, возможно, я здесь упускаю что-то довольно очевидное, поэтому любые идеи будут оценены. Я новичок с SSL, и этот проект находится на проторенном пути, поэтому я немного растерялся.

P.S. 1: Моя процедура ChooseLocalCertificate вызывается дважды во время рукопожатия и возвращает действительный (насколько я могу судить) ненулевой сертификат оба раза.

P.S. 2: SSLInOutStream - это мой собственный класс, а не NetworkStream. Как я уже сказал, рукопожатие проходит в основном нормально, поэтому я сомневаюсь, что это виновник ... но кто знает?

Ответы [ 2 ]

7 голосов
/ 29 мая 2010

По какой-то причине сайт не позволил мне оставить комментарий к решению, опубликованному выше, но это решило мою проблему. Вот мой комментарий:

Эй, это было отличное предположение, и это исправило мою проблему. Большое спасибо. Класс C # X509Certificate, похоже, не поддерживает установку закрытого ключа, но дочерний класс X509Certificate2 поддерживает. Мне пришлось немного поэкспериментировать с вещами BouncyCastle, но реализация (если кому-то это понадобится в будущем) такова:

X509CertificateCollection CC = new X509CertificateCollection();
X509Certificate2 C2 = new X509Certificate2(MyLocalCertificate.GetEncoded());
C2.PrivateKey = Org.BouncyCastle.Security.DotNetUtilities.ToRSA((Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)MyPrivateKey.Private);
CC.Add(C2);

MyLocalCertificate является экземпляром класса bouncycastle X509Certificate, а MyPrivateKey является экземпляром класса bouncycastle AsymmetricCipherKeyPair.

5 голосов
/ 29 мая 2010

Я не знаком с Bouncycastle .NET API для SSL, но на первый взгляд, я предполагаю, что вы не предоставляете закрытый ключ для API.

Несмотря на то, что сам закрытый ключ никогда не отправляется на сервер, требуется цифровая подпись некоторых данных, чтобы доказать серверу, что вы их храните. Должен быть некоторый API для предоставления закрытого ключа для этой операции подписи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...