C# .NET - 固定证书颁发机构 - 我做得正确吗?

2023-11-22

我的软件使用 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;
        }
}

它工作正常,但我不知道我是否检查了正确的事情。一些加密货币专家的任何建议将不胜感激。


您的代码对于固定到根 CA 公钥来说看起来是正确的。

不过,HPKP 要求您至少提供一个备用引脚,我建议您遵循该指南。鉴于您固定到根 CA,最好提供另一个根 CA 的公钥作为备份,以减轻第一个 CA 发生问题(例如停业)时的 DoS 风险。

当然,您的代码可以容纳多个要固定的公钥,因此只需将附加密钥添加到字符串列表中即可。

Cheers

编辑2017.10.23

以下是我认为合理的根 CA 公钥固定和证书验证应该是什么样子的示例。这个快速示例是在 WebApi 项目中完成的,因此是样板值控制器。

请注意,我的示例中仅使用一 (1) 个根 CA 公钥,并且如上所述,应提供备份 pin(至少 2 个数组元素)。

这是一个sample并且不打算被视为生产代码 - 我建议以下内容接受同行/安全审查:

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.");
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# .NET - 固定证书颁发机构 - 我做得正确吗? 的相关文章

随机推荐

  • 将变量从容器开始传递到文件

    我在 Dockerfile 中有以下几行 我想在应用程序最后启动之前将配置文件中的值设置为默认值 并提供可选的使用 e启动容器时的选项 我正在尝试使用 Docker 来做到这一点ENV突击队 ENV CONFIG VALUE default
  • 我使用的是哪个版本的 Kohana?

    Kohana框架中哪里可以找到版本信息 我在教程中看到的所有内容都与我在应用程序中看到的内容相反 我认为这是一个版本问题 因为文档和我的安装之间的方法和调用略有不同 至少对于 gt 3 0 的版本 Kohana 的版本号位于system c
  • Applescript 右键单击​​文件

    苹果脚本中是否有一个命令可以右键单击文件并调出上下文菜单 我正在寻找类似的东西 tell application Finder set theDesktopItems to every item of desktop right click
  • 如何逃脱液体模板标签?

    这听起来很简单 但是我在文档中找不到它 我怎样才能写 this in a liquid模板 未经引擎处理 可以使用以下命令禁用液体处理引擎raw tag raw this endraw 将显示 this
  • 将 Node.js 应用程序(托管在 GAE 上)的 IP 列入白名单以访问 MongoDB Atlas(托管在 GCP 上)

    我希望我的后端服务器 Node js 托管在 Google App Engine 上 灵活的环境 如果重要的话 能够从我的数据库 MongoDB 通过 Atlas 也托管在同一区域的 Google Cloud 平台上 获取和传递数据作为我的
  • 如何配置 flot 以在 y 轴零点处绘制缺失的时间序列?

    我正在使用浮点 github上的浮动 用以下时间序列数据绘制图表 1357171200000 1 1357344000000 1 1357430400000 2 1357516800000 2 1357689600000 3 1357776
  • 如何在Magento中连接多个外部数据库? [关闭]

    Closed 这个问题是无关 目前不接受答案 我需要从 Magento 连接到一些外部数据库 我找到了一个教程在 Magento 中创建外部数据库连接 本教程很有帮助 它适用于连接到一个外部数据库 但是 我必须连接多个外部数据库 如何在 M
  • django.core.paginator 使用 jQuery 进行 Ajax 分页

    Problem 我需要在 Django 模板中使用 jQuery 进行 Ajax 分页 情况 我的模板中有以下代码 code omitted table table
  • PHP spl_自动加载

    我真的没有得到 spl autoload 的文档 bool spl autoload register callback autoload function 根据我的理解 当 php 遇到尚未加载的类时 它将尝试运行注册的函数 例如 pub
  • 我可以使用 open_basedir 访问 /dev/urandom 吗?

    我想在 Codeigniter 中使用 phpass 0 3 但由于以下原因出现以下错误open basedir 遇到 PHP 错误严重性 警告消息 is 可读 函数 可读 open basedir 限制生效 文件 dev urandom
  • 为什么 Google API V3 不返回子级?

    我想使用 Python 获取 Google Drive 中给定文件夹中的所有文件 文件夹的列表 我正在使用的调用是这样的 query parentID in parents response service files list q que
  • 自定义创建的方法错误:“不是函数”

    我有一个英雄按钮列表 其中创建了自定义动画button component ts 一开始 他们是不活跃的 当我按下其中之一时 所选的应该变为活动状态 为此 我创建了一个字段hero ts called state和一个名为的函数toggle
  • 使用 css 按对角线分割双色调背景

    我正在尝试使用 css 创建一个背景 其中一侧是纯色 另一侧是纹理 两者被对角线分开 我希望这是 2 个独立的 div 因为我计划使用 jQuery 添加一些动作 如果您单击右侧 灰色三角形会变小 如果您单击左侧 纹理三角形会变小 就像窗帘
  • Safari 为 Silverlight (NPAPI) 计划的生命周期是怎样的

    Chrome 已经放弃了 NPAPI silverlight 支持 Firefox 宣布将于 2016 年底停止对 NPAPI 支持 https blog mozilla org futurereleases 2015 10 08 npap
  • 如何从 MSI“文件”表中提取数据(文件计数)

    在我们的构建过程中 当前有可能将基于非代码的文件 例如图像文件 添加到我们的 Web 项目中 但不包含在 WiX 构建的 MSI 安装程序中 为了帮助防止这种情况 我想在 WiX 项目的 AfterBuild 目标中执行以下操作 获取所有已
  • 在 UWP Xaml 中创建并填充 NxN 网格

    我正在尝试创建一个UWP益智游戏 我想将图片切成n个部分 然后在网格中显示这些部分 我的问题是 如何强制某种 NxN 风格 现在我必须最大化窗口才能看到 3x3 网格 如果我缩小任一侧 它将收敛到 2 列 1 列网格 有办法处理这个问题吗
  • Ionic 4 Angular 路由器导航并清除上一页的堆栈/历史记录

    我正在使用 Ionic 4 和 Angular 路由器开发一个应用程序 我想导航到另一个页面并清除页面堆栈 在 Android 原生中 它是这样的 Intent intent new Intent NewActivity this Main
  • 带有 attr_accessor 的类上的 Ruby instance_eval

    我了解之间的基本区别instance eval and class eval 但我在玩的时候发现了一些奇怪的事情attr accessor 这是一个例子 A Class new A class eval attr accessor x a
  • 如何在 Markdown 中为 PDF 文档添加图像作为页眉/页脚

    我想将图像作为页眉和页脚 与我的组织的视觉标识保持一致 添加到 PDF 报告中 我已经设法在 Sweave 中做到这一点 但我也希望能够仅使用 Markdown 来做到这一点 我可以使用插入图像 footer H R Footer pdf
  • C# .NET - 固定证书颁发机构 - 我做得正确吗?

    我的软件使用 HTTPS 连接连接到 Dropbox 以检索一些敏感数据 我想固定证书颁发机构以防止中间人攻击 到目前为止我有以下代码 static bool VerifyServerCertificate object sender X5