强制 HttpClient 信任单个证书 [英] Force HttpClient to trust single Certificate

查看:40
本文介绍了强制 HttpClient 信任单个证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你能强制 HttpClient 只信任一个证书吗?

Can you force HttpClient to only trust a single certificate?

我知道你可以做到:

WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 certificate = GetMyX509Certificate();
handler.ClientCertificates.Add(certificate);
HttpClient client = new HttpClient(handler);

但这会迫使它只信任那个单一的证书,还是会信任那个证书和所有能生效的证书.GlobalSign 可以验证吗?

But will this force it to only trust that single certificate, or will it trust that certifate AND all certificates that fx. GlobalSign can verify?

基本上我想确保它只能是我的客户端正在与之交谈的服务器/证书.

Basicly I want to ensure that it can ONLY be my server/certificate that my client is talking to.

推荐答案

你能强制 HttpClient 只信任一个证书吗?...基本上我想确保它只能是我的客户正在与之交谈的服务器/证书.

Can you force HttpClient to only trust a single certificate? ... Basically I want to ensure that it can ONLY be my server/certificate that my client is talking to.

是的.但是什么类型的证书?服务器还是 CA?以下是两者的示例.

Yes. But what type of certificate? Server or CA? Examples for both follow.

此外,在服务器的情况下,固定公钥而不是证书可能会更好.这是因为一些组织,如谷歌,每 30 天左右轮换一次他们的服务器证书,以努力保持 CRL 对移动客户端来说很小.但是,组织将重新认证相同的公钥.

Also, it might be better to pin the public key rather than the certificate in the case of a server. That's because some organizations, like Google, rotate their server certificates every 30 days or so in an effort to keep the CRLs small for mobile clients. However, the organizations will re-certify the same public key.

以下是从 将特定 CA 用于SSL 连接.它需要将证书放置在证书存储中.您可以在应用中随身携带 CA.

Here's an example of pinning the CA from Use a particular CA for a SSL connection. It does not require placing the certificate in a Certificate Store. You can carry the CA around in your app.

static bool VerifyServerCertificate(object sender, X509Certificate certificate,
    X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    try
    {
        String CA_FILE = "ca-cert.der";
        X509Certificate2 ca = new X509Certificate2(CA_FILE);

        X509Chain chain2 = new X509Chain();
        chain2.ChainPolicy.ExtraStore.Add(ca);

        // Check all properties (NoFlag is correct)
        chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

        // This setup does not have revocation information
        chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

        // Build the chain
        chain2.Build(new X509Certificate2(certificate));

        // Are there any failures from building the chain?
        if (chain2.ChainStatus.Length == 0)
            return false;

        // If there is a status, verify the status is NoError
        bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError;
        Debug.Assert(result == true);

        return result;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }

    return false;
}

没有知道如何默认使用这个链(上面的chain2),这样就不需要回调了.也就是说,将它安装在 ssl 套接字上,连接将正常工作".

I have not figured out how to use this chain (chain2 above) by default such that there's no need for the callback. That is, install it on the ssl socket and the connection will "just work".

而且我没有想出了如何安装它以便将其传递到回调中.也就是说,我必须为回调的每次调用构建链,因为我的 chain2 没有作为 chain 传递给函数.

And I have not figured out how install it such that its passed into the callback. That is, I have to build the chain for each invocation of the callback because my chain2 is not passed into the functions as chain.

这是一个从 OWASP 的 证书和公钥固定.它需要将证书放置在证书存储中.您可以在应用中随身携带证书或公钥.

Here's an example of pinning the server certificate from OWASP's Certificate and Public Key Pinning. It does not require placing the certificate in a Certificate Store. You can carry the certificate or public key around in your app.

// 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;
}

这篇关于强制 HttpClient 信任单个证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆