SslStream, makecert и Windows в одном. Ужасы сертификации 2.
От: Schizophrenia Россия  
Дата: 12.04.07 06:26
Оценка:
Здравствуйте.
Очень прошу помочь с некоторым вопросом. Мне необходимо установить ssl поток для передачи данных
между клиентом и сервером

Язык разработки C#, .Net 2.0. Система Windows 2000. Необходимо установить защищенное соединение
(Ssl) между клиентом и сервером.


Что делаю я:

Сначала я занялась генерированием сертификатов с помощью утилиты makecert.

Сначала я создала root сертификат, самоподписывающийся:
Makecert -r -eku 1.3.6.1.5.5.7.3.1 -n "CN=RootSslStram" -sv root.pvk root.cer
И установила его в хранилище сертификатов с названием Root

Затем, с его помощью я подписала сертификат, который будет использовать сервер:
Makecert -n "CN=SslStreamCert" -sv SampleCert.pvk -ic root.cer -iv root.pvk SampleCert.cer

После этого, с помощью утилиты pvk2pfx, я создала файл сертификата, который содержит в
себе пару ключей: открытый и приватный (два в одном ):
pvk2pfx -pvk SampleCert.pvk -pi *** -spc SampleCert.cer -pfx SampleCert.pfx -po ***
Этот SampleCert.pfx я установила в хранилище My.

Затем, я попыталась дать своей программе возможность воспользоваться сертификатом.
Для большей простоты, я приведу код простейшего соединения, взятый с сайта
http://www.leastprivilege.com/PermaLink.aspx?guid=6b5d5471-0710-41d7-891b-308afa959a6e



Сервер:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Security;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            X509Certificate cert = getServerCert();

            TcpListener sslServer = new TcpListener(IPAddress.Any, 4242);

            sslServer.Start();

            Console.WriteLine("Waiting for incoming connection...");
            TcpClient client = sslServer.AcceptTcpClient();

            SslStream sslStream = new SslStream(client.GetStream());
            sslStream.AuthenticateAsServer(cert, false, SslProtocols.Default, false);

            StreamReader reader = new StreamReader(sslStream);
            StreamWriter writer = new StreamWriter(sslStream);

            Console.ReadLine();
            

        }

        private static X509Certificate getServerCert()
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            X509CertificateCollection cert = store.Certificates.Find(X509FindType.FindBySubjectName, "SampleCert", true);
            return cert[0];
        }

        
    }
}



Клиент:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.IO;
using System.Security.Cryptography.X509Certificates;


namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string serverName = "SampleCert";

                TcpClient sslClient = new TcpClient();
                sslClient.Connect("localhost", 4242);

                SslStream sslStream = new SslStream(sslClient.GetStream(), false,new RemoteCertificateValidationCallback(CertificateValidationCallback));
                
                sslStream.AuthenticateAsClient(serverName);

        
                StreamWriter writer = new StreamWriter(sslStream);
                StreamReader reader = new StreamReader(sslStream);

                

            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadLine();
        }

        static bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors != SslPolicyErrors.None)
            {
                Console.WriteLine("SSL Certificate Validation Error!");
                Console.WriteLine(sslPolicyErrors.ToString());
                return false;
            }
            else
                return true;
        }
    }
}



После запуска на исполнение AuthenticateAsServer выдает исключение, содержащее следующую строку:
Предоставленные пакету учетные данные не были распознаны.
Или английская версия того же сообщения:
The credentials supplied to the package were not recognized

В общем, ошибка с именем — SEC_E_UNKNOWN_CREDENTIALS.



Первой моей идеей было то, что ошибка происходит из-за того, что Windows не доверяет моему
сертификату. Но на деле, это оказалось неправдой, т.к. все сертификаты лежат именно там где надо.

Затем, мне попался сайт http://www-1.ibm.com/support/docview.wss?uid=swg21200501.
Но, это тоже мне не очень помогло.

Есть еще идея, что клиент не разобрался с сертификатом сервера и поэтому при аутентификации
прислал ему какой-нибудь мусор. Но как это проверить, я не знаю.



Теперь я не знаю, что и подумать. Поэтому прошу вас, если знаете, что можно здесь сделать,
подскажите, пожалуйста.

Спасибо, всем, кто откликнется.
Во всяком желании возможно вознаграждение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.