C#数字证书编程总结
生活随笔
收集整理的這篇文章主要介紹了
C#数字证书编程总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
.NET中如何操作數(shù)字證書詳解
http://blog.csdn.net/zjlovety/article/details/7252792
.NET為我們提供了操作數(shù)字證書的兩個(gè)主要的類,分為為:
System.Security.Cryptography.X509Certificates.X509Certificate2類, 每個(gè)這個(gè)類的實(shí)例可以表示一個(gè)證書;
System.Security.Cryptography.X509Certificates.X509Store類,可以對保存在計(jì)算機(jī)安全區(qū)域內(nèi)的證書進(jìn)行add/remove/get操作。
另外我們可以使用System.Security.Cryptography.X509Certificates.X509Certificate2UI類來顯示證書消息的對話框,它就是在IE中的證書查看器的.NE實(shí)現(xiàn)。
生成證書
在介紹以上類的使用方法之前,我們先要擁有一個(gè)數(shù)字證書,獲取數(shù)字證書有三種方法,一是從CA機(jī)構(gòu)申請,二是自己搭建服務(wù)器發(fā)布證書,三是使用makecert.exe來生成一個(gè)證書文件。這里我們使用makecert.exe來生成一個(gè)證書文件,用來測試。啟動(dòng)VS2010的命令行,輸入對應(yīng)參數(shù),生成名為TestCertificates的證書文件。如圖6-28所示。
生成證書
圖6-28 生成證書
makecert.exe的參數(shù)讀者可以查看幫助,這里只解釋圖6-28中的參數(shù)。
參數(shù)說明:
-sr CurrentUser:指定主題的證書存儲(chǔ)位置。Location 可以是 currentuser(默認(rèn)值)或 localmachine
-ss MyTestContainer:指定主題的證書存儲(chǔ)名稱,輸出證書即存儲(chǔ)在那里。
-n CN=TestCert:指定主題的證書名稱。此名稱必須符合 X.500 標(biāo)準(zhǔn)。最簡單的方法是在雙引號(hào)中指定此名稱,并加上前綴 CN=;例如,"CN=myName"。
-sky exchange:指定頒發(fā)者的密鑰類型,必須是 signature、exchange 或一個(gè)表示提供程序類型的整數(shù)。默認(rèn)情況下,可傳入 1 表示交換密鑰,傳入 2 表示簽名密鑰。
-pe:將所生成的私鑰標(biāo)記為可導(dǎo)出。這樣可將私鑰包括在證書中。
生成的密鑰文件被保存在了我們指定的MyTestContainer中,但到哪去查看我們的證書呢?Windows沒有給我們準(zhǔn)備好直接的管理證書的入口,但我們可以在MMC控制臺(tái)自行添加。
開始 ? 運(yùn)行 ? MMC,打開一個(gè)空的MMC控制臺(tái)。
在控制臺(tái)菜單,文件 ? 添加/刪除管理單元 ? 添加按鈕 ? 選"證書" ? 添加 ? 選"我的用戶賬戶" ? 關(guān)閉 ? 確定
在控制臺(tái)菜單,文件 ? 添加/刪除管理單元 ? 添加按鈕 ? 選"證書" ? 添加 ? 選"計(jì)算機(jī)賬戶" ? 關(guān)閉 ? 確定
如圖6-29,我們可以查看兩個(gè)賬戶的證書管理,在我的賬戶中可以看到MyTestContainer下的證書TestCert。
在MMC控制臺(tái)查看和管理證書
圖6-29 在MMC控制臺(tái)查看和管理證書
當(dāng)然我們也可以將證書文件保存為文件,如圖6-30所示。
將證書保存為文件
圖6-30 將證書保存為文件
打開E盤,可以看到生成的證書文件。如圖6-31所示。
生成的證書文件
圖6-31 生成的證書文件
將證書保存為文件時(shí),我們有三種選擇:
帶有私鑰的證書
由Public Key Cryptography Standards #12,PKCS#12標(biāo)準(zhǔn)定義,包含了公鑰和私鑰的二進(jìn)制格式的證書形式,以pfx作為證書文件后綴名。
二進(jìn)制編碼的證書
證書中沒有私鑰,DER 編碼二進(jìn)制格式的證書文件,以cer作為證書文件后綴名。
Base64編碼的證書
證書中沒有私鑰,BASE64 編碼格式的證書文件,也是以cer作為證書文件后綴名。
右鍵單擊本地的證書文件,我們可以看到安裝選項(xiàng),可以把該證書文件安裝到證書存儲(chǔ)區(qū)。也可在MMC的證書管理臺(tái)上執(zhí)行導(dǎo)出任務(wù)將存儲(chǔ)區(qū)的證書導(dǎo)出為文件。這里就不再演示了,讀者可以自行實(shí)踐。
編程操作證書
我們可以通過編程的方式操作操作本地的證書文件和在存儲(chǔ)區(qū)中的證書。我們以剛才保存在E盤的test.cer文件為例,講解如何讀取本地的證書文件,并將它添加到存儲(chǔ)區(qū)中。先看代碼清單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演示了如何讀取本地證書文件的方法。靜態(tài)方法ReadFile用來從本地磁盤中讀取證書文件到byte數(shù)組中。主要的操作都在Main方法中。X509Certificate2 x509 = new X509Certificate2()一句使用無參數(shù)的構(gòu)造函數(shù)初始化X509Certificate2類的實(shí)例x509。然后我們使用x509.Import(rawData)語句將byte數(shù)組導(dǎo)入到當(dāng)前證書實(shí)例。接下來是輸出該證書的信息。
輸出信息之后,我們看下面的四行代碼:
X509Store store = new X509Store(); ?
store.Open(OpenFlags.MaxAllowed); ?
store.Add(x509); ?
store.Close();?
?
首先我們初始化一個(gè)X509Store類的實(shí)例store,然后使用Open方法打開存儲(chǔ)區(qū),添加上面讀取的證書到存儲(chǔ)區(qū)。
X509Certificate2一共提供了14個(gè)構(gòu)造函數(shù)供我們使用,這里就不一一介紹了。我們也可以通過X509Certificate2類的構(gòu)造函數(shù)直接導(dǎo)入本地的證書文件,可以使用代碼清單6-18所示的方式。
代碼清單6-18 使用構(gòu)造函數(shù)導(dǎo)入證書文件
X509Certificate2 myX509Certificate2 = new X509Certificate2( ?
@"e:\MyTestCert.pfx", //證書路徑 ?
"password", //證書的私鑰保護(hù)密碼 ?
X509KeyStorageFlags.Exportable //表示此證書的私鑰以后還可以導(dǎo)出 ?
);?
?
代碼清單6-18給出了如何導(dǎo)入帶私鑰保護(hù)密碼的證書的方法。X509KeyStorageFlags 枚舉用來標(biāo)識(shí)X.509 證書的私鑰導(dǎo)出到何處以及如何導(dǎo)出。該枚舉的成員說明如表6-1所示。
表6-1 X509KeyStorageFlags 枚舉說明
成員名稱
說明
DefaultKeySet
使用默認(rèn)的密鑰集。用戶密鑰集通常為默認(rèn)值。
UserKeySet
私鑰存儲(chǔ)在當(dāng)前用戶存儲(chǔ)區(qū)而不是本地計(jì)算機(jī)存儲(chǔ)區(qū)。既使證書指定密鑰應(yīng)存儲(chǔ)在本地計(jì)算機(jī)存儲(chǔ)區(qū),私鑰也會(huì)存儲(chǔ)到當(dāng)前用戶存儲(chǔ)區(qū)。
MachineKeySet
私鑰存儲(chǔ)在本地計(jì)算機(jī)存儲(chǔ)區(qū)而不是當(dāng)前用戶存儲(chǔ)區(qū)。
Exportable
導(dǎo)入的密鑰被標(biāo)記為可導(dǎo)出。
UserProtected
通過對話框或其他方法,通知用戶密鑰被訪問。使用的加密服務(wù)提供程序 (CSP) 定義確切的行為。
PersistKeySet
導(dǎo)入證書時(shí)會(huì)保存與 PFX 文件關(guān)聯(lián)的密鑰。
那么如何操作存儲(chǔ)區(qū)中的證書呢,可以使用代碼清單6-19的方式。
代碼清單6-19 操作存儲(chǔ)區(qū)中的證書
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); ?
store.Open(OpenFlags.ReadOnly); ?
//輪詢存儲(chǔ)區(qū)中的所有證書 ?
foreach(X509Certificate2 myX509Certificate2 in store.Certificates) ?
{ ?
//將證書的名稱跟要導(dǎo)出的證書MyTestCert比較,找到要導(dǎo)出的證書 ?
if (myX509Certificate2.Subject == "CN=TestCert") ?
{ ?
//證書導(dǎo)出到byte[]中,password為私鑰保護(hù)密碼 ?
byte[] CertByte = myX509Certificate2.Export(X509ContentType.Pfx,"password"); ?
//將證書的字節(jié)流寫入到證書文件 ?
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類的實(shí)例store,使用了兩個(gè)參數(shù)的構(gòu)造函數(shù),第一個(gè)參數(shù)是存儲(chǔ)容器的名稱,StoreName枚舉只能枚舉系統(tǒng)默認(rèn)的存儲(chǔ)區(qū)名稱。第二個(gè)參數(shù)是StoreLocation枚舉,用來標(biāo)識(shí)是本機(jī)證書還是當(dāng)前用戶證書。導(dǎo)出容器證書使用的是Export方法。第一個(gè)參數(shù)X509ContentType.Pfx表示要導(dǎo)出為含有私鑰的pfx證書形式,第二個(gè)參數(shù)為私鑰保護(hù)密碼。如果要導(dǎo)出為不含私鑰的cer證書,第一個(gè)參數(shù)使用X509ContentType.Cert,表示導(dǎo)出為不含私鑰的cer證書,也就不需要密碼了。
創(chuàng)建發(fā)行者證書
發(fā)行者證書是驗(yàn)證發(fā)行者可靠性的證書文件,保護(hù)證書發(fā)行者的簽名。我們可以從證書頒發(fā)機(jī)構(gòu)獲得該文件。做為程序測試,我們可以使用Cert2spc.exe來生成發(fā)行者證書。從命令行啟動(dòng)該程序,如圖6-32所示。
生成SPC文件
圖6-32 生成SPC文件
如圖6-32,我們使用Cert2spc.exe以test.cer為參數(shù)生成目標(biāo)為tset.spc的發(fā)行者證書,如果存在多個(gè)證書文件,可以作為參數(shù)以空格隔開生成統(tǒng)一的發(fā)行者證書。
使用證書對文件簽名
簽名工具 (SignTool.exe) 是一個(gè)命令行工具,用于對文件進(jìn)行數(shù)字簽名,驗(yàn)證文件或時(shí)間戳文件中的簽名。我們可以對cab文件、dll文件或者其他文件進(jìn)行簽名,從互聯(lián)網(wǎng)訪問這些文件的時(shí)候就需要安裝和驗(yàn)證證書。該工具詳細(xì)的說明讀者可以從MSDN上找到,我就不在重復(fù)了。
========
C#中使用X509Certificate2類獲取數(shù)字證書頒發(fā)者和持有者的名稱信息
在 .NET Framework 中有一個(gè)名為 X509Certificate2 的類,使用該類包含的屬性可以方便地獲得 X.509 格式數(shù)字證書中的序列號(hào)、有效期起始日、有效期終止日等信息。在MSDN網(wǎng)站上可以查到關(guān)于該類的詳細(xì)說明。
在該類的屬性中,Issuer 和 IssuerName、Subject 和 SubjectName 這兩對看起來比較像,容易讓人混淆。這里做一下說明:
1) Issuer 和 Subject 屬性的類型都是 string,使用這兩個(gè)屬性,可以分別得到證書頒發(fā)者和證書持有者的 Distinguished Name。Distinguished Name 通常是一個(gè)類似下面形式的字符串:"CN=MyName, O=MyOrg, OU=MyOrgUnit, C=US"
這種字符串內(nèi)部用 , 作為分隔符(注意是英文中的逗號(hào),不是中文中的逗號(hào)),其中 CN 代表 Common Name,O 代表組織名,OU 代表組織下屬機(jī)構(gòu)名,C 代表國家名。
2) IssuerName 和 SubjectName 屬性的類型都是 System.Security.Cryptography.X509Certificates.X500DistinguishedName,注意不是 string。X500DistinguishedName 有三個(gè)屬性,分別是:Name, Oid 和 RawData。使用 Name 屬性也可以獲得 Distinguished Name。即:
X509Certificate2.Issuer 與 X509Certificate2.IssuerName.Name 的值是相等的;
X509Certificate2.Subject 與 X509Certificate2.SubjectName.Name 的值是相等的。
對于證書頒發(fā)者或持有者的 Distinguished Name,經(jīng)常被用到的部分是其中的 Common Name,即 CN= 后面的內(nèi)容。但是 .NET Framework 中并沒有直接提供從 Distinguished Name 中提取出 Common Name 的方法。由于 Distinguished Name 的內(nèi)部是用 , 來隔開不同含義的部分,于是就可以用 , 作為分隔符,將 Distinguished Name 拆分為多個(gè)子串,然后在子串中查找 CN= ,找到以后把 CN= 后面的部分提取出來,這樣就可以得到 Common Name 的值了。具體實(shí)現(xiàn)代碼如下:
/************************************************** ?
* 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"; /* 注意這里的 , 不是中文里的逗號(hào) */
? ? ? ? ? ? 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#創(chuàng)建數(shù)字證書并導(dǎo)出為pfx,并使用pfx進(jìn)行非對稱加解密
http://www.cnblogs.com/luminji/archive/2010/10/28/1863179.html
? ? ?本文源程序下載:http://download.csdn.net/source/2444494
? ? ?我的項(xiàng)目當(dāng)中,考慮到安全性,需要為每個(gè)客戶端分發(fā)一個(gè)數(shù)字證書,同時(shí)使用數(shù)字證書中的公私鑰來進(jìn)行數(shù)據(jù)的加解密。為了完成這個(gè)安全模塊,特寫了如下一個(gè)DEMO程序,該DEMO程序包含的功能有:
1:調(diào)用.NET2.0的MAKECERT創(chuàng)建含有私鑰的數(shù)字證書,并存儲(chǔ)到個(gè)人證書區(qū);
2:將該證書導(dǎo)出為pfx文件,并為其指定一個(gè)用來打開pfx文件的password;
3:讀取pfx文件,導(dǎo)出pfx中公鑰和私鑰;
4:用pfx證書中的公鑰進(jìn)行數(shù)據(jù)的加密,用私鑰進(jìn)行數(shù)據(jù)的解密;
系統(tǒng)界面:
image
代碼如下:
01./// <summary> ??
02. ? ? ? ?/// 將證書從證書存儲(chǔ)區(qū)導(dǎo)出,并存儲(chǔ)為pfx文件,同時(shí)為pfx文件指定打開的密碼 ??
03. ? ? ? ?/// 本函數(shù)同時(shí)也演示如何用公鑰進(jìn)行加密,私鑰進(jìn)行解密 ??
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. ? ? ? ?/// 創(chuàng)建還有私鑰的證書 ??
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. ? ? ? ?} ?
?
上文是一個(gè)示例程序,一個(gè)完整的證書工具類如下:
01.public sealed class DataCertificate ??
02. ? ?{ ?
03. ? ? ? ?#region 生成證書 ??
04. ? ? ? ?/// <summary> ??
05. ? ? ? ?/// 根據(jù)指定的證書名和makecert全路徑生成證書(包含公鑰和私鑰,并保存在MY存儲(chǔ)區(qū)) ??
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 文件導(dǎo)入導(dǎo)出 ??
30. ? ? ? ?/// <summary> ??
31. ? ? ? ?/// 從WINDOWS證書存儲(chǔ)區(qū)的個(gè)人MY區(qū)找到主題為subjectName的證書, ??
32. ? ? ? ?/// 并導(dǎo)出為pfx文件,同時(shí)為其指定一個(gè)密碼 ??
33. ? ? ? ?/// 并將證書從個(gè)人區(qū)刪除(如果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">是否從存儲(chǔ)區(qū)刪除</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證書存儲(chǔ)區(qū)的個(gè)人MY區(qū)找到主題為subjectName的證書, ??
84. ? ? ? ?/// 并導(dǎo)出為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. ? ? ? ?/// 根據(jù)私鑰證書得到證書實(shí)體,得到實(shí)體后可以根據(jù)其公鑰和私鑰進(jìn)行加解密 ??
133. ? ? ? ?/// 加解密函數(shù)使用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. ? ? ? ?/// 到存儲(chǔ)區(qū)獲取證書 ??
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. ? ? ? ?/// 根據(jù)公鑰證書,返回證書實(shí)體 ??
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發(fā)布,歡迎轉(zhuǎn)載,演繹或用于商業(yè)目的,但是必須保留本文的署名http://www.cnblogs.com/luminji(包含鏈接)。
========
總結(jié)
以上是生活随笔為你收集整理的C#数字证书编程总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解Win7下PowerShell初步使
- 下一篇: Linux进程地址空间学习总结