在本文中,将探讨如何将智能卡证书集成到.NET应用程序中。这包括从创建证书到在智能卡中选择证书,并使用它执行PKCS11签名的步骤。为了应用这些概念,需要一个PKI(公钥基础设施)智能卡。如今,这些设备非常实惠,可以从Gemalto等供应商那里以不到80美元的价格获得一个智能卡和读卡器。
本文不会展示可以用PKI基础设施做什么,而是展示如何轻松地(当知道如何做时...)在.NET和C#中使用智能卡PKI设备。那些有PKCS#11库经验的人会明白意思!
本文中代码不多,因为大部分工作都是由框架本身完成的。然而,本文集中介绍了在将智能卡用于企业应用程序数据库许可时学到的许多技巧。
第一步是生成PFX证书,这是大多数智能卡实用程序用来在卡上安装证书的格式。当知道步骤时,这是一个相对简单的过程。重要的是,必须导出私钥。经过几次搜索,找到了一个简短但非常有用的页面,提供了解决方案,可以在这里找到它。
将需要3个实用程序:
makecert和cert2spc随Microsoft SDKs提供,可以在"Program Files\Microsoft SDKs\Windows"中找到。pvkimprt是Microsoft Office实用程序,可以从Microsoft网站下载。
在DOS shell中,需要输入以下命令(在设置正确的路径之后):
makecert -r -n "CN=CodeProject" -b 01/01/2000 -e 01/01/2099 -eku 1.3.6.1.5.5.7.3.3 -sv smartcert.pvk smartcert.cer
cert2spc smartcert.cer smartcert.spc
pvkimprt -pfx smartcert.spc smartcert.pvk
这将生成需要使用的2个文件,smartcert.cer只包含公钥(尽管可以包含私钥),而smartcard.pfx是完整的RSA密钥对,受密码保护,因为私钥是证书最敏感的部分。生成完成后,系统会提示输入密码。
在这里不会描述这个框架,因为可以在WEB上找到很多好文章。需要知道的是,这个框架可以节省大量的代码和负担,以便将PKI智能卡集成到.NET应用程序中。在BaseCSP和minidriver架构之前,需要使用PKCS#11并编写大量的互操作代码。现在,唯一需要做的是使用适合智能卡的正确CSP(Crypto Service Provider)。
当安装智能卡的驱动程序时,供应商将提供必要的库,这些库集成在这个框架中。然而,即使在CSP架构中,也有两种方法,这取决于供应商的实现有多新。第一种CSP架构将要求供应商编写一个完整的CSP提供者,而使用新的BaseCSP架构,供应商将只编写一个位于BaseCSP下方的minidriver。
接下来,需要将PFX证书安装到智能卡中。任何智能卡供应商都会提供一个简单的实用程序来完成这个任务。在这里不是谈论证书管理,这远远超出了这个话题的范围,而是一个简单的Windows或WEB实用程序,用于将证书上传到卡上,这应该接受PFX文件,因为这是交换证书的标准。当导入PFX文件时,系统会提示输入创建证书时输入的证书密码,以及容器名称。容器名称是用来选择证书的名称。
现在开始编码!首先,需要找出卡使用哪个CSP。就像之前提到的,如果卡支持新的BaseCSP,那么将引用标准智能卡CSP(Microsoft Base Smart Card Crypto Provider),如果卡是较旧的一代,可能需要使用供应商特定的CSP,例如Gemplus GemSafe卡将使用"Gemplus GemSAFE Card CSP v1.0"。
这些值可以在注册表中的以下位置找到:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
现在知道要使用哪个CSP,让开始编码。以下行创建了一个CspParameters类,它将链接到智能卡证书。为了选择正确的证书,有两个关键参数,即CSP名称和容器名称。最后一个参数是在使用卡中的证书时需要输入的PIN码,基本上是一个4位PIN码,就像SIM卡或银行卡一样。
CspParameters csp = new CspParameters(
1,
"Microsoft Base Smart Card Crypto Provider",
"Codeproject_1",
new System.Security.AccessControl.CryptoKeySecurity(),
pwd);
现在已经将CSP连接到智能卡,可以使用证书来签名一些数据。当然,签名的目的是验证签名。数字签名的原理是用私钥签名一些数据,信息接收者将使用可以分发的公钥来验证签名。
不会深入签名机制,因为CodeProject上已经有很多关于这个主题的文章,而且WEB上还有很多更多。只想指出,证书是一个信任资产,要被信任,它需要由一个可信的方发行,这就是像Verisign或RSA这样的公司发挥作用的地方。事实上,这完全取决于需要的信任水平。如果想将证书用于个人使用,那么可以使用这些实用程序创建自签名证书,可以将其分发给朋友。
为了验证,需要证书的公钥。一个简单的方法是使用刚刚创建的CspParameters创建一个RSACryptoServiceProvider,然后使用ToXmlString(false)方法将公钥导出为XML格式。然后在验证签名的程序中,只需使用FromXmlString(xmlKey)方法创建RSACryptoServiceProvider的密钥,并使用这个CSP实例来验证签名。
提供的完整代码使用智能卡证书签名一些数据,并使用公钥的XML表示来验证签名。
在真正的安全环境中,会分发.CER文件,例如,它只包含公钥,并将其安装在接收者证书存储中。
最近通过在Windows 7上与IIS7托管的WCF服务访问卡上的证书,遇到了一个独特的问题。当调用服务时,收到一条消息,告诉智能卡管理器没有运行。从应用程序访问卡完全正常工作,所以猜测当代码由IIS进程执行时,有什么东西阻止了卡。
发现一些帖子上说,.NET框架调用的SCard API在访问卡时失败了,出现了E_ACCESS_DENIED错误。一个有趣的帖子解释说,由于UAC和Windows 7和Windows Server 2008的扩展安全性,旧的智能卡API现在在从NT服务或与IIS托管的WCF服务调用时失败了(还没有尝试过在Windows服务中托管的,但结果是可以预测的)。
解决方案是使用授权API更改访问权限,以授予智能卡资源管理器对所有人的访问权限!这个解决方案的唯一问题是它需要在每次机器重启时应用。一个简单的解决方案是在注册表键下创建一个字符串:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
包括一个简短的C代码片段,在MSDN上找到的,它完成了这项工作。
然后是Windows Server 2008的情况...
授权代码将在Windows 2008上工作,
ONLY
如果机器在域中。到目前为止,找不到任何解释(即使在MSDN论坛上提问),但经验表明,如果在不在域的服务器2008上运行此代码,GetNamedSecurityInfo调用返回5(访问被拒绝),不能给SC资源管理器访问权限。
当然,这段代码不仅在需要访问智能卡证书时有用,而且在任何需要从Windows服务或WEB服务访问智能卡资源的情况下都有用。
阅读本文后,应该能够使用Microsoft最新的CSP框架在.NET应用程序中使用智能卡证书。如果想进一步了解可以用PKI做什么,建议浏览CodeProject Cryptography & Security文章,那里有很多有趣的主题!