使用自签名证书将Metro应用程序连接到Python SSL服务器



我如何在Windows 8 Metro应用程序中使用StreamSocket在服务器中使用自签名证书连接到基于Python+ openssl的服务器?我尝试将服务器的公钥添加到Windows Desktop上的各种受信任存储中,但无济于事。我所尝试的一切都产生了相同的结果:一个异常,与这篇文章中的消息相同。

我在Windows 8.1上使用Visual Studio 2013进行开发,连接到运行OpenSSL 1.0.1的Python 3.4服务器

我终于找到了答案。微软在这里提供了一个示例。下载样例后,查看场景5。基于该场景中的代码,下面是一个Windows 8 App Store单元测试类,它提供了如何使用代码的示例:

namespace Services.Implementation.Tests
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Text;
    using Windows.Networking;
    using Windows.Networking.Sockets;
    using Windows.Storage.Streams;
    using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
    using Windows.Security.Cryptography.Certificates;
    using System.Collections.Generic;
    [TestClass]
    public class NetworkConnectionIPv6Tests
    {
        #region Test Lifecycle Members
        /// <summary>
        /// Gets or sets the test context.
        /// </summary>
        /// <value>
        /// The test context.
        /// </value>
        public TestContext TestContext
        {
            get; set;
        }
        #endregion // Test Lifecycle Members
        #region Test Methods
        [TestMethod, TestCategory("Integration")]
        public void TestConnection()
        {
            const int ServerPort = 63253;
            const string ServerIpAddress = "fe80::7ed1:c3ff:fed9:6fc7";
            HostName hostName = new HostName(ServerIpAddress);
            byte[] receiveBuffer = new byte[4096];
            using (StreamSocket streamSocket = new StreamSocket())
            {
                bool retry = true;
                do
                {
                    try
                    {
                        streamSocket.ConnectAsync(hostName, ServerPort.ToString(), SocketProtectionLevel.Tls12).GetAwaiter().GetResult();
                        string certInformation = GetCertificateInformation(
                            streamSocket.Information.ServerCertificate,
                            streamSocket.Information.ServerIntermediateCertificates);
                        Debug.WriteLine("Certificate information: {0}", certInformation);
                        retry = false;
                    }
                    catch (Exception exception)
                    {
                        // If this is an unknown status it means that the error is fatal and retry will likely fail.
                        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                        {
                            throw;
                        }
                        // If the exception was caused by an SSL error that is ignorable we are going to prompt the user
                        // with an enumeration of the errors and ask for permission to ignore.
                        if (streamSocket.Information.ServerCertificateErrorSeverity != SocketSslErrorSeverity.Ignorable)
                        {
                            Debug.WriteLine("Connect failed with error: " + exception.Message);
                            Assert.Fail("Failed to avoid unignorable errors");
                        }
                        // ---------------------------------------------------------------------------
                        // WARNING: Only test applications may ignore SSL errors.
                        // In real applications, ignoring server certificate errors can lead to MITM
                        // attacks (while the connection is secure, the server is not authenticated).
                        // ---------------------------------------------------------------------------
                        streamSocket.Control.IgnorableServerCertificateErrors.Clear();
                        foreach (var ignorableError in streamSocket.Information.ServerCertificateErrors)
                        {
                            streamSocket.Control.IgnorableServerCertificateErrors.Add(ignorableError);
                        }
                    }
                } while (retry);
                byte[] messageBytes = Encoding.UTF8.GetBytes("Test");
                Stopwatch stopwatch = Stopwatch.StartNew();
                uint bytesSent = streamSocket.OutputStream.WriteAsync(messageBytes.AsBuffer()).GetAwaiter().GetResult();
                Assert.AreEqual(messageBytes.Length, (int) bytesSent, "Failed to sent the correct amount of bytes");
                IBuffer bytesReceived = streamSocket.InputStream.ReadAsync(receiveBuffer.AsBuffer(), (uint) receiveBuffer.Length, InputStreamOptions.None).GetAwaiter().GetResult();
                stopwatch.Stop();
                Debug.WriteLine("Remote call turnaround in {0} seconds", stopwatch.Elapsed.TotalSeconds);
                Assert.IsTrue(bytesReceived.Length > 0, "There were no bytes received from the server");
                string responseString = new string(Encoding.UTF8.GetChars(receiveBuffer, 0, (int) bytesReceived.Length));
                Assert.AreEqual("Test right back", responseString, "Failed to receive the expected message from the server");
            }
        }
        #endregion // Test Methods
        #region Helper Methods
        /// <summary>
        /// Gets detailed certificate information
        /// </summary>
        /// <param name="serverCert">The server certificate</param>
        /// <param name="intermediateCertificates">The server certificate chain</param>
        /// <returns>A string containing certificate details</returns>
        private string GetCertificateInformation(
            Certificate serverCert,
            IReadOnlyList<Certificate> intermediateCertificates)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("tFriendly Name: " + serverCert.FriendlyName);
            sb.AppendLine("tSubject: " + serverCert.Subject);
            sb.AppendLine("tIssuer: " + serverCert.Issuer);
            sb.AppendLine("tValidity: " + serverCert.ValidFrom + " - " + serverCert.ValidTo);
            // Enumerate the entire certificate chain.
            if (intermediateCertificates.Count > 0)
            {
                sb.AppendLine("tCertificate chain: ");
                foreach (var cert in intermediateCertificates)
                {
                    sb.AppendLine("ttIntermediate Certificate Subject: " + cert.Subject);
                }
            }
            else
            {
                sb.AppendLine("tNo certificates within the intermediate chain.");
            }
            return sb.ToString();
        }
        #endregion // Helper Methods
    }
}

使用这个例子的关键是你必须使用Windows 8.1的Visual Studio 2013。

相关内容

最新更新