如何检测证书类型(A1或A3)?

时间:2017-01-05 18:59:02

标签: c# .net-4.0 certificate x509certificate2

我的机器上有两种类型的证书,一种是A1,另一种是A3,当将其中一种加载到X509Certificate2对象中时,如何以编程方式检测它是A1还是A3?

我了解如果未插入A3证书,则无法访问私钥。请注意两个证书都有效/已安装并插入。

修改

我刚发现A1A3类型是由特定的国家/地区法规(巴西)定义的,所以让我解释一下它们的区别:

ICP-Brasil允许8种类型的数字证书,分为2个系列(A和S)。

  

A系列(A1,A2,A3和4)由数字签名证书组成,用于Web身份验证,电子邮件,虚拟专用网络(VPN)和电子文档,并验证其完整性   信息。
  S系列(S1,S2,S3和S4)包括机密性证书,用于编码文件,数据库,消息和其他机密电子信息。这八种类型根据使用,安全级别和有效性进行区分   (Gisele Ribeiro,Source

Types of certificate

因此,为了更新我的问题,我希望检测证书是否来自具有密钥生成功能的智能卡。

1 个答案:

答案 0 :(得分:5)

据推测,你的A1和A3命名法是关于巴西标准(e-CPF / e-CNPJ /类似的东西)。据我所知,这些术语意味着:

  • A1:软件私钥
  • A3:硬件私钥

(我真的很好奇A2是什么,但我离题了。)

从技术上讲,证书不知道密钥的存在位置。因此,证书不知道其私钥(无论在哪里)是基于硬件还是软件。但是,基于http://www.bcb.gov.br/sfn/ced/ManualdeSeguran%C7adaRSFN-v32.pdfhttp://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)