Подключение к серверу с SSL сертификатами
Добавлено: 13 июл 2015, 17:56
Добрый день, мужчины!
Вот такая проблема. Есть сервер к которому нужно подключится. Сервер для защиты использует SSL сертификаты. По задаче нужно отправить запрос на сервер и получить от него ответ. Сертификаты на руках и уже установлены в хранилище сертификатов. Отправляемый контент содержит "подпись" которая так-же получается с помощью ключей, находящихся в этих сертификатах. Подпись правильная и проверена владельцами сервера, по этому исключаю ошибку в ней. Итого имеем: сертификат CA certificate file.cer, client certificate file.pfx, private key file.pfx и пароль (все предоставил владелец сервера). Козалось все просто, есть все составляющие осталось только написать код.
Проверил путь. Вроде все нормально. Кириллицы нет. Врядли информация в сертифекате может быть не верная, т.к. по мимо меня их используют много людей. Вот и ней пойму в чем пролема.
Решил воспользоватся примером владельца написанным на С#. Для этого использовал следующий код:
private string Sign(string data)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateSign, false);
var cert = certColl[0];
var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
var signature = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider());
return Utilities.BytesToHex(signature);
}
private void VerifySign(string data, string signature)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, "private", false);
var cert = certColl[0];
var pubKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
var isValid = pubKey.VerifyData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider(), Utilities.HexToBytes(signature));
if (!isValid)
throw new Exception("Invalid Signature");
}
private static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[1024];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public static bool TrustAllCertificateCallback(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
return true;
}
public string ExecutePOST(string content)
{
var httpRequest = (HttpWebRequest)HttpWebRequest.Create(GatewayUrl);
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateClient, false);
httpRequest.ClientCertificates.Add(certColl[0]);
httpRequest.Method = "POST";
httpRequest.Accept = "*/*";
ServicePointManager.ServerCertificateValidationCallback = TrustAllCertificateCallback;
byte[] requestBuff = Encoding.UTF8.GetBytes(content);
using (var requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(requestBuff, 0, requestBuff.Length);
requestStream.Flush();
}
var response = (HttpWebResponse)httpRequest.GetResponse();
var responseBuff = ReadFully(response.GetResponseStream());
if (response.ContentEncoding.ToLower().Contains("gzip"))
responseBuff = new CompressProvider().Decompress(responseBuff);
return Encoding.UTF8.GetString(responseBuff);
Реализация его в Лабвью на картинке 3 и 4.
Но сдесь тоже есть проблема. Не могу реализовать следующюю строчку, а именно указать УРЛ по которому нужно отправить запрос:
var httpRequest = (HttpWebRequest)HttpWebRequest.Create(GatewayUrl);
Дело в том, что метод Create(GatewayUrl) принадлежит классу WebRequest, который не доступен для меня (картинка 4). На МСДН предлагаютт альтернативнуюю библиотеку, но там этот класс тоже не доступен.
В общем помогите кто как может!!:)
Вот такая проблема. Есть сервер к которому нужно подключится. Сервер для защиты использует SSL сертификаты. По задаче нужно отправить запрос на сервер и получить от него ответ. Сертификаты на руках и уже установлены в хранилище сертификатов. Отправляемый контент содержит "подпись" которая так-же получается с помощью ключей, находящихся в этих сертификатах. Подпись правильная и проверена владельцами сервера, по этому исключаю ошибку в ней. Итого имеем: сертификат CA certificate file.cer, client certificate file.pfx, private key file.pfx и пароль (все предоставил владелец сервера). Козалось все просто, есть все составляющие осталось только написать код.
Проверил путь. Вроде все нормально. Кириллицы нет. Врядли информация в сертифекате может быть не верная, т.к. по мимо меня их используют много людей. Вот и ней пойму в чем пролема.
Решил воспользоватся примером владельца написанным на С#. Для этого использовал следующий код:
private string Sign(string data)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateSign, false);
var cert = certColl[0];
var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
var signature = rsa.SignData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider());
return Utilities.BytesToHex(signature);
}
private void VerifySign(string data, string signature)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, "private", false);
var cert = certColl[0];
var pubKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
var isValid = pubKey.VerifyData(Encoding.UTF8.GetBytes(data), new SHA1CryptoServiceProvider(), Utilities.HexToBytes(signature));
if (!isValid)
throw new Exception("Invalid Signature");
}
private static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[1024];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public static bool TrustAllCertificateCallback(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
return true;
}
public string ExecutePOST(string content)
{
var httpRequest = (HttpWebRequest)HttpWebRequest.Create(GatewayUrl);
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certColl = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateClient, false);
httpRequest.ClientCertificates.Add(certColl[0]);
httpRequest.Method = "POST";
httpRequest.Accept = "*/*";
ServicePointManager.ServerCertificateValidationCallback = TrustAllCertificateCallback;
byte[] requestBuff = Encoding.UTF8.GetBytes(content);
using (var requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(requestBuff, 0, requestBuff.Length);
requestStream.Flush();
}
var response = (HttpWebResponse)httpRequest.GetResponse();
var responseBuff = ReadFully(response.GetResponseStream());
if (response.ContentEncoding.ToLower().Contains("gzip"))
responseBuff = new CompressProvider().Decompress(responseBuff);
return Encoding.UTF8.GetString(responseBuff);
Реализация его в Лабвью на картинке 3 и 4.
Но сдесь тоже есть проблема. Не могу реализовать следующюю строчку, а именно указать УРЛ по которому нужно отправить запрос:
var httpRequest = (HttpWebRequest)HttpWebRequest.Create(GatewayUrl);
Дело в том, что метод Create(GatewayUrl) принадлежит классу WebRequest, который не доступен для меня (картинка 4). На МСДН предлагаютт альтернативнуюю библиотеку, но там этот класс тоже не доступен.
В общем помогите кто как может!!:)