[英]Connect a Metro app to a Python SSL server with a self-signed certificate
How can I use a StreamSocket
in a Windows 8 Metro app to connect to a Python+OpenSSL-based server using a self-signed certificate in the server ? 如何使用服务器中的自签名证书在Windows 8 Metro应用程序中使用
StreamSocket
连接到基于Python + OpenSSL的服务器? I've tried adding the server's public key to the various trusted stores on the Windows Desktop to no avail. 我尝试将服务器的公钥添加到Windows桌面上的各种受信任存储中都无济于事。 Everything I've tried yields the same results: an exception with the same message as in this post .
我已经竭尽所能产生相同的结果:与同一消息的例外,因为在这个职位 。
I'm developing with Visual Studio 2013 on Windows 8.1, connecting to a Python 3.4 server running OpenSSL 1.0.1h 我正在使用Windows 8.1上的Visual Studio 2013开发,并连接到运行OpenSSL 1.0.1h的Python 3.4服务器
I was able to find the answer. 我找到了答案。 Microsoft provides a sample here .
Microsoft 在此处提供了一个示例 。 Once you download the sample, check out scenario 5. Based on the code in that scenario, here's a Windows 8 App Store unit test class that provides an example of how to use the code:
下载示例后,请检查场景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
}
}
The key to using this example is that you have to be using Visual Studio 2013 targeting for Windows 8.1. 使用此示例的关键是您必须使用Windows 8.1的Visual Studio 2013目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.