所以我正在尝试开发一个安全的 Windows 8.1 Phone 应用程序。请注意,这是在 Windows Phone 上使用,而不是在普通 Windows 上使用。这里主要关注的是中间人(MITM)攻击。
该应用程序是使用 Microsoft App Studio ( http://appstudio.windows.com/ ) 生成的,并使用 Visual Studio 2015 进行了编辑。
我可以使用此 MS 博客文章中的说明将证书固定到普通 Windows 部分:https ://blogs.msdn.microsoft.com/wsdevsol/2014/06/05/include-self-signed-certificates-with-your- windows-runtime-based-windows-phone-8-1-apps/但问题是用户可以将证书上传到设备,这将覆盖来自该应用程序的检查。
这种方法的问题在于Package.appxmanifest
Windows Phone 应用程序的界面不允许您更新证书,更不用说将其标记为“独占”了。
我的第二次尝试是根据这篇文章对服务器证书的指纹进行硬编码:https ://blogs.windows.com/buildingapps/2015/10/13/create-more-secure-apps-with-less-effort-10 -by-10/(注意“独占信任”复选框)
尽管该帖子适用于 Windows 10,但代码有效(在添加了正确的导入之后)。然而,同样,当一个人更新自己的证书时,它会绕过指纹检查。
因为我无法使用 Visual Studio 界面将证书上传到电话应用程序部分,因此无法选中“独占信任”框,我将如何确保对网站的任何请求仅使用证书我上传还是我硬编码的指纹?
这是指纹识别码:
using System;
using System.Net;
using Windows.Web.Http;
using System.Collections.Generic;
using Windows.System;
using Windows.Security.Cryptography.Certificates;
using The_App.Views;
namespace The_App.Services
{
public class NavigationServices
{
static public void NavigateToPage(string pageName, object parameter = null)
{
try
{
string pageTypeName = String.Format("{0}.{1}", typeof(MainPage).Namespace, pageName);
Type pageType = Type.GetType(pageTypeName);
App.RootFrame.Navigate(pageType, parameter);
}
catch (Exception ex)
{
AppLogs.WriteError("NavigationServices.NavigateToPage", ex);
}
}
static public async void NavigateTo(Uri uri)
{
try
{
// Send a get request to uri
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(uri);
// Get the list of certificates that were used to validate the server's identity
IReadOnlyList<Certificate> serverCertificates = response.RequestMessage.TransportInformation.ServerIntermediateCertificates;
// Perform validation
if (!ValidCertificates(serverCertificates))
{
// Close connection as chain is not valid
return;
}
// PrintResults("Validation passed\n");
// Validation passed, continue with connection to service
await Launcher.LaunchUriAsync(uri);
}
catch (Exception ex)
{
AppLogs.WriteError("NavigationServices.NavigateTo", ex);
}
}
private static bool ValidCertificates(IReadOnlyList<Certificate> certs)
{
// In this example, we iterate through the certificates and check that the chain contains
// one specific certificate we are expecting
for (int i = 0; i < certs.Count; i++)
{
// PrintResults("Cert# " + i + ": " + certs[i].Subject + "\n");
byte[] thumbprint = certs[i].GetHashValue();
// Check if the thumbprint matches whatever you are expecting
// <The SHA1 Server Certificate HEX Number in the comments>
byte[] expected = new byte[] { <The SHA1 Server Certificate Number in Bytes 45, 15, etc.> };
if (thumbprint == expected)
{
return true;
}
}
return false;
}
}
}