NET中如何操作数字证书详解

.NET为我们提供了操作数字证书的两个主要的类,分为为:

System.Security.Cryptography.X509Certificates.X509Certificate2类, 每个这个类的实例可以表示一个证书;

System.Security.Cryptography.X509Certificates.X509Store类,可以对保存在计算机安全区域内的证书进行add/remove/get操作。

另外我们可以使用System.Security.Cryptography.X509Certificates.X509Certificate2UI类来显示证书消息的对话框,它就是在IE中的证书查看器的.NE实现。

生成证书

在介绍以上类的使用方法之前,我们先要拥有一个数字证书,获取数字证书有三种方法,一是从CA机构申请,二是自己搭建服务器发布证书,三是使用makecert.exe来生成一个证书文件。这里我们使用makecert.exe来生成一个证书文件,用来测试。启动VS2010的命令行,输入对应参数,生成名为TestCertificates的证书文件。如图6-28所示。

图6-28 生成证书

makecert.exe的参数读者可以查看帮助,这里只解释图6-28中的参数。

参数说明:

-sr CurrentUser:指定主题的证书存储位置。Location 可以是 currentuser(默认值)或 localmachine

-ss MyTestContainer:指定主题的证书存储名称,输出证书即存储在那里。

-n CN=TestCert:指定主题的证书名称。此名称必须符合 X.500 标准。最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,"CN=myName"。

-sky exchange:指定颁发者的密钥类型,必须是 signature、exchange 或一个表示提供程序类型的整数。默认情况下,可传入 1 表示交换密钥,传入 2 表示签名密钥。

-pe:将所生成的私钥标记为可导出。这样可将私钥包括在证书中。

生成的密钥文件被保存在了我们指定的MyTestContainer中,但到哪去查看我们的证书呢?Windows没有给我们准备好直接的管理证书的入口,但我们可以在MMC控制台自行添加。

  1. 开始 ? 运行 ? MMC,打开一个空的MMC控制台。
  2. 在控制台菜单,文件 ? 添加/删除管理单元 ? 添加按钮 ? 选"证书" ? 添加 ? 选"我的用户账户" ? 关闭 ? 确定
  3. 在控制台菜单,文件 ? 添加/删除管理单元 ? 添加按钮 ? 选"证书" ? 添加 ? 选"计算机账户" ? 关闭 ? 确定

如图6-29,我们可以查看两个账户的证书管理,在我的账户中可以看到MyTestContainer下的证书TestCert。

图6-29 在MMC控制台查看和管理证书

当然我们也可以将证书文件保存为文件,如图6-30所示。

图6-30 将证书保存为文件

打开E盘,可以看到生成的证书文件。如图6-31所示。

图6-31 生成的证书文件

将证书保存为文件时,我们有三种选择:

  1. 带有私钥的证书

    由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。

  2. 二进制编码的证书

    证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。

  3. Base64编码的证书

    证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。

右键单击本地的证书文件,我们可以看到安装选项,可以把该证书文件安装到证书存储区。也可在MMC的证书管理台上执行导出任务将存储区的证书导出为文件。这里就不再演示了,读者可以自行实践。

编程操作证书

我们可以通过编程的方式操作操作本地的证书文件和在存储区中的证书。我们以刚才保存在E盘的test.cer文件为例,讲解如何读取本地的证书文件,并将它添加到存储区中。先看代码清单6-17。

代码清单 6-17 操作本地证书文件

  1. class OperCert
  2. {
  3. internal static byte[] ReadFile(string fileName)
  4. {
  5. FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
  6. int size = (int)f.Length;
  7. byte[] data = new byte[size];
  8. size = f.Read(data, 0, size);
  9. f.Close();
  10. return data;
  11. }
  12. static void Main(string[] args)
  13. {
  14. try
  15. {
  16. X509Certificate2 x509 = new X509Certificate2();
  17. byte[] rawData = ReadFile(@"e:\test.cer");
  18. x509.Import(rawData);
  19. Console.WriteLine("{0}Subject: {1}{0}", Environment.NewLine, x509.Subject);
  20. Console.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine, x509.Issuer);
  21. Console.WriteLine("{0}Version: {1}{0}", Environment.NewLine, x509.Version);
  22. Console.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine, x509.NotBefore);
  23. Console.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine, x509.NotAfter);
  24. Console.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine, x509.Thumbprint);
  25. Console.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine, x509.SerialNumber);
  26. Console.WriteLine("{0}Friendly Name: {1}{0}", Environment.NewLine, x509.PublicKey.Oid.FriendlyName);
  27. Console.WriteLine("{0}Public Key Format: {1}{0}", Environment.NewLine, x509.PublicKey.EncodedKeyValue.Format(true));
  28. Console.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine, x509.RawData.Length);
  29. Console.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine, x509.ToString(true));
  30. Console.WriteLine("{0}Certificate to XML String: {1}{0}", Environment.NewLine, x509.PublicKey.Key.ToXmlString(false));
  31. X509Store store = new X509Store();
  32. store.Open(OpenFlags.MaxAllowed);
  33. store.Add(x509);
  34. store.Close();
  35. }
  36. catch (Exception e)
  37. {
  38. Console.WriteLine("Error:"+e.Message);
  39. }
  40. }
  41. }

代码清单6-17演示了如何读取本地证书文件的方法。静态方法ReadFile用来从本地磁盘中读取证书文件到byte数组中。主要的操作都在Main方法中。X509Certificate2 x509 = new X509Certificate2()一句使用无参数的构造函数初始化X509Certificate2类的实例x509。然后我们使用x509.Import(rawData)语句将byte数组导入到当前证书实例。接下来是输出该证书的信息。

输出信息之后,我们看下面的四行代码:

  1. X509Store store = new X509Store();
  2. store.Open(OpenFlags.MaxAllowed);
  3. store.Add(x509);
  4. store.Close();

首先我们初始化一个X509Store类的实例store,然后使用Open方法打开存储区,添加上面读取的证书到存储区。

X509Certificate2一共提供了14个构造函数供我们使用,这里就不一一介绍了。我们也可以通过X509Certificate2类的构造函数直接导入本地的证书文件,可以使用代码清单6-18所示的方式。

代码清单6-18 使用构造函数导入证书文件

  1. X509Certificate2 myX509Certificate2 = new X509Certificate2(
  2. @"e:\MyTestCert.pfx", //证书路径
  3. "password", //证书的私钥保护密码
  4. X509KeyStorageFlags.Exportable //表示此证书的私钥以后还可以导出
  5. );

代码清单6-18给出了如何导入带私钥保护密码的证书的方法。X509KeyStorageFlags 枚举用来标识X.509 证书的私钥导出到何处以及如何导出。该枚举的成员说明如表6-1所示。

表6-1 X509KeyStorageFlags 枚举说明


成员名称


说明


DefaultKeySet


使用默认的密钥集。用户密钥集通常为默认值。


UserKeySet


私钥存储在当前用户存储区而不是本地计算机存储区。既使证书指定密钥应存储在本地计算机存储区,私钥也会存储到当前用户存储区。


MachineKeySet


私钥存储在本地计算机存储区而不是当前用户存储区。


Exportable


导入的密钥被标记为可导出。


UserProtected


通过对话框或其他方法,通知用户密钥被访问。使用的加密服务提供程序 (CSP) 定义确切的行为。


PersistKeySet


导入证书时会保存与 PFX 文件关联的密钥。

那么如何操作存储区中的证书呢,可以使用代码清单6-19的方式。

代码清单6-19 操作存储区中的证书

  1. X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
  2. store.Open(OpenFlags.ReadOnly);
  3. //轮询存储区中的所有证书
  4. foreach(X509Certificate2 myX509Certificate2 in store.Certificates)
  5. {
  6. //将证书的名称跟要导出的证书MyTestCert比较,找到要导出的证书
  7. if (myX509Certificate2.Subject == "CN=TestCert")
  8. {
  9. //证书导出到byte[]中,password为私钥保护密码
  10. byte[] CertByte = myX509Certificate2.Export(X509ContentType.Pfx,"password");
  11. //将证书的字节流写入到证书文件
  12. FileStream fStream = new FileStream(
  13. @"C:\Samples\PartnerAEncryptMsg\MyTestCert_Exp.pfx",
  14. FileMode.Create,
  15. FileAccess.Write);
  16. fStream.Write(CertByte, 0, CertByte.Length);
  17. fStream.Close();
  18. }
  19. }
  20. store.Close();

代码清单6-19首先声明X509Store类的实例store,使用了两个参数的构造函数,第一个参数是存储容器的名称,StoreName枚举只能枚举系统默认的存储区名称。第二个参数是StoreLocation枚举,用来标识是本机证书还是当前用户证书。导出容器证书使用的是Export方法。第一个参数X509ContentType.Pfx表示要导出为含有私钥的pfx证书形式,第二个参数为私钥保护密码。如果要导出为不含私钥的cer证书,第一个参数使用X509ContentType.Cert,表示导出为不含私钥的cer证书,也就不需要密码了。

创建发行者证书

发行者证书是验证发行者可靠性的证书文件,保护证书发行者的签名。我们可以从证书颁发机构获得该文件。做为程序测试,我们可以使用Cert2spc.exe来生成发行者证书。从命令行启动该程序,如图6-32所示。

图6-32 生成SPC文件

如图6-32,我们使用Cert2spc.exe以test.cer为参数生成目标为tset.spc的发行者证书,如果存在多个证书文件,可以作为参数以空格隔开生成统一的发行者证书。

使用证书对文件签名

签名工具 (SignTool.exe) 是一个命令行工具,用于对文件进行数字签名,验证文件或时间戳文件中的签名。我们可以对cab文件、dll文件或者其他文件进行签名,从互联网访问这些文件的时候就需要安装和验证证书。该工具详细的说明读者可以从MSDN上找到,我就不在重复了。

时间: 2024-11-11 07:32:37

NET中如何操作数字证书详解的相关文章

公钥,私钥,数字签名,数字证书详解

鲍勃有两把钥匙,一把是公钥,另一把是私钥. 鲍勃把公钥送给他的朋友们----帕蒂.道格.苏珊----每人一把. 苏珊要给鲍勃写一封保密的信.她写完后用鲍勃的公钥加密,就可以达到保密的效果. 鲍勃收信后,用私钥解密,就看到了信件内容.这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密. 鲍勃给苏珊回信,决定采用"数字签名".他写完后先用Hash函数,生成信件的摘要(digest). 然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"

iOS开发者证书-详解

iOS开发者证书-详解/生成/使用 本文假设你已经有一些基本的Xcode开发经验, 并注册了iOS开发者账号. 相关基础 加密算法 现代密码学中, 主要有两种加密算法: 对称密钥加密 和 公开密钥加密. 对称密钥加密 对称密钥加密(Symmetric-key algorithm)又称为对称加密, 私钥加密, 共享密钥加密. 这类算法在加密和解密时使用相同的密钥. 例如: 最常见的应用场景 - 系统登陆. 要成功登陆系统, 你必须输入正确的密码, 这密码是唯一的, 是与创建时一样的. 同样 的,

**Python中的深拷贝和浅拷贝详解

Python中的深拷贝和浅拷贝详解 这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容. 要说清楚Python中的深浅拷贝,需要搞清楚下面一系列概念: 变量-引用-对象(可变对象,不可变对象)-切片-拷贝(浅拷贝,深拷贝) [变量-对象-引用] 在Python中一切都是对象,比如说:3, 3.14, 'Hello', [1,2,3,4],{'a':1}...... 甚至连type其本身都是对象,type对象 Python中变量与C/

php中的PDO函数库详解

PHP中的PDO函数库详解 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,PDO更高效.目前而言,实现“数据库抽象层”任重而道远,使用PDO这样的“数据库访问抽象层”是一个不错的选择. PDO中包含三个预定义的类 PDO中包含三个预定义的类,它们分别是 PDO.PDOStatement 和 PDOException. 一.PDO PDO->beginTransaction(

好程序员web前端分享html中meta标签及用法详解

好程序员web前端分享html中meta标签及用法详解,这篇文章给大家介绍了html中meta标签及用法详解,感兴趣的朋友一起看看,Html中meta标签一.meta标签 含义 <meta> 元素 可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词. <meta> 标签位于文档的头部,不包含任何内容. <meta> 标签的属性定义了与文档相关联的名称/值对.二.meta 中常用属性 charset? (字符集) 说明:规

JDK中的Timer和TimerTask详解

目录结构: Timer和TimerTask 一个Timer调度的例子 如何终止Timer线程 关于cancle方式终止线程 反复执行一个任务 schedule VS. scheduleAtFixedRate 一些注意点 1. Timer和TimerTask Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务. 2.

Android总结篇系列:Activity中几个主要函数详解

专注Android领域开发. 仰望星空,同时需要脚踏实地. ——好记性不如烂博客 Android总结篇系列:Activity中几个主要函数详解 Activity作为Android系统中四大基本组件之一,包含大量的与其他的各大组件.intent.widget以及系统各项服务等之间的交互的函数.在此,本文主要选取实际项目开发中常用的,但完全理解又需要有一定深入了解的几个函数进行讲解,后续本文会根据需要不断更新. 1. startActivityForResult / onActivityResult

Oracle中常用的to_Char用法详解

Oracle中常用的to_Char用法详解(有FMT的详细列表) The following are number examples for the to_char function. to_char(1210.73, '9999.9') would return '1210.7' to_char(1210.73, '9,999.99') would return '1,210.73' to_char(1210.73, '$9,999.00') would return '$1,210.73'

Swift使用WKWebView在iOS应用中调用Web的方法详解

这篇文章主要介绍了Swift使用WKWebView在iOS应用中调用Web的方法详解,使用WKWebView便等于使用和Safari中相同的JavaScript解释器,用来替代过去的UIWebView,需要的朋友可以参考下 自从iOS8开始,Apple引入了WKWebView欲代替UIWebView.相比而言,WKWebView消耗内从更少,功能也更加强大.让我们来看看WKWebView怎么使用吧! 0.初始化(1)首先需要引入WebKit库 复制代码代码如下: #import <WebKit/