C# HttpClient с X509Certificate2 - WebException: запрос был прерван: не удалось создать безопасный канал SSL/TLS

Я работаю над внедрением платежного сервиса Swish и тестирую его с помощью этого руководства (Руководство на английском языке, хотя имя файла - шведский).

https://www.getswish.se/content/uploads/2015/06/Guide-Testverktyg_20151210.zip

Как видите, тестовый проект содержит два сертификата, .p12 а также .pem файл. Я попытался подтвердить подлинность запроса с обоими.

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

Как предложено здесь, я реализовал ведение журнала, и это результат. Ссылка Pastebin из-за ограничения символов. Я не вижу ничего, указывающего на StatusCode=401 в журналах, так что я не думаю, что это HTTP 401 Unauthorized,

public class PaymentRequest
{
    [JsonProperty("payeePaymentReference")]
    public string PayeePaymentReference { get; set; }

    [JsonProperty("callbackUrl")]
    public string CallbackUrl { get; set; }

    [JsonProperty("payerAlias")]
    public string PayerAlias { get; set; }

    [JsonProperty("payeeAlias")]
    public string PayeeAlias { get; set; }

    [JsonProperty("amount")]
    public string Amount { get; set; }

    [JsonProperty("currency")]
    public string Currency { get; set; }

    [JsonProperty("message")]
    public string Message { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var service = new SwishService();

        var paymentRequest = new PaymentRequest();
        paymentRequest.PayeePaymentReference = "0123456789";
        paymentRequest.CallbackUrl = "https://example.com/api/swishcb/paymentrequests";
        paymentRequest.PayerAlias = "4671234768";
        paymentRequest.PayeeAlias = "1231181189";
        paymentRequest.Amount = "100";
        paymentRequest.Currency = "SEK";
        paymentRequest.Message = "Kingston USB Flash Drive 8 GB";

        service.SendPaymentRequest(paymentRequest);
    }
}

public class SwishService
{
    private HttpClient client;
    public SwishService()
    {
        var baseAddress = new Uri("https://mss.swicpc.bankgirot.se");

        var certHandler = new WebRequestHandler();
        certHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
        certHandler.UseDefaultCredentials = false;

        //Same result with Swish Merchant Test Certificate 1231181189.p12 file
        var certPath = $"C:\\Users\\<Path>\\Testcertifikat\\Test Swish Root CA v1 Test.pem";

        var certificate = new X509Certificate2(certPath, "swish");
        certHandler.ClientCertificates.Add(certificate);

        client = new HttpClient(new LoggingHandler(certHandler));
        client.BaseAddress = baseAddress;
        client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
    }

    public void SendPaymentRequest(PaymentRequest paymentRequest)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
                                               | SecurityProtocolType.Tls11
                                               | SecurityProtocolType.Tls12
                                               | SecurityProtocolType.Ssl3;

        //Code throws exception before this callback is called
        ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        };

        var content = new StringContent(JsonConvert.SerializeObject(paymentRequest), Encoding.UTF8, "application/json");

        var response = client.PostAsync("/swish-cpcapi/api/v1/paymentrequests/", content).Result;

        var resultStream = response.Content.ReadAsStreamAsync().Result;
        var result = string.Empty;

        using (var streamReader = new StreamReader(resultStream))
        {
            result = streamReader.ReadToEnd();
        }
    }

}

Обновить:

Используя Postman в Chrome, я мог отправить запрос после импорта сертификата в Chrome, а затем через mmc в магазине Trusted Root Certification Authorities, Мне пока не удалось найти решение в коде. PS: хостинг для приложения требует, чтобы сертификат загружался из файла, а не извлекался из хранилища сертификатов.

Обновление 2:

Журнал диагностики системы с трассировкой стека:

https://pastebin.com/qMz6X6yJ

2 ответа

Решение

Найден тест SSL, выполненный на сервере:

https://www.ssllabs.com/ssltest/analyze.html?d=mss.swicpc.bankgirot.se

Отсюда я мог видеть, что следующие протоколы были разрешены:

После того, как я установил это все работало:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Вы можете прикрепить eventHandler к ServicePointManager как это:

ServicePointManager.ServerCertificateValidationCallback = ForcedAuthDelegate;

и реализация ForcedAuthDelegate должен вернуться true принять соединение:

        static bool ForcedAuthDelegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
Другие вопросы по тегам