【发布时间】:2018-09-12 23:41:46
【问题描述】:
对如何进行证书固定感到困惑。我们如何通过 xmarin 表单在 n android 或 ios 设备中安装证书。如果应用程序是在安装期间完成的吗?有一些关于如何使用 pinning 验证 https 请求的教程,但没有安装公共证书?
【问题讨论】:
标签: xamarin xamarin.forms ssl-certificate pinning
对如何进行证书固定感到困惑。我们如何通过 xmarin 表单在 n android 或 ios 设备中安装证书。如果应用程序是在安装期间完成的吗?有一些关于如何使用 pinning 验证 https 请求的教程,但没有安装公共证书?
【问题讨论】:
标签: xamarin xamarin.forms ssl-certificate pinning
另一种方法是在叶子的证书公钥上执行固定,在this simple demo class 中,我们可以通过自定义 ServicePointManager 来了解使用 HttpClient 时如何做到这一点:
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace ApproovSDK
{
/**
* Service point configuration.
*
* Adds simple pinning scheme to service point manager.
*
* FOR DEMONSTRATION PURPOSES ONLY
*/
public static class ServicePointConfiguration
{
private static string PinnedPublicKey = null;
public static void SetUp(string key = null)
{
PinnedPublicKey = key;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertficate;
}
private static bool ValidateServerCertficate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
)
{
if (PinnedPublicKey == null || PinnedPublicKey.Length <= 0) return true;
//Console.WriteLine("Expected: " + PinnedPublicKey);
//Console.WriteLine("Found : " + certificate?.GetPublicKeyString());
return String.Equals(PinnedPublicKey, certificate?.GetPublicKeyString(),
StringComparison.OrdinalIgnoreCase);
}
}
}
上面的示例是为演示目的而编写的,更好的实现应该为每个被调用的域关联多个键。
【讨论】:
虽然您可以使用证书本身来执行验证并固定证书,但还有其他选择。
根据OWASP documentation here,您可以实现以下三种方法中的任何一种:
证书
证书最容易固定。您可以获取 网站带外证书,让 IT 人员通过电子邮件发送您的 公司证书给你,使用 openssl s_client 检索 证书等。当证书到期时,您将更新您的 应用。假设您的应用程序没有错误或安全性 缺陷,应用程序将每两年更新一次。在 运行时,您检索网站或服务器的证书 打回来。在回调中,您比较检索到的证书 将证书嵌入程序中。如果比较 失败,然后使方法或函数失败。
固定证书有一个缺点。如果网站轮换 定期证书,那么您的申请需要 定期更新。例如,谷歌轮换其证书,所以 您将需要大约每月更新一次您的应用程序(如果 依赖于谷歌服务)。尽管谷歌轮换 证书,基础公钥(在证书内) 保持静止。
公钥
公钥固定更灵活,但由于 从证书中提取公钥所需的额外步骤。作为 使用证书,程序检查提取的公钥 其嵌入的公钥副本。有两个缺点二 公钥固定。首先,使用键更难(相对于 证书),因为您通常必须从 证书。提取是 Java 和 .Net 中的一个小不便, 但它在 Cocoa/CocoaTouch 和 OpenSSL 中不舒服。二、 密钥是静态的,可能违反密钥轮换政策。
散列
虽然上面三个选择使用了DER编码,但也可以接受 使用信息的散列(或其他转换)。事实上, 原始示例程序是使用摘要证书编写的,并且 公钥。更改了样本以允许程序员检查 使用 dumpasn1 和其他 ASN.1 解码器等工具的对象。
散列还提供了三个额外的好处。首先,散列允许 您可以匿名化证书或公钥。这可能很重要 如果您的应用程序担心在 反编译和重新设计。
其次,经过消化的证书指纹通常可用作 许多库的原生 API,因此使用起来很方便。
最后,组织可能想要提供储备(或备用) 身份,以防主要身份被泄露。散列确保 您的对手看不到保留的证书或公钥 提前使用。事实上,谷歌的 IETF 草案 websec-key-pinning 使用该技术。
我强烈建议使用散列方法,这意味着当您验证传入的证书时,您只需要检查来自服务器的证书的散列值是否符合您的预期。类似于以下内容:
private bool ValidateServerCertificate(object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
// Make sure we have a certificate to check.
if (certificate == null)
{
return false;
}
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
return this.KnownKeys.Contains(certificate.GetCertHashString(),
StringComparer.Ordinal);
}
KnownKeys 是一个简单的编译时定义的已知证书哈希数组:
private readonly string[] KnownKeys = new[]
{
"INSERT HASH",
"AND A SECOND IF REQUIRED"
};
【讨论】: