.Net应用程序证书的使用方法证书在Microsoft®.NETFramework中应用十分广泛,从安全通信到代码签名再到安全策略。.NETFramework2.0改进了对证书的支持,为使用证书进行符合标准的加密操作添加了一个全新的命名空间。在本文中,我将讨论证书和Windows®证书存储区的背景知识。同时我还会为您介绍证书API的使用方法和Framework如何使用这些API实现安全功能。“证书”实际上是一种ASN.1(AbstractSyntaxNotationOne)编码的文件,它包含一个公钥和其他有关该密钥及其所有者的信息。另外,证书具有有效期,并通过另一密钥(所谓的颁发者)进行签名,该密钥能保证这些属性的真实性,最重要的是,保证公钥本身的真实性。您可以将ASN.1看成是一种二进制XML。与XML一样,它也具有编码规则、强类型和标记;但是,这些都是二进制值,通常没有可打印字符与之对应。要使这种文件能够在系统之间互换,需要一种标准的格式。这种标准格式即X.509(当前为第3版),RFC3280(tools.ietf.org/html/rfc3280)中对其进行了描述。虽然X.509并未规定证书中嵌入的密钥类型,但RSA算法是目前使用最为普遍的非对称加密算法。首先让我们回顾一下这种算法的历史由来。“RSA”这一名称是发明该算法的三个人的姓氏首字母缩写:RonRivest、AdiShamir和LenAdleman。他们成立了一家名为RSASecurity的公司,该公司发布了几个名为公钥加密标准(PKCS)的标准文档。这些文档对加密技术的几个方面进行了介绍。其中最流行的文档之一,即PKCS#7,为已签名和加密的数据定义了一种名为加密消息语法(CMS)的二进制格式。目前CMS广泛应用于众多流行的安全协议,其中包括安全套接字层(SSL)和安全多用途Internet邮件扩展(S/MIME)。由于它是一种标准,因此当应用程序需要在几方之间交换已签名和加密的数据时,它也是一种可供选择的格式。您可以从RSALaboratories网站(=2124)获得这些PKCS文档。如何获得一个证书目前有几种方法可以获取证书。在交换文件时,证书通常以两种格式之一出现。扩展名为.cer的文件是采用X.509v3格式的已签名ASN.1文件。这些文件中包含着我之前提到的一个公钥和额外的信息。您要将这些文件中包含的内容提供给业务合作伙伴或朋友,以便他们能够使用公钥为您加密数据。此外,您可能会遇到扩展名为.pfx(个人信息交换,PersonalInformationExchange)的文件。.pfx文件包含一个证书和与之对应的私钥(PKCS#12标准对该格式有所说明)。这类文件是高度敏感的,通常用于导入服务器上的密钥对或用于备份目的。在导出密钥对时,Windows提供用密码加密.pfx文件;而在导入密钥对时,您必须再次提供此密码方可导入。您还可以生成自己的证书。证书的生成方式通常取决于其使用方式。在对等方身份不明的常规Internet环境下,您通常要向某个商业证书颁发机构(CA)申请证书。该方法的优点在于这些已知的CA已经得到Windows和其他任何支持证书及SSL的OS(包括浏览器)的信任。因此不必进行CA密钥的交换。对于B2B和Intranet环境,您可以使用内部CA。Windows2000和WindowsServer®2003中包含了证书服务。配合ActiveDirectory®一起使用,此功能允许您在组织内轻松地分发证书。(稍后我将介绍如何从私有CA申请证书。)在开发过程中,有时您可能会发现,刚才提到的方法不起作用了。例如,如果您出于测试的需要希望很快获得一个证书,可以使用makecert.exe。该工具包随附于.NETFrameworkSDK中,能够生成证书和密钥对。在IIS资源工具包中也有一个与之类似的名为selfssl.exe的工具。它专门用于创建SSL密钥对,而且使用这种密钥,只需一个步骤即可对IIS进行配置。Windows证书存储区证书和与之对应的私钥可存储在各种设备上,例如硬盘、智能卡和USB令牌。Windows提供了一个名为证书存储区的抽象层,用于统一证书的访问方式,不管这些证书存储在何处。只要硬件设备具有Windows支持的加密服务提供程序(CSP),就可以使用证书存储区API访问其上存储的数据。证书存储区位于用户配置文件的深处。这样就可以对特定帐户的密钥使用ACL。每个存储区被划分为若干个容器。例如,其中有一个名为Personal的容器,您可以将自己的证书(具有关联私钥的证书)存储在其中。TrustedRootCertificationAuthorities容器包含了所有您信任的CA的证书。OtherPeople容器则保存着与您进行安全通信的人员的证书。此外还有其他一些证书。访问证书存储区最简单方法是运行certmgr.msc。另外还有一个供Windows计算机帐户(NETWORK、LOCALSERVICE和LOCALSYSTEM)使用的计算机范围的存储区,如果您希望跨帐户共享证书或密钥,可以使用该存储区。ASP.NET应用程序总是使用计算机存储区;而对于桌面应用程序,证书通常安装在用户存储区。只有管理员才能对计算机存储区和服务帐户存储区进行管理。要实现这一目的,您必须启动Microsoft管理控制台(mmc.exe)并添加“证书”管理单元,从中可以选择要管理的存储区。图1显示了MMC管理单元的一个屏幕快照。图1“证书”MMC管理单元(单击该图像获得较大视图)除了可以导入、导出和搜索证书外,您还可以通过管理单元从内部企业CA申请证书。只需右键单击Personal容器并选择AllTasks|RequestCertificate。本地计算机会随后生成一个RSA密钥对,并将公钥部分发送给CA以进行签名。Windows将已签名的证书添加到证书存储区,并将对应的私钥添加到密钥容器。证书通过存储属性被链接到密钥容器。对于对应帐户或LOCALSYSTEM,私钥容器受到ACL的严密保护。当您要从ASP.NET或其他用户帐户访问计算机配置文件中存储的密钥时,这就成为一个问题。为此我编写了一个工具,您可以用它修改容器文件的ACL(可从下载该工具)。商业CA和WindowsCA还为申请证书提供了Web界面。通常在这些时候,由InternetExplorer®中的ActiveX®控件生成密钥并将其导入当前用户的存储区中。按照惯例,当您想指定某个证书可以由某个用户或服务访问时,有以下两种选择:一是将该证书导入该用户的存储区,二是在以该用户身份登录时申请证书。使用证书证书可用于.NETFramework中的各个位置,而且在某种程度上此功能依赖于System.Security.X509Certificates命名空间中的X509Certificate类。如果您更仔细地观察,还会发现证书类是以2结尾。这是因为.NETFramework1.x具有一个名为X509Certificate的X.509证书表示形式。该类的功能有限,而且不支持加密操作。2.0版中新添加了一个名为X509Certificate2的类。该类派生自X509Certificate,同时添加了许多功能。您可以根据需要在二者之间来回转换,但无论何时都应尽可能使用最新版本。访问证书您可以直接从文件系统检索证书。但更好的办法是从证书存储区进行检索。要从一个.cer文件创建一个X509Certificate2实例,只需将文件名传递给构造函数即可:X509Certificate2cert1=newX509Certificate2(alice.cer);您也可以从.pfx文件加载证书。但是,如前所述,.pfx文件可以通过设置密码加以保护,因此您应当将该密码以SecureString的形式提供给他人。SecureString在内部对密码进行加密,并尽可能降低密码在内存、页面文件和崩溃转储期间的暴露几率。因此,您每次只能向字符串添加一个(值类型)字符。如果要从控制台要求用户提供密码,那么图2中的代码是非常有用的,这些代码可禁用控制台回显并返回SecureString。在“使用.NETFramework2.0进行加密管理”(可从msdn.microsoft.com/library/en-us/dnnetsec/html/credmgmt.asp获得)一文中,KennyKerr谈到了将常见Windows凭据对话框的结果转换为SecureString的代码。不管您以何种方式获得SecureString,它都可以随后被传递到X509Certificate2构造函数,以加载.pfx文件,如下所示:X509Certificate2cert2=newX509Certificate2(alice.pfx,password);要访问Windows证书存储区,请使用X509Store类。在其构造函数中,您要提供存储区位置(当前用户或计算机)和存储区名称。可以使用字符串或StoreName枚举来指定要打开的容器。注意,内部名称并不总是与MMC管理单元中找到的名称匹配。Personal容器映射到名称My,而OtherPeople则变为AddressBook。获得有效的X509Store实例后,就可以搜索、检索、删除和添加证书。除非在部署情况下,否则使用最为频繁的恐怕要数搜索功能。您可以按各种条件搜索证书,其中包括使用者名称、序列号、指纹、颁发者和有效期。如果以编程方式从存储区检索应用程序中的证书,则应当使用唯一的属性,例如接收者密钥标识符。指纹虽然也是唯一的,但要记住,它是证书的一个SHA-1哈希值,在诸如续订证书时会发生改变。图3中的代码显示了一种搜索证书的常规方法。在获得X509Certificate2的一个实例后,可以检查证书的各个属性(如使用者名称、到期日期、颁发者和友好名称)。HasPrivateKey属性会告知您是否存在关联私钥。PrivateKey和PublicKey属性将对应密钥作为一个RSACryptoServiceProvider实例返回。要导入证书,请对X509Store实例调用Add方法。当存储区的构造函数中不存在您所指定的存储区名称时,就会创建一个新容器。以下说明了如何将名为alice.cer的文件中的一个证书导入到名为Test的新容器中:staticvoidImportCert(){X509Certificate2cert=newX509Certificate2(alice.cer);X509Storestore=newX509Store(Test,StoreLocation.CurrentUser);try{store.Open(OpenFlags.ReadWrite);store.Add(cert);}finally{store.Close();}}显示证书详细信息和证书选择器Windows提供了两个标准对话框对证书进行操作:其中一个对话框用于显示证书的详细信息(各个属性和证书路径),另一个则供用户从列表中选择证书。您可以使用X509Certificate2UI类的两个静态方法访问这两个对话框:SelectFromCollection和DisplayCertificate。要显示证书列表,必须填充X509Certificate2Collection并将其传递给SelectFromCollection。让用户从存储区内的个人证书之一进行选择是很常见的。为此,只需传入一个已打开的X509Store的Certificates属性即可。您还可以控制对话框标题、消息以及是否允许多个选择。DisplayCertificate方法显示的对话框与在Windows资源管理器中双击.cer文件时看到