1.相关名词
证书文件通常以.cer, .crt结尾
公钥文件通常以.pem结尾
私钥文件通常以.key结尾
.pfx 一种文件存储格式, pkcs12是它的实现, 通常里面同时包含私钥, 公钥, 证书, 方便存储和传播
公钥/私钥用于数据加密, 公钥可以发布给任何人, 私钥必须保密
用公钥加密
用私钥解密
客户端通过公钥将数据加密传递给我,只有我手中的私钥可以解密,这就是SSL,这里的秘钥就是key文件。
2.makecert
Microsoft Visual Studio 安装目录可以找到 makecert.exe文件,通过makecert可以在本地生成一个证书。
我的VS版本为2017 运行文件路径为
string MakeCert = @"C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64\makecert.exe"
makecert --help 用来验证是否可以生成证书
参数意义
-r: 自签名
-pe: 将所生成的私钥标记为可导出。这样可将私钥包括在证书中。
-n "cn=MyCA": 证书的subject name,.net自带类库中有X509Store类,可以在store中根据证书subject name,来找到改证书
store参考:X509Store 类
-$ commercial:指明证书商业使用。
-a:指定签名算法。必须是 md5(默认值)或 sha1。
-b 08/05/2010:证书有效期的开始时间,默认为证书的创建日期。格式为:mm/dd/yyyy
-e 01/01/2012:指定有效期的结束时间。默认为 12/31/2039 11:59:59 GMT。格式同上
-ss my:证书产生到my个人store区
-sr currentuser:保持到计算机当前个人用户区,其他用户登录系统后则看不到该证书。
3.C#语言操作代码示例
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace TcpServer.Utils
{
public class CertificateUtil
{
///
/// 将证书从证书存储区导出,并存储为pfx文件,同时为pfx文件指定打开的密码
/// 本函数同时也演示如何用公钥进行加密,私钥进行解密
///
public void OutPfxFile(string name, string password)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;
foreach (X509Certificate2 x509 in storecollection)
{
if (x509.Subject == "CN=" + name)
{
Debug.Print(string.Format("certificate name: {0}", x509.Subject));
byte[] pfxByte = x509.Export(X509ContentType.Pfx, password);
using (FileStream fileStream = new FileStream(name + ".pfx", FileMode.Create))
{
// 写数据到文件
for (int i = 0; i < pfxByte.Length; i++)
fileStream.WriteByte(pfxByte[i]);
// Set the stream position to the beginning of the file.
fileStream.Seek(0, SeekOrigin.Begin);
//读取并校验数据
for (int i = 0; i < fileStream.Length; i++)
{
if (pfxByte[i] != fileStream.ReadByte())
{
Debug.Print("Error writing data.");
return;
}
}
fileStream.Close();
Debug.Print("The data was written to {0} " +
"and verified.", fileStream.Name);
}
string myname = "这是测试文本数据 this is test text data";
string enStr = this.RSAEncrypt(x509.PublicKey.Key.ToXmlString(false), myname);
Console.WriteLine("密文是:" + enStr);
string deStr = this.RSADecrypt(x509.PrivateKey.ToXmlString(true), enStr);
Console.WriteLine("明文是:" + deStr);
}
}
store.Close();
store = null;
storecollection = null;
}
///
/// 从WINDOWS证书存储区的个人MY区找到主题为subjectName的证书,
/// 并导出为CER文件(即,只含公钥的)
///
public static bool OutCerFile(string subjectName, string cerFileName)
{
subjectName = "CN=" + subjectName;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;
foreach (X509Certificate2 x509 in storecollection)
{
if (x509.Subject == subjectName)
{
Debug.Print(string.Format("certificate name: {0}", x509.Subject));
byte[] cerByte = x509.Export(X509ContentType.Cert);
using (FileStream fileStream = new FileStream(cerFileName, FileMode.Create))
{
for (int i = 0; i < cerByte.Length; i++)
fileStream.WriteByte(cerByte[i]);
fileStream.Seek(0, SeekOrigin.Begin);
for (int i = 0; i < fileStream.Length; i++)
{
if (cerByte[i] != fileStream.ReadByte())
{
Log.WriteLog("Export CER error while verify the CERT file!" + "ExportToCERFile");
fileStream.Close();
return false;
}
}
fileStream.Close();
}
}
}
store.Close();
store = null;
storecollection = null;
return true;
}
///
/// 根据指定的证书名和makecert全路径生成证书(包含公钥和私钥,并保存在MY存储区)
///
public void CreateBook(string name, string path)
{
//string MakeCert = @"C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64\makecert.exe";
string x509Name = "CN=" + name;
string param = " -pe -ss my -n \"" + x509Name + "\" ";
Process p = Process.Start(path, param);
p.WaitForExit();
p.Close();
}
///
/// 从pfx文件读取证书信息
///
private void ReadPfxFile(string name, string password)
{
X509Certificate2 pc = new X509Certificate2(name + ".pfx", password);
Console.WriteLine("name:" + pc.SubjectName.Name);
Console.WriteLine("public:" + pc.PublicKey.ToString());
Console.WriteLine("private:" + pc.PrivateKey.ToString());
pc = null;
}
///
///使用私钥 RSA解密
///
public string RSADecrypt(string xmlPrivateKey, string m_strDecryptString)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(xmlPrivateKey);
byte[] rgb = Convert.FromBase64String(m_strDecryptString);
byte[] bytes = provider.Decrypt(rgb, false);
return new UnicodeEncoding().GetString(bytes);
}
///
///使用公钥 RSA加密
///
public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString)
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(xmlPublicKey);
byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString);
return Convert.ToBase64String(provider.Encrypt(bytes, false));
}
///
/// 根据私钥证书得到证书实体,得到实体后可以根据其公钥和私钥进行加解密
/// 加解密函数使用DEncrypt的RSACryption类
///
public static X509Certificate2 GetCertificateFromPfxFile(string pfxFileName,
string password)
{
try
{
return new X509Certificate2(pfxFileName, password, X509KeyStorageFlags.Exportable);
}
catch (Exception e)
{
Log.WriteLog("get certificate from pfx" + pfxFileName + " error:" + e.ToString() +
"GetCertificateFromPfxFile");
return null;
}
}
///
/// 到存储区获取证书
///
public static X509Certificate2 GetCertificateFromStore(string subjectName)
{
subjectName = "CN=" + subjectName;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection storecollection = (X509Certificate2Collection)store.Certificates;
foreach (X509Certificate2 x509 in storecollection)
{
if (x509.Subject == subjectName)
{
return x509;
}
}
store.Close();
store = null;
storecollection = null;
return null;
}
///
/// 根据公钥证书,返回证书实体
///
public static X509Certificate2 GetCertFromCerFile(string cerPath)
{
try
{
return new X509Certificate2(cerPath);
}
catch (Exception e)
{
Log.WriteLog(e.ToString() + "DataCertificate.LoadStudentPublicKey");
return null;
}
}
}
}