.NET Framework 2.0 大幅強化憑證支援,新增 System.Security.Cryptography.X509Certificates 命名空間與 X509Certificate2 類別,提供符合 PKCS #7/CMS 標準的加密簽名 API。本文系統涵蓋:Windows 憑證存儲區操作、憑證類別體系、驗證/SSL/Web 服務/程式碼簽名應用、資料簽名加密與解密驗證完整流程。
.cer (公開金鑰)、.pfx (含私鑰,PKCS #12,可設密碼保護)。makecert.exe (測試)、selfssl.exe (IIS SSL 快速建立)。Personal (我的憑證)、Trusted Root CA、Other People 等。工具:certmgr.msc。| 類別 | 特點 |
|---|---|
X509Certificate | 1.x 版本,功能有限,不支援加密操作。 |
X509Certificate2 | 2.0 新增,繼承自前者,支援私鑰操作、PKCS#7、完整屬性存取。**首選類別**。 |
兩者可互轉,但建議統一使用 X509Certificate2。
// 從 .cer
X509Certificate2 cert1 = new X509Certificate2("alice.cer");
// 從 .pfx (需 SecureString 密碼)
SecureString pwd = GetSecureStringFromConsole(); // 禁用回顯讀取
X509Certificate2 cert2 = new X509Certificate2("alice.pfx", pwd);
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); // Personal = My
store.Open(OpenFlags.ReadOnly);
var col = store.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, "21f2bf44...", true);
X509Certificate2 cert = col[0];
store.Close();
常用搜尋條件:主體名稱、序號、指紋 (SHA-1,換發會變)、主體金鑰識別碼 (SKI,較穩定)。
// 選擇憑證
X509Certificate2 cert = X509Certificate2UI.SelectFromCollection(store.Certificates, "標題", "訊息", X509SelectionFlag.SingleSelection)[0];
// 顯示詳細資訊
X509Certificate2UI.DisplayCertificate(cert);
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online | X509RevocationMode.Offline;
chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(30);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
// chain.ChainPolicy.VerificationTime = new DateTime(1999,1,1); // 歷史時間點驗證
chain.Build(cert);
if (chain.ChainStatus.Length > 0) Console.WriteLine(chain.ChainStatus[0].Status);
HttpWebRequest / Web 服務 Proxy:URL 使用 https:// 自動啟用。ServicePointManager.ServerCertificateValidationCallback 自訂策略 (如測試環境允許過期)。request.ClientCertificates.Add(cert)。Stream 加上 SSL 層,支援自訂驗證回調,適用非 HTTP 協定。X509SecurityToken 加入 RequestSoapContext.Security.Tokens。<serviceCredentials> 宣告存儲區位置、名稱、搜尋類型與值,完全對應程式碼枚舉。signtool.exe 簽署 .exe/.dll (Authenticode),驗證發布者身分。核心類別:ContentInfo (資料封裝)、SignedCms (簽名)、EnvelopedCms (加密)、CmsSigner/CmsRecipient。
// 1. 簽名
byte[] Sign(byte[] data, X509Certificate2 signerCert) {
ContentInfo content = new ContentInfo(data);
SignedCms signed = new SignedCms(content);
signed.ComputeSignature(new CmsSigner(signerCert));
return signed.Encode(); // 含資料、簽名、簽名憑證
}
// 分離簽名 (不含資料,適合大量小資料)
SignedCms signed = new SignedCms(content, true); // true = detached
// ... 同樣 ComputeSignature
return signed.Encode(); // 僅含簽名
// 2. 加密
byte[] Encrypt(byte[] data, X509Certificate2 recipientCert) {
ContentInfo content = new ContentInfo(data);
EnvelopedCms env = new EnvelopedCms(content);
env.Encrypt(new CmsRecipient(recipientCert)); // 產生隨機 Session Key 對稱加密資料,再用接收者公開鑰加密 Session Key
return env.Encode();
}
// 解密
EnvelopedCms env = new EnvelopedCms();
env.Decode(encryptedData);
env.Decrypt(); // 自動從存儲區尋找私鑰解密 Session Key
byte[] plain = env.ContentInfo.Content;
// 驗證簽名 (含憑證鏈驗證)
SignedCms signed = new SignedCms();
signed.Decode(signedData); // 或分離簽名需先載入資料再 Decode(signature)
signed.CheckSignature(false); // false = 驗證簽名+憑證
// 取得簽名者資訊
foreach (SignerInfo si in signed.SignerInfos) Console.WriteLine(si.Certificate.Subject);
byte[] original = signed.ContentInfo.Content;
分離簽名驗證:
new SignedCms(content, true).Decode(signature).CheckSignature(false)。
包含 Windows Forms 範例應用程式,示範憑證選擇、檔案簽名加密、驗證解密完整流程:
本文配套原始碼