C#数字证书编程总结
生活随笔
收集整理的這篇文章主要介紹了
C#数字证书编程总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
.NET中如何操作數字證書詳解
http://blog.csdn.net/zjlovety/article/details/7252792
.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控制臺自行添加。
開始 ? 運行 ? MMC,打開一個空的MMC控制臺。
在控制臺菜單,文件 ? 添加/刪除管理單元 ? 添加按鈕 ? 選"證書" ? 添加 ? 選"我的用戶賬戶" ? 關閉 ? 確定
在控制臺菜單,文件 ? 添加/刪除管理單元 ? 添加按鈕 ? 選"證書" ? 添加 ? 選"計算機賬戶" ? 關閉 ? 確定
如圖6-29,我們可以查看兩個賬戶的證書管理,在我的賬戶中可以看到MyTestContainer下的證書TestCert。
在MMC控制臺查看和管理證書
圖6-29 在MMC控制臺查看和管理證書
當然我們也可以將證書文件保存為文件,如圖6-30所示。
將證書保存為文件
圖6-30 將證書保存為文件
打開E盤,可以看到生成的證書文件。如圖6-31所示。
生成的證書文件
圖6-31 生成的證書文件
將證書保存為文件時,我們有三種選擇:
帶有私鑰的證書
由Public Key Cryptography Standards #12,PKCS#12標準定義,包含了公鑰和私鑰的二進制格式的證書形式,以pfx作為證書文件后綴名。
二進制編碼的證書
證書中沒有私鑰,DER 編碼二進制格式的證書文件,以cer作為證書文件后綴名。
Base64編碼的證書
證書中沒有私鑰,BASE64 編碼格式的證書文件,也是以cer作為證書文件后綴名。
右鍵單擊本地的證書文件,我們可以看到安裝選項,可以把該證書文件安裝到證書存儲區。也可在MMC的證書管理臺上執行導出任務將存儲區的證書導出為文件。這里就不再演示了,讀者可以自行實踐。
編程操作證書
我們可以通過編程的方式操作操作本地的證書文件和在存儲區中的證書。我們以剛才保存在E盤的test.cer文件為例,講解如何讀取本地的證書文件,并將它添加到存儲區中。先看代碼清單6-17。
代碼清單 6-17 操作本地證書文件
class OperCert ?
{ ?
internal static byte[] ReadFile(string fileName) ?
{ ?
FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read); ?
int size = (int)f.Length; ?
byte[] data = new byte[size]; ?
size = f.Read(data, 0, size); ?
f.Close(); ?
return data; ?
} ?
static void Main(string[] args) ?
{ ?
try?
{ ?
X509Certificate2 x509 = new X509Certificate2(); ?
byte[] rawData = ReadFile(@"e:\test.cer"); ?
x509.Import(rawData); ?
Console.WriteLine("{0}Subject: {1}{0}", Environment.NewLine, x509.Subject); ?
Console.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine, x509.Issuer); ?
Console.WriteLine("{0}Version: {1}{0}", Environment.NewLine, x509.Version); ?
Console.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine, x509.NotBefore); ?
Console.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine, x509.NotAfter); ?
Console.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine, x509.Thumbprint); ?
Console.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine, x509.SerialNumber); ?
Console.WriteLine("{0}Friendly Name: {1}{0}", Environment.NewLine, x509.PublicKey.Oid.FriendlyName); ?
Console.WriteLine("{0}Public Key Format: {1}{0}", Environment.NewLine, x509.PublicKey.EncodedKeyValue.Format(true)); ?
Console.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine, x509.RawData.Length); ?
Console.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine, x509.ToString(true)); ?
Console.WriteLine("{0}Certificate to XML String: {1}{0}", Environment.NewLine, x509.PublicKey.Key.ToXmlString(false)); ?
X509Store store = new X509Store(); ?
store.Open(OpenFlags.MaxAllowed); ?
store.Add(x509); ?
store.Close(); ?
} ?
catch (Exception e) ?
{ ?
Console.WriteLine("Error:"+e.Message); ?
} ?
} ?
}?
代碼清單6-17演示了如何讀取本地證書文件的方法。靜態方法ReadFile用來從本地磁盤中讀取證書文件到byte數組中。主要的操作都在Main方法中。X509Certificate2 x509 = new X509Certificate2()一句使用無參數的構造函數初始化X509Certificate2類的實例x509。然后我們使用x509.Import(rawData)語句將byte數組導入到當前證書實例。接下來是輸出該證書的信息。
輸出信息之后,我們看下面的四行代碼:
X509Store store = new X509Store(); ?
store.Open(OpenFlags.MaxAllowed); ?
store.Add(x509); ?
store.Close();?
?
首先我們初始化一個X509Store類的實例store,然后使用Open方法打開存儲區,添加上面讀取的證書到存儲區。
X509Certificate2一共提供了14個構造函數供我們使用,這里就不一一介紹了。我們也可以通過X509Certificate2類的構造函數直接導入本地的證書文件,可以使用代碼清單6-18所示的方式。
代碼清單6-18 使用構造函數導入證書文件
X509Certificate2 myX509Certificate2 = new X509Certificate2( ?
@"e:\MyTestCert.pfx", //證書路徑 ?
"password", //證書的私鑰保護密碼 ?
X509KeyStorageFlags.Exportable //表示此證書的私鑰以后還可以導出 ?
);?
?
代碼清單6-18給出了如何導入帶私鑰保護密碼的證書的方法。X509KeyStorageFlags 枚舉用來標識X.509 證書的私鑰導出到何處以及如何導出。該枚舉的成員說明如表6-1所示。
表6-1 X509KeyStorageFlags 枚舉說明
成員名稱
說明
DefaultKeySet
使用默認的密鑰集。用戶密鑰集通常為默認值。
UserKeySet
私鑰存儲在當前用戶存儲區而不是本地計算機存儲區。既使證書指定密鑰應存儲在本地計算機存儲區,私鑰也會存儲到當前用戶存儲區。
MachineKeySet
私鑰存儲在本地計算機存儲區而不是當前用戶存儲區。
Exportable
導入的密鑰被標記為可導出。
UserProtected
通過對話框或其他方法,通知用戶密鑰被訪問。使用的加密服務提供程序 (CSP) 定義確切的行為。
PersistKeySet
導入證書時會保存與 PFX 文件關聯的密鑰。
那么如何操作存儲區中的證書呢,可以使用代碼清單6-19的方式。
代碼清單6-19 操作存儲區中的證書
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ?
store.Open(OpenFlags.ReadOnly); ?
//輪詢存儲區中的所有證書 ?
foreach(X509Certificate2 myX509Certificate2 in store.Certificates) ?
{ ?
//將證書的名稱跟要導出的證書MyTestCert比較,找到要導出的證書 ?
if (myX509Certificate2.Subject == "CN=TestCert") ?
{ ?
//證書導出到byte[]中,password為私鑰保護密碼 ?
byte[] CertByte = myX509Certificate2.Export(X509ContentType.Pfx,"password"); ?
//將證書的字節流寫入到證書文件 ?
FileStream fStream = new FileStream( ?
@"C:\Samples\PartnerAEncryptMsg\MyTestCert_Exp.pfx", ?
FileMode.Create, ?
FileAccess.Write); ?
fStream.Write(CertByte, 0, CertByte.Length); ?
fStream.Close(); ?
} ?
} ?
store.Close();?
?
代碼清單6-19首先聲明X509Store類的實例store,使用了兩個參數的構造函數,第一個參數是存儲容器的名稱,StoreName枚舉只能枚舉系統默認的存儲區名稱。第二個參數是StoreLocation枚舉,用來標識是本機證書還是當前用戶證書。導出容器證書使用的是Export方法。第一個參數X509ContentType.Pfx表示要導出為含有私鑰的pfx證書形式,第二個參數為私鑰保護密碼。如果要導出為不含私鑰的cer證書,第一個參數使用X509ContentType.Cert,表示導出為不含私鑰的cer證書,也就不需要密碼了。
創建發行者證書
發行者證書是驗證發行者可靠性的證書文件,保護證書發行者的簽名。我們可以從證書頒發機構獲得該文件。做為程序測試,我們可以使用Cert2spc.exe來生成發行者證書。從命令行啟動該程序,如圖6-32所示。
生成SPC文件
圖6-32 生成SPC文件
如圖6-32,我們使用Cert2spc.exe以test.cer為參數生成目標為tset.spc的發行者證書,如果存在多個證書文件,可以作為參數以空格隔開生成統一的發行者證書。
使用證書對文件簽名
簽名工具 (SignTool.exe) 是一個命令行工具,用于對文件進行數字簽名,驗證文件或時間戳文件中的簽名。我們可以對cab文件、dll文件或者其他文件進行簽名,從互聯網訪問這些文件的時候就需要安裝和驗證證書。該工具詳細的說明讀者可以從MSDN上找到,我就不在重復了。
========
C#中使用X509Certificate2類獲取數字證書頒發者和持有者的名稱信息
在 .NET Framework 中有一個名為 X509Certificate2 的類,使用該類包含的屬性可以方便地獲得 X.509 格式數字證書中的序列號、有效期起始日、有效期終止日等信息。在MSDN網站上可以查到關于該類的詳細說明。
在該類的屬性中,Issuer 和 IssuerName、Subject 和 SubjectName 這兩對看起來比較像,容易讓人混淆。這里做一下說明:
1) Issuer 和 Subject 屬性的類型都是 string,使用這兩個屬性,可以分別得到證書頒發者和證書持有者的 Distinguished Name。Distinguished Name 通常是一個類似下面形式的字符串:"CN=MyName, O=MyOrg, OU=MyOrgUnit, C=US"
這種字符串內部用 , 作為分隔符(注意是英文中的逗號,不是中文中的逗號),其中 CN 代表 Common Name,O 代表組織名,OU 代表組織下屬機構名,C 代表國家名。
2) IssuerName 和 SubjectName 屬性的類型都是 System.Security.Cryptography.X509Certificates.X500DistinguishedName,注意不是 string。X500DistinguishedName 有三個屬性,分別是:Name, Oid 和 RawData。使用 Name 屬性也可以獲得 Distinguished Name。即:
X509Certificate2.Issuer 與 X509Certificate2.IssuerName.Name 的值是相等的;
X509Certificate2.Subject 與 X509Certificate2.SubjectName.Name 的值是相等的。
對于證書頒發者或持有者的 Distinguished Name,經常被用到的部分是其中的 Common Name,即 CN= 后面的內容。但是 .NET Framework 中并沒有直接提供從 Distinguished Name 中提取出 Common Name 的方法。由于 Distinguished Name 的內部是用 , 來隔開不同含義的部分,于是就可以用 , 作為分隔符,將 Distinguished Name 拆分為多個子串,然后在子串中查找 CN= ,找到以后把 CN= 后面的部分提取出來,這樣就可以得到 Common Name 的值了。具體實現代碼如下:
/************************************************** ?
* Author: HAN Wei ?
* Author's blog: http://blog.csdn.net/henter/ ?
* Date: April 23rd, 2015
* Description: demonstrate how to extract Common Name?
* ? ? ? ? ? ? ?from Distinguished Name
**************************************************/
using System;
namespace ExtractCnFromDn
{
? ? class Program
? ? {
? ? ? ? public static string ExtractCommonNameFromDN(string DistinguishedName)
? ? ? ? {
? ? ? ? ? ? if (String.IsNullOrEmpty(DistinguishedName))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? throw new ArgumentNullException("Distinguishedname");
? ? ? ? ? ? }
? ? ? ? ? ? string strCommonName = string.Empty;
? ? ? ? ? ? bool bFoundSubStr = false;
? ? ? ? ? ? string strStartSubStr = "CN=";
? ? ? ? ? ? char[] chDelimiterChars = { ',' };
? ? ? ? ? ? string[] NameArray = DistinguishedName.Split(chDelimiterChars);
? ? ? ? ? ? int iNameLength;
? ? ? ? ? ? for (int i = 0; i < NameArray.Length; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? iNameLength = NameArray[i].Length;
? ? ? ? ? ? ? ? if (iNameLength > 3)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if (String.Compare(strStartSubStr, NameArray[i].Substring(0, 3), true) == 0)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? strCommonName = NameArray[i].Substring(3, (iNameLength - 3));
? ? ? ? ? ? ? ? ? ? ? ? bFoundSubStr = true;
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (bFoundSubStr == false)
? ? ? ? ? ? ? ? strCommonName = string.Empty;
? ? ? ? ? ? return strCommonName;
? ? ? ? }
? ? ? ? /*************************************************/
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? string strDn = "CN=測試人員, E=test@abc.com, S=上海市, C=CN"; /* 注意這里的 , 不是中文里的逗號 */
? ? ? ? ? ? string strCn = string.Empty;
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? strCn = ExtractCommonNameFromDN(strDn);
? ? ? ? ? ? }
? ? ? ? ? ? catch (ArgumentNullException e)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine("Error message: {0}", e.Message);
? ? ? ? ? ? ? ? Console.ReadLine();
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? Console.WriteLine("Distinguished name: {0}", strDn);
? ? ? ? ? ? Console.WriteLine("Common name: {0}", strCn);
? ? ? ? ? ? Console.ReadLine();
? ? ? ? ? ? return;
? ? ? ? }
? ? }
}
========
C#創建數字證書并導出為pfx,并使用pfx進行非對稱加解密
http://www.cnblogs.com/luminji/archive/2010/10/28/1863179.html
? ? ?本文源程序下載:http://download.csdn.net/source/2444494
? ? ?我的項目當中,考慮到安全性,需要為每個客戶端分發一個數字證書,同時使用數字證書中的公私鑰來進行數據的加解密。為了完成這個安全模塊,特寫了如下一個DEMO程序,該DEMO程序包含的功能有:
1:調用.NET2.0的MAKECERT創建含有私鑰的數字證書,并存儲到個人證書區;
2:將該證書導出為pfx文件,并為其指定一個用來打開pfx文件的password;
3:讀取pfx文件,導出pfx中公鑰和私鑰;
4:用pfx證書中的公鑰進行數據的加密,用私鑰進行數據的解密;
系統界面:
image
代碼如下:
01./// <summary> ??
02. ? ? ? ?/// 將證書從證書存儲區導出,并存儲為pfx文件,同時為pfx文件指定打開的密碼 ??
03. ? ? ? ?/// 本函數同時也演示如何用公鑰進行加密,私鑰進行解密 ??
04. ? ? ? ?/// </summary> ??
05. ? ? ? ?/// <param name="sender"></param> ??
06. ? ? ? ?/// <param name="e"></param> ??
07. ? ? ? ?private void btn_toPfxFile_Click(object sender, EventArgs e) ??
08. ? ? ? ?{ ??
09. ? ? ? ? ? ?X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ??
10. ? ? ? ? ? ?store.Open(OpenFlags.ReadWrite); ??
11. ? ? ? ? ? ?X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates; ??
12. ? ? ? ? ? ?foreach (X509Certificate2 x509 in storecollection) ??
13. ? ? ? ? ? ?{ ??
14. ? ? ? ? ? ? ? ?if (x509.Subject == "CN=luminji") ??
15. ? ? ? ? ? ? ? ?{ ??
16. ? ? ? ? ? ? ? ? ? ?Debug.Print(string.Format("certificate name: {0}", x509.Subject)); ??
17. ? ? ? ? ? ? ? ? ? ?byte[] pfxByte = x509.Export(X509ContentType.Pfx, "123"); ??
18. ? ? ? ? ? ? ? ? ? ?using (FileStream ?fileStream = new FileStream("luminji.pfx", FileMode.Create)) ??
19. ? ? ? ? ? ? ? ? ? ?{ ??
20. ? ? ? ? ? ? ? ? ? ? ? ?// Write the data to the file, byte by byte. ??
21. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < pfxByte.Length; i++) ??
22. ? ? ? ? ? ? ? ? ? ? ? ? ? ?fileStream.WriteByte(pfxByte[i]); ??
23. ? ? ? ? ? ? ? ? ? ? ? ?// Set the stream position to the beginning of the file. ??
24. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Seek(0, SeekOrigin.Begin); ??
25. ? ? ? ? ? ? ? ? ? ? ? ?// Read and verify the data. ??
26. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < fileStream.Length; i++) ??
27. ? ? ? ? ? ? ? ? ? ? ? ?{ ??
28. ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (pfxByte[i] != fileStream.ReadByte()) ??
29. ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ??
30. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Debug.Print("Error writing data."); ??
31. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return; ??
32. ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ??
33. ? ? ? ? ? ? ? ? ? ? ? ?} ??
34. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Close(); ??
35. ? ? ? ? ? ? ? ? ? ? ? ?Debug.Print("The data was written to {0} " + ??
36. ? ? ? ? ? ? ? ? ? ? ? ? ? ?"and verified.", fileStream.Name); ??
37. ? ? ? ? ? ? ? ? ? ?} ??
38. ? ? ? ? ? ? ? ? ? ?string myname = "my name is luminji! and i love huzhonghua!"; ??
39. ? ? ? ? ? ? ? ? ? ?string enStr = this.RSAEncrypt(x509.PublicKey.Key.ToXmlString(false), myname); ??
40. ? ? ? ? ? ? ? ? ? ?MessageBox.Show("密文是:" + enStr); ??
41. ? ? ? ? ? ? ? ? ? ?string deStr = this.RSADecrypt(x509.PrivateKey.ToXmlString(true), enStr); ??
42. ? ? ? ? ? ? ? ? ? ?MessageBox.Show("明文是:" + deStr); ??
43. ? ? ? ? ? ? ? ?} ??
44. ? ? ? ? ? ?} ??
45. ? ? ? ? ? ?store.Close(); ??
46. ? ? ? ? ? ?store = null; ??
47. ? ? ? ? ? ?storecollection = null; ??
48. ? ? ? ?} ??
49. ? ? ? ?/// <summary> ??
50. ? ? ? ?/// 創建還有私鑰的證書 ??
51. ? ? ? ?/// </summary> ??
52. ? ? ? ?/// <param name="sender"></param> ??
53. ? ? ? ?/// <param name="e"></param> ??
54. ? ? ? ?private void btn_createPfx_Click(object sender, EventArgs e) ??
55. ? ? ? ?{ ??
56. ? ? ? ? ? ?string MakeCert = "C:\\Program Files\\Microsoft Visual Studio 8\\SDK\\v2.0\\Bin\\makecert.exe"; ??
57. ? ? ? ? ? ?string x509Name = "CN=luminji"; ??
58. ? ? ? ? ? ?string param = " -pe -ss my -n \"" + x509Name + "\" " ; ??
59. ? ? ? ? ? ?Process p = Process.Start(MakeCert, param); ??
60. ? ? ? ? ? ?p.WaitForExit(); ??
61. ? ? ? ? ? ?p.Close(); ??
62. ? ? ? ? ? ?MessageBox.Show("over"); ??
63. ? ? ? ?} ??
64. ? ? ? ?/// <summary> ??
65. ? ? ? ?/// 從pfx文件讀取證書信息 ??
66. ? ? ? ?/// </summary> ??
67. ? ? ? ?/// <param name="sender"></param> ??
68. ? ? ? ?/// <param name="e"></param> ??
69. ? ? ? ?private void btn_readFromPfxFile(object sender, EventArgs e) ??
70. ? ? ? ?{ ??
71. ? ? ? ? ? ?X509Certificate2 pc = new X509Certificate2("luminji.pfx", "123"); ??
72. ? ? ? ? ? ?MessageBox.Show("name:" + pc.SubjectName.Name); ??
73. ? ? ? ? ? ?MessageBox.Show("public:" + pc.PublicKey.ToString()); ??
74. ? ? ? ? ? ?MessageBox.Show("private:" + pc.PrivateKey.ToString()); ??
75. ? ? ? ? ? ?pc = null; ??
76. ? ? ? ?} ??
77. ? ? ? ?/// <summary> ??
78. ? ? ? ?/// RSA解密 ??
79. ? ? ? ?/// </summary> ??
80. ? ? ? ?/// <param name="xmlPrivateKey"></param> ??
81. ? ? ? ?/// <param name="m_strDecryptString"></param> ??
82. ? ? ? ?/// <returns></returns> ??
83. ? ? ? ?public string RSADecrypt(string xmlPrivateKey, string m_strDecryptString) ??
84. ? ? ? ?{ ??
85. ? ? ? ? ? ?RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); ??
86. ? ? ? ? ? ?provider.FromXmlString(xmlPrivateKey); ??
87. ? ? ? ? ? ?byte[] rgb = Convert.FromBase64String(m_strDecryptString); ??
88. ? ? ? ? ? ?byte[] bytes = provider.Decrypt(rgb, false); ??
89. ? ? ? ? ? ?return new UnicodeEncoding().GetString(bytes); ??
90. ? ? ? ?} ??
91. ? ? ? ?/// <summary> ??
92. ? ? ? ?/// RSA加密 ??
93. ? ? ? ?/// </summary> ??
94. ? ? ? ?/// <param name="xmlPublicKey"></param> ??
95. ? ? ? ?/// <param name="m_strEncryptString"></param> ??
96. ? ? ? ?/// <returns></returns> ??
97. ? ? ? ?public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString) ??
98. ? ? ? ?{ ??
99. ? ? ? ? ? ?RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); ??
100. ? ? ? ? ? ?provider.FromXmlString(xmlPublicKey); ??
101. ? ? ? ? ? ?byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString); ??
102. ? ? ? ? ? ?return Convert.ToBase64String(provider.Encrypt(bytes, false)); ??
103. ? ? ? ?} ?
?
上文是一個示例程序,一個完整的證書工具類如下:
01.public sealed class DataCertificate ??
02. ? ?{ ?
03. ? ? ? ?#region 生成證書 ??
04. ? ? ? ?/// <summary> ??
05. ? ? ? ?/// 根據指定的證書名和makecert全路徑生成證書(包含公鑰和私鑰,并保存在MY存儲區) ??
06. ? ? ? ?/// </summary> ??
07. ? ? ? ?/// <param name="subjectName"></param> ??
08. ? ? ? ?/// <param name="makecertPath"></param> ??
09. ? ? ? ?/// <returns></returns> ??
10. ? ? ? ?public static bool CreateCertWithPrivateKey(string subjectName, string makecertPath) ??
11. ? ? ? ?{ ??
12. ? ? ? ? ? ?subjectName = "CN=" + subjectName; ??
13. ? ? ? ? ? ?string param = " -pe -ss my -n \"" + subjectName + "\" "; ??
14. ? ? ? ? ? ?try ?
15. ? ? ? ? ? ?{ ??
16. ? ? ? ? ? ? ? ?Process p = Process.Start(makecertPath, param); ??
17. ? ? ? ? ? ? ? ?p.WaitForExit(); ??
18. ? ? ? ? ? ? ? ?p.Close(); ??
19. ? ? ? ? ? ?} ??
20. ? ? ? ? ? ?catch (Exception e) ??
21. ? ? ? ? ? ?{ ??
22. ? ? ? ? ? ? ? ?LogRecord.putErrorLog(e.ToString(), "DataCerficate.CreateCertWithPrivateKey"); ??
23. ? ? ? ? ? ? ? ?return false; ??
24. ? ? ? ? ? ?} ??
25. ? ? ? ? ? ?return true; ??
26. ? ? ? ?} ?
27. ? ? ? ?#endregion ?
28.?
29. ? ? ? ?#region 文件導入導出 ??
30. ? ? ? ?/// <summary> ??
31. ? ? ? ?/// 從WINDOWS證書存儲區的個人MY區找到主題為subjectName的證書, ??
32. ? ? ? ?/// 并導出為pfx文件,同時為其指定一個密碼 ??
33. ? ? ? ?/// 并將證書從個人區刪除(如果isDelFromstor為true) ??
34. ? ? ? ?/// </summary> ??
35. ? ? ? ?/// <param name="subjectName">證書主題,不包含CN=</param> ??
36. ? ? ? ?/// <param name="pfxFileName">pfx文件名</param> ??
37. ? ? ? ?/// <param name="password">pfx文件密碼</param> ??
38. ? ? ? ?/// <param name="isDelFromStore">是否從存儲區刪除</param> ??
39. ? ? ? ?/// <returns></returns> ??
40. ? ? ? ?public static bool ExportToPfxFile(string subjectName, string pfxFileName, ??
41. ? ? ? ? ? ?string password, bool isDelFromStore) ??
42. ? ? ? ?{ ??
43. ? ? ? ? ? ?subjectName = "CN=" + subjectName; ??
44. ? ? ? ? ? ?X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ??
45. ? ? ? ? ? ?store.Open(OpenFlags.ReadWrite); ??
46. ? ? ? ? ? ?X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates; ??
47. ? ? ? ? ? ?foreach (X509Certificate2 x509 in storecollection) ??
48. ? ? ? ? ? ?{ ??
49. ? ? ? ? ? ? ? ?if (x509.Subject == subjectName) ??
50. ? ? ? ? ? ? ? ?{ ??
51. ? ? ? ? ? ? ? ? ? ?Debug.Print(string.Format("certificate name: {0}", x509.Subject)); ??
52. ?
53. ? ? ? ? ? ? ? ? ? ?byte[] pfxByte = x509.Export(X509ContentType.Pfx, password); ??
54. ? ? ? ? ? ? ? ? ? ?using (FileStream fileStream = new FileStream(pfxFileName, FileMode.Create)) ??
55. ? ? ? ? ? ? ? ? ? ?{ ??
56. ? ? ? ? ? ? ? ? ? ? ? ?// Write the data to the file, byte by byte. ??
57. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < pfxByte.Length; i++) ??
58. ? ? ? ? ? ? ? ? ? ? ? ? ? ?fileStream.WriteByte(pfxByte[i]); ??
59. ? ? ? ? ? ? ? ? ? ? ? ?// Set the stream position to the beginning of the file. ??
60. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Seek(0, SeekOrigin.Begin); ??
61. ? ? ? ? ? ? ? ? ? ? ? ?// Read and verify the data. ??
62. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < fileStream.Length; i++) ??
63. ? ? ? ? ? ? ? ? ? ? ? ?{ ??
64. ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (pfxByte[i] != fileStream.ReadByte()) ??
65. ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ??
66. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?LogRecord.putErrorLog("Export pfx error while verify the pfx file!", "ExportToPfxFile"); ??
67. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Close(); ??
68. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return false; ??
69. ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ??
70. ? ? ? ? ? ? ? ? ? ? ? ?} ??
71. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Close(); ??
72. ? ? ? ? ? ? ? ? ? ?} ??
73. ? ? ? ? ? ? ? ? ? ?if( isDelFromStore == true) ??
74. ? ? ? ? ? ? ? ? ? ? ? ?store.Remove(x509); ??
75. ? ? ? ? ? ? ? ?} ??
76. ? ? ? ? ? ?} ??
77. ? ? ? ? ? ?store.Close(); ??
78. ? ? ? ? ? ?store = null; ??
79. ? ? ? ? ? ?storecollection = null; ??
80. ? ? ? ? ? ?return true; ??
81. ? ? ? ?} ??
82. ? ? ? ?/// <summary> ??
83. ? ? ? ?/// 從WINDOWS證書存儲區的個人MY區找到主題為subjectName的證書, ??
84. ? ? ? ?/// 并導出為CER文件(即,只含公鑰的) ??
85. ? ? ? ?/// </summary> ??
86. ? ? ? ?/// <param name="subjectName"></param> ??
87. ? ? ? ?/// <param name="cerFileName"></param> ??
88. ? ? ? ?/// <returns></returns> ??
89. ? ? ? ?public static bool ExportToCerFile(string subjectName, string cerFileName) ??
90. ? ? ? ?{ ??
91. ? ? ? ? ? ?subjectName = "CN=" + subjectName; ??
92. ? ? ? ? ? ?X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ??
93. ? ? ? ? ? ?store.Open(OpenFlags.ReadWrite); ??
94. ? ? ? ? ? ?X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates; ??
95. ? ? ? ? ? ?foreach (X509Certificate2 x509 in storecollection) ??
96. ? ? ? ? ? ?{ ??
97. ? ? ? ? ? ? ? ?if (x509.Subject == subjectName) ??
98. ? ? ? ? ? ? ? ?{ ??
99. ? ? ? ? ? ? ? ? ? ?Debug.Print(string.Format("certificate name: {0}", x509.Subject)); ??
100. ? ? ? ? ? ? ? ? ? ?//byte[] pfxByte = x509.Export(X509ContentType.Pfx, password); ??
101. ? ? ? ? ? ? ? ? ? ?byte[] cerByte = x509.Export(X509ContentType.Cert); ??
102. ? ? ? ? ? ? ? ? ? ?using (FileStream fileStream = new FileStream(cerFileName, FileMode.Create)) ??
103. ? ? ? ? ? ? ? ? ? ?{ ??
104. ? ? ? ? ? ? ? ? ? ? ? ?// Write the data to the file, byte by byte. ??
105. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < cerByte.Length; i++) ??
106. ? ? ? ? ? ? ? ? ? ? ? ? ? ?fileStream.WriteByte(cerByte[i]); ??
107. ? ? ? ? ? ? ? ? ? ? ? ?// Set the stream position to the beginning of the file. ??
108. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Seek(0, SeekOrigin.Begin); ??
109. ? ? ? ? ? ? ? ? ? ? ? ?// Read and verify the data. ??
110. ? ? ? ? ? ? ? ? ? ? ? ?for (int i = 0; i < fileStream.Length; i++) ??
111. ? ? ? ? ? ? ? ? ? ? ? ?{ ??
112. ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (cerByte[i] != fileStream.ReadByte()) ??
113. ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ??
114. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?LogRecord.putErrorLog("Export CER error while verify the CERT file!", "ExportToCERFile"); ??
115. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Close(); ??
116. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return false; ??
117. ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ??
118. ? ? ? ? ? ? ? ? ? ? ? ?} ??
119. ? ? ? ? ? ? ? ? ? ? ? ?fileStream.Close(); ??
120. ? ? ? ? ? ? ? ? ? ?} ??
121. ? ? ? ? ? ? ? ?} ??
122. ? ? ? ? ? ?} ??
123. ? ? ? ? ? ?store.Close(); ??
124. ? ? ? ? ? ?store = null; ??
125. ? ? ? ? ? ?storecollection = null; ??
126. ? ? ? ? ? ?return true; ??
127. ? ? ? ?} ?
128. ? ? ? ?#endregion ?
129.?
130. ? ? ? ?#region 從證書中獲取信息 ??
131. ? ? ? ?/// <summary> ??
132. ? ? ? ?/// 根據私鑰證書得到證書實體,得到實體后可以根據其公鑰和私鑰進行加解密 ??
133. ? ? ? ?/// 加解密函數使用DEncrypt的RSACryption類 ??
134. ? ? ? ?/// </summary> ??
135. ? ? ? ?/// <param name="pfxFileName"></param> ??
136. ? ? ? ?/// <param name="password"></param> ??
137. ? ? ? ?/// <returns></returns> ??
138. ? ? ? ?public static X509Certificate2 GetCertificateFromPfxFile(string pfxFileName, ??
139. ? ? ? ? ? ?string password) ??
140. ? ? ? ?{ ??
141. ? ? ? ? ? ?try ?
142. ? ? ? ? ? ?{ ??
143. ? ? ? ? ? ? ? ?return new X509Certificate2(pfxFileName, password, X509KeyStorageFlags.Exportable); ??
144. ? ? ? ? ? ?} ??
145. ? ? ? ? ? ?catch (Exception e) ??
146. ? ? ? ? ? ?{ ??
147. ? ? ? ? ? ? ? ?LogRecord.putErrorLog("get certificate from pfx" + pfxFileName + " error:" + e.ToString(), ??
148. ? ? ? ? ? ? ? ? ? ?"GetCertificateFromPfxFile"); ??
149. ? ? ? ? ? ? ? ?return null; ??
150. ? ? ? ? ? ?} ??
151. ? ? ? ?} ??
152. ? ? ? ?/// <summary> ??
153. ? ? ? ?/// 到存儲區獲取證書 ??
154. ? ? ? ?/// </summary> ??
155. ? ? ? ?/// <param name="subjectName"></param> ??
156. ? ? ? ?/// <returns></returns> ??
157. ? ? ? ?public static X509Certificate2 GetCertificateFromStore(string subjectName) ??
158. ? ? ? ?{ ??
159. ? ? ? ? ? ?subjectName = "CN=" + subjectName; ??
160. ? ? ? ? ? ?X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ??
161. ? ? ? ? ? ?store.Open(OpenFlags.ReadWrite); ??
162. ? ? ? ? ? ?X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates; ??
163. ? ? ? ? ? ?foreach (X509Certificate2 x509 in storecollection) ??
164. ? ? ? ? ? ?{ ??
165. ? ? ? ? ? ? ? ?if (x509.Subject == subjectName) ??
166. ? ? ? ? ? ? ? ?{ ??
167. ? ? ? ? ? ? ? ? ? ?return x509; ??
168. ? ? ? ? ? ? ? ?} ??
169. ? ? ? ? ? ?} ??
170. ? ? ? ? ? ?store.Close(); ??
171. ? ? ? ? ? ?store = null; ??
172. ? ? ? ? ? ?storecollection = null; ??
173. ? ? ? ? ? ?return null; ??
174. ? ? ? ?} ??
175. ? ? ? ?/// <summary> ??
176. ? ? ? ?/// 根據公鑰證書,返回證書實體 ??
177. ? ? ? ?/// </summary> ??
178. ? ? ? ?/// <param name="cerPath"></param> ??
179. ? ? ? ?public static X509Certificate2 GetCertFromCerFile(string cerPath) ??
180. ? ? ? ?{ ??
181. ? ? ? ? ? ?try ?
182. ? ? ? ? ? ?{ ??
183. ? ? ? ? ? ? ? ?return new X509Certificate2(cerPath); ??
184. ? ? ? ? ? ?} ??
185. ? ? ? ? ? ?catch (Exception e) ??
186. ? ? ? ? ? ?{ ??
187. ? ? ? ? ? ? ? ?LogRecord.putErrorLog(e.ToString(), "DataCertificate.LoadStudentPublicKey"); ??
188. ? ? ? ? ? ? ? ?return null; ??
189. ? ? ? ? ? ?} ? ? ? ? ? ? ??
190. ? ? ? ?} ?
191. ? ? ? ?#endregion ? ? ? ? ?
192. ? ?} ?
Creative Commons License
本文基于Creative Commons Attribution 2.5 China Mainland License發布,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名http://www.cnblogs.com/luminji(包含鏈接)。
========
總結
以上是生活随笔為你收集整理的C#数字证书编程总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解Win7下PowerShell初步使
- 下一篇: C# SharpMap 学习总结