Joh*_*ohn 6 .net c# https ca pki
我的软件使用 HTTPS 连接连接到 Dropbox 以检索一些敏感数据。
我想固定证书颁发机构以防止中间人攻击。
到目前为止,我有以下代码:
static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
try
{
var currentCaPublicKey = chain.ChainElements.Cast<X509ChainElement>().Last().Certificate.GetPublicKeyString();
var caPublicKeys = new List<string>(){"00ad0e15cee443805cb187f3b760f97112a5aedc269488aaf4cef520392858600cf880daa9159532613cb5b128848a8adc9f0a0c83177a8f90ac8ae779535c31842af60f98323676ccdedd3ca8a2ef6afb21f25261df9f20d71fe2b1d9fe1864d2125b5ff9581835bc47cda136f96b7fd4b0383ec11bc38c33d9d82f18fe280fb3a783d6c36e44c061359616fe599c8b766dd7f1a24b0d2bff0b72da9e60d08e9035c678558720a1cfe56d0ac8497c3198336c22e987d0325aa2ba138211ed39179d993a72a1e6faa4d9d5173175ae857d22ae3f014686f62879c8b1dae45717c47e1c0eb0b492a656b3bdb297edaaa7f0b7c5a83f9516d0ffa196eb085f18774f"};
return caPublicKeys.Any(s => currentCaPublicKey.Equals(s));
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我不知道我是否在检查正确的东西。一些加密专家的任何建议将不胜感激。
您的代码看起来适合固定到根 CA 公钥。
但是,HPKP 要求您提供至少一个备用引脚,我建议您遵循该指南。鉴于您固定到一个根 CA,提供另一个根 CA 的公钥作为备份以减轻 DoS 风险(如果第一个 CA 发生某些事情(例如,停业))是合适的。
当然,您的代码可以容纳多个要固定的公钥,因此只需将附加密钥添加到您的字符串列表中即可。
干杯
编辑 2017.10.23
这是我认为合理的根 CA 公钥固定和证书验证应该是什么样子的示例。这个快速示例是在 WebApi 项目中完成的,因此是样板值控制器。
请注意,我的示例中仅使用了一 (1) 个根 CA 公钥,并且如上所述,应提供一个备份引脚(最少 2 个数组元素)。
这是一个示例,不打算用作生产代码 - 我建议以下内容接受同行/安全审查:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Web.Http;
namespace CertPinPocClient.Controllers
{
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
ServicePointManager.ServerCertificateValidationCallback = new PinnedRootCaCertificate(new[]
{
"MIICCgKCAgEAzHYh7u+V5haaRSoGSVGm/gC4EYvZHkBR3/c/kQvTJeh1L9Bn/b7U1s7onw85SjvpZ28ohoT7p4vJRoNUBemR6hf3TM1mZmSE0tqnLGzBV9H4Nfrxx1+cubxYyYaOJ8iJfp1XslGGyZqQmUFFjWOUuU9cvOAbz4DqBIUn344JhG0xEHCf5IOF0gfuWE8yQC9vIjlveUQQ7dq/rDNZcQjqDhEb6DcF7za+1ZxjZdmtKewoYgDBPqzf66Gwi85BZsEcYFQTbjzvAhYaq4xPhJF6iPS4ihf+zjnMPxmy2oH1bm8n2fVuyxqV5JgIDU0ualx728UhfJUjcoBl57OLVsiJIdHFHpcDhN8Fn5QUGkNPgQqX27R1aw/+t2HfYTEsg6urH3aam8e7qRKUEXJs8qMKnXZ15aY0zlO7DLtfnK5tq2Cnu+HBBo4FlDhRO4kTBZOisFkvkEWI/Nj6jioOyMWsTsUvOdDK5KUpWZazpc3rwCvQy3KwBz6EyPU7ihrTm+nqqK5wiI9YwRcMjsPRBZfAur1cB0hNi+g98+2zzj+hwyR49KkOzFowp5MvXEWhnYDrY4cHSJ7zSdgMdO9HWPMke1HuKOUuUUUIpQMvPmFDAh4WQpAKqGvI/cOZeubnSwVMQra13QviYdlUeT56tFDTjgdbUNyBy0gxcFPVgTjzTj8CAwEAAQ==",
}).Valid;
var httpClient = new HttpClient
{
BaseAddress = new Uri("https://local.monitor.iontech.org")
};
var httpResponseMessage = httpClient.GetAsync(new Uri("https://local.monitor.iontech.org/api/status/")).Result;
var result = httpResponseMessage.Content.ReadAsStringAsync().Result;
return new[] {result};
}
}
public class PinnedRootCaCertificate
{
private readonly string[] _rootCaPublicKeys;
public PinnedRootCaCertificate(string[] rootCaPublicKeys)
{
_rootCaPublicKeys = rootCaPublicKeys;
}
public bool Valid(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
if (sslpolicyerrors != SslPolicyErrors.None) return false;
var rootCertificate = SelfSignedCertificate(chain);
var publicKey = Convert.ToBase64String(rootCertificate.PublicKey.EncodedKeyValue.RawData);
return rootCertificate.Verify() && _rootCaPublicKeys.Contains(publicKey);
}
private X509Certificate2 SelfSignedCertificate(X509Chain chain)
{
foreach (var x509ChainElement in chain.ChainElements)
{
if (x509ChainElement.Certificate.SubjectName.Name != x509ChainElement.Certificate.IssuerName.Name) continue;
return x509ChainElement.Certificate;
}
throw new Exception("Self-signed certificate not found.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4768 次 |
最近记录: |