本文介绍了如何使用Windows自带的证书生成器生成,导出,使用证书。并以验证文件是否被修改举例
1.证书相关辅助类
public sealed class DataCertificate { #region 生成证书 /// <summary> /// 根据指定的证书名和makecert全路径生成证书(包含公钥和私钥,并保存在MY存储区) /// </summary> /// <paramname="subjectName"></param> /// <paramname="makecertPath"></param> /// <returns></returns> public static boolCreateCertWithPrivateKey(string subjectName, string makecertPath) { subjectName = "CN=" +subjectName; string param = "-r -pe -n" + subjectName + " -b 01/01/2005 -sky exchange -ss my"; try { Process p = Process.Start(makecertPath,param); p.WaitForExit(); p.Close(); } catch (Exception e) { //LogRecord.putErrorLog(e.ToString(),"DataCerficate.CreateCertWithPrivateKey"); return false; } return true; } #endregion #region 文件导入导出 /// <summary> /// 从WINDOWS证书存储区的个人MY区找到主题为subjectName的证书, /// 并导出为pfx文件,同时为其指定一个密码 /// 并将证书从个人区删除(如果isDelFromstor为true) /// </summary> /// <paramname="subjectName">证书主题,不包含CN=</param> /// <paramname="pfxFileName">pfx文件名</param> /// <paramname="password">pfx文件密码</param> /// <paramname="isDelFromStore">是否从存储区删除</param> /// <returns></returns> public static bool ExportToPfxFile(stringsubjectName, string pfxFileName, string password, boolisDelFromStore) { subjectName = "CN=" +subjectName; X509Store store = new X509Store(StoreName.My,StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2Collectionstorecollection = (X509Certificate2Collection)store.Certificates; foreach (X509Certificate2 x509 instorecollection) { if (x509.Subject ==subjectName) { Debug.Print(string.Format("certificatename: {0}", x509.Subject)); byte[] pfxByte =x509.Export(X509ContentType.Pfx, password); using (FileStreamfileStream = new FileStream(pfxFileName, FileMode.Create)) { // Write the data tothe file, byte by byte. for (int i = 0; i <pfxByte.Length; i++) fileStream.WriteByte(pfxByte[i]); // Set the streamposition to the beginning of the file. fileStream.Seek(0, SeekOrigin.Begin); // Read and verify thedata. for (int i = 0; i <fileStream.Length; i++) { if (pfxByte[i] !=fileStream.ReadByte()) { //LogRecord.putErrorLog("Exportpfx error while verify the pfx file!", "ExportToPfxFile"); fileStream.Close(); return false; } } fileStream.Close(); } if (isDelFromStore == true) store.Remove(x509); } } store.Close(); store = null; storecollection = null; return true; } /// <summary> /// 从WINDOWS证书存储区的个人MY区找到主题为subjectName的证书, /// 并导出为CER文件(即,只含公钥的) /// </summary> /// <paramname="subjectName"></param> /// <paramname="cerFileName"></param> /// <returns></returns> public static bool ExportToCerFile(stringsubjectName, string cerFileName) { subjectName = "CN=" +subjectName; X509Store store = new X509Store(StoreName.My,StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2Collectionstorecollection = (X509Certificate2Collection)store.Certificates; foreach (X509Certificate2 x509 instorecollection) { if (x509.Subject ==subjectName) { Debug.Print(string.Format("certificatename: {0}", x509.Subject)); //byte[] pfxByte =x509.Export(X509ContentType.Pfx, password); byte[] cerByte =x509.Export(X509ContentType.Cert); using (FileStreamfileStream = new FileStream(cerFileName, FileMode.Create)) { // Write the data tothe file, byte by byte. for (int i = 0; i <cerByte.Length; i++) fileStream.WriteByte(cerByte[i]); // Set the streamposition to the beginning of the file. fileStream.Seek(0, SeekOrigin.Begin); // Read and verify thedata. for (int i = 0; i <fileStream.Length; i++) { if (cerByte[i] !=fileStream.ReadByte()) { //LogRecord.putErrorLog("ExportCER error while verify the CERT file!", "ExportToCERFile"); fileStream.Close(); return false; } } fileStream.Close(); } } } store.Close(); store = null; storecollection = null; return true; } #endregion #region 从证书中获取信息 /// <summary> /// 根据私钥证书得到证书实体,得到实体后可以根据其公钥和私钥进行加解密 /// 加解密函数使用DEncrypt的RSACryption类 /// </summary> /// <paramname="pfxFileName"></param> /// <paramname="password"></param> /// <returns></returns> public static X509Certificate2GetCertificateFromPfxFile(string pfxFileName, string password) { try { return new X509Certificate2(pfxFileName,password, X509KeyStorageFlags.Exportable); } catch (Exception e) { //LogRecord.putErrorLog("getcertificate from pfx" + pfxFileName + " error:" +e.ToString(), // "GetCertificateFromPfxFile"); return null; } } /// <summary> /// 到存储区获取证书 /// </summary> /// <paramname="subjectName"></param> /// <returns></returns> public static X509Certificate2GetCertificateFromStore(string subjectName) { subjectName = "CN=" +subjectName; X509Store store = new X509Store(StoreName.My,StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2Collectionstorecollection = (X509Certificate2Collection)store.Certificates; foreach (X509Certificate2 x509 instorecollection) { if (x509.Subject ==subjectName) { return x509; } } store.Close(); store = null; storecollection = null; return null; } /// <summary> /// 根据公钥证书,返回证书实体 /// </summary> /// <paramname="cerPath"></param> public static X509Certificate2GetCertFromCerFile(string cerPath) { try { return new X509Certificate2(cerPath); } catch (Exception e) { //LogRecord.putErrorLog(e.ToString(),"DataCertificate.LoadStudentPublicKey"); return null; } } #endregion #region 加解密 private static byte[] m_Bytes; /// <summary> /// 根据明文加密证书密码生成密文 /// </summary> /// <paramname="mingwen"></param> /// <paramname="pfxFileName"></param> /// <paramname="password"></param> /// <returns></returns> public static string EncryptString(stringmingwen, string pfxFileName, string password) { UnicodeEncoding ByteConverter = newUnicodeEncoding(); byte[] mingwenBytes =ByteConverter.GetBytes(mingwen); X509Certificate2 X509Certificate2 =GetCertificateFromPfxFile(pfxFileName, password); RSACryptoServiceProvidermyRSACryptoServiceProvider = (RSACryptoServiceProvider)X509Certificate2.PrivateKey; RSAParameters parameters =myRSACryptoServiceProvider.ExportParameters(true); byte[] encryptedData =myRSACryptoServiceProvider.SignData(mingwenBytes, new SHA1CryptoServiceProvider()); return Convert.ToBase64String(encryptedData); //returnRSAext.EncryptProcess(mingwen, parameters.D, parameters.Modulus); //byte[] plaintextByte =myRSACryptoServiceProvider.Encrypt(mingwenBytes, false); //m_Bytes = plaintextByte; //string str = ""; //for (int i = 0; i <plaintextByte.Length; i++) //{ // str +=plaintextByte[i].ToString("X2"); //} //return str; } /// <summary> /// 根据明文密文证书,验证文件是否被修改 /// </summary> /// <paramname="yuanwen"></param> /// <paramname="miwen"></param> /// <paramname="cerPath"></param> /// <returns></returns> public static bool DecryptString(stringyuanwen, string miwen, string cerPath) { X509Certificate2 X509Certificate2 =GetCertFromCerFile(cerPath); RSACryptoServiceProvidermyRSACryptoServiceProvider = (RSACryptoServiceProvider)X509Certificate2.PublicKey.Key; //RSAParameters parameters =myRSACryptoServiceProvider.ExportParameters(true); UnicodeEncoding ByteConverter = newUnicodeEncoding(); byte[] dataToVerifyBytes =ByteConverter.GetBytes(yuanwen); byte[] signedDataBytes = Convert.FromBase64String(miwen); returnmyRSACryptoServiceProvider.VerifyData(dataToVerifyBytes, new SHA1CryptoServiceProvider(),signedDataBytes); //returnRSAext.DecryptProcess(miwen, parameters.Modulus, parameters.Exponent); //byte[] plaintextByte =myRSACryptoServiceProvider.Decrypt(mingwenBytes, false); //returnEncoding.UTF8.GetString(plaintextByte); } #endregion }
2.使用举例
根据指定的证书名和makecert全路径生成证书(包含公钥和私钥,并保存在MY存储区)
stringMakeCert = @"C:\Program Files (x86)\WindowsKits\8.0\bin\x86\makecert.exe";
DataCertificate.CreateCertWithPrivateKey("digihail123",MakeCert);
从WINDOWS证书存储区的个人MY区找到主题为digihail123的证书,并使用密码生成pfx文件和导出cer文件
DataCertificate.ExportToPfxFile("digihail123","d:\\digihail456.pfx","123456",false);
DataCertificate.ExportToCerFile("digihail123","d:\\digihail456.cer");
根据明文 pfx文件 密码生成密文 并把明文 密文一起写入的文件,和cer证书下发给客户端
string miwen=DataCertificate.EncryptString(mingwen,"d:\\digihail456.pfx", "123456");
4.根据从文件读取的 明文 密文 和cer文件验证文件是否被修改
bool isok = DataCertificate.DecryptString(mingwen,miwen,"d:\\digihail456.cer");