【问题标题】:How to make sure that my software is connected to the right server?如何确保我的软件连接到正确的服务器?
【发布时间】:2012-06-18 17:05:19
【问题描述】:

我有一个使用 ssl 证书标识自己的服务器。证书是自签名的。

如果用户尝试更换服务器并将“假”证书添加到操作系统信任的证书列表中,我想确保该软件不会发送数据。

到目前为止,这是我想出的:

ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;

private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    bool result = false;
    if (sender is HttpWebRequest)
    {
        var wr = sender as HttpWebRequest;
        if (wr.Address.Host == "<my host>")
        {
            if (cert == null)
            {
                return false;
            }
            if (cert.GetCertHashString() == "<certificate hash string>")
            {
                return true;
            }
            return false;
        }
    }

    return result;
}

按照我对代码的理解,它会信任我的 my host 证书,但它不会受到用户主机替换的保护。

我希望软件仅在使用&lt;certificate hash string&gt; 标识自己的证书时接受my host,并且如果my host 提供其他证书,则必须拒绝连接。

我该怎么做?

【问题讨论】:

  • 在我回答这个问题之前。生成两个证书。插入一个证书的哈希值,然后发送另一个证书。报告发生了什么。
  • 我认为另一条评论已经说到点子上了,但仍然......在代码中包含证书哈希字符串听起来不是一个好主意。
  • 试图保护什么?客户正在上传机密数据?如果您有不受信任的客户,那么如何阻止他们直接入侵数据?证书是否会被黑客入侵以获取其他用户稍后发送的数据?如果他们要破解证书,什么会阻止他们破解哈希码?
  • 因为另一个是自签名的,直到我告诉软件它才会被接受,所以我用google.com尝试了这个东西,它被拒绝了。看来这段代码毕竟够用了
  • @KenBrittain 我打算在之后混淆代码,但如果你有更好的想法将证书哈希放在哪里,我愿意接受建议

标签: c# .net security ssl trust


【解决方案1】:

如何确保我的软件连接到正确的服务器?

由于您事先知道服务器,因此您知道服务器应该使用的证书和公钥。为了利用这些知识,您使用一种称为固定的技术。 OWASP 在Certificate and Public Key Pinning 对此进行了讨论。

C# 的代码相当简单。以下摘自 OWASP 页面。它连接到 Google,并确保服务器使用预期的公钥:

// Encoded RSAPublicKey
private static String PUB_KEY = "30818902818100C4A06B7B52F8D17DC1CCB47362" +
    "C64AB799AAE19E245A7559E9CEEC7D8AA4DF07CB0B21FDFD763C63A313A668FE9D764E" +
    "D913C51A676788DB62AF624F422C2F112C1316922AA5D37823CD9F43D1FC54513D14B2" +
    "9E36991F08A042C42EAAEEE5FE8E2CB10167174A359CEBF6FACC2C9CA933AD403137EE" +
    "2C3F4CBED9460129C72B0203010001";

public static void Main(string[] args)
{
  ServicePointManager.ServerCertificateValidationCallback = PinPublicKey;
  WebRequest wr = WebRequest.Create("https://encrypted.google.com/");
  wr.GetResponse();
}

public static bool PinPublicKey(object sender, X509Certificate certificate, X509Chain chain,
                                SslPolicyErrors sslPolicyErrors)
{
  if (null == certificate)
    return false;

  String pk = certificate.GetPublicKeyString();
  if (pk.Equals(PUB_KEY))
    return true;

  // Bad dog
  return false;
}

证书固定不适用于 Google 和其他一些人。这是因为他们每 30 天左右轮换一次证书,以使 CRL 对于移动客户端来说很小。但是他们重新认证了相同的公钥,以允许像 pinning 这样的密钥连续性方案起作用。所以公钥固定将按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2023-03-17
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    相关资源
    最近更新 更多