1

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

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

4

1 回答 1

1

我能够找到答案。Microsoft在此处提供了一个示例。下载示例后,请查看场景 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("\t\tIntermediate 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。

于 2014-07-18T03:18:43.200 回答