我的机器上有两种类型的证书,一种是A1,另一种是A3,当将其中一种加载到X509Certificate2
对象中时,如何以编程方式检测它是A1还是A3?
我了解如果未插入A3证书,则无法访问私钥。请注意两个证书都有效/已安装并插入。
我刚发现A1
和A3
类型是由特定的国家/地区法规(巴西)定义的,所以让我解释一下它们的区别:
ICP-Brasil允许8种类型的数字证书,分为2个系列(A和S)。
A系列(A1,A2,A3和4)由数字签名证书组成,用于Web身份验证,电子邮件,虚拟专用网络(VPN)和电子文档,并验证其完整性 信息。
S系列(S1,S2,S3和S4)包括机密性证书,用于编码文件,数据库,消息和其他机密电子信息。这八种类型根据使用,安全级别和有效性进行区分 (Gisele Ribeiro,Source)
因此,为了更新我的问题,我希望检测证书是否来自具有密钥生成功能的智能卡。
答案 0 :(得分:5)
据推测,你的A1和A3命名法是关于巴西标准(e-CPF / e-CNPJ /类似的东西)。据我所知,这些术语意味着:
(我真的很好奇A2是什么,但我离题了。)
从技术上讲,证书不知道密钥的存在位置。因此,证书不知道其私钥(无论在哪里)是基于硬件还是软件。但是,基于http://www.bcb.gov.br/sfn/ced/ManualdeSeguran%C7adaRSFN-v32.pdf和http://oid-info.com/get/2.16.76.1.2,看起来您可以按照以下方式执行操作:
private static bool IsBrazilA1Certificate(X509Certificate2 cert)
{
// End with the "." so it matches on children, but not that OID.
return HasParentEku(cert, "2.16.76.1.2.1.");
}
private static bool IsBrazilA3Certificate(X509Certificate2 cert)
{
// End with the "." so it matches on children, but not that OID.
return HasParentEku(cert, "2.16.76.1.2.3.");
}
private static bool HasParentEku(X509Certificate2 cert, string oidFragment)
{
var ekuExtension = (X509EnhancedKeyUsageExtension) cert.Extensions["2.5.29.37"];
if (ekuExtension == null)
{
return false;
}
foreach (Oid eku in ekuExtension.EnhancedKeyUsages)
{
if (eku.Value.StartsWith(oidFragment))
{
return true;
}
}
return false;
}
由于我没有巴西A1或A3证书,我无法对此进行测试,但这是我能从描述中得到的最好的。否则你会问到这是否有私钥?" (cert.HasPrivateKey
)和"是硬件支持的私钥?" (一个更难的问题)。
编辑:上述代码并未遵循EKU验证的正常规则,这一点毫无价值。通常,根本没有EKU扩展名的证书被视为具有所有EKU。但是,由于您正在明确查看根据巴西A1或A3政策创建的内容,因此它与您请求的内容相匹配。 (此外,它是我见过任何必须使用基于StartsWith的规则进行验证的唯一时间,通常策略是特定的EKU OID)