微信 连接被意外关闭、密钥集不存在,p12私钥证书的使用
报错1: 基础连接已关闭 连接被意外关闭 。
报错2: 密钥集不存在 。
其实是权限问题导致没访问到证书。
微信的.P12私钥证书,如果是在WINDOWS上,需要先导入到系统库,分配权限,才能在代码中正常使用。
解决方法是
1.开始-运行 输入mmc
2.文件-添加/删除管理单元 在可用的管理单元中选择 证书 添加到右侧 弹框选择计算机帐户
3.展开个人-证书 选择你导入的证书或从这里右键导入
4.右击证书-所有任务-管理私钥
5.根据你的实际情况,给对应用户名添加权限,比如你的程序部署在IIS上,没指定其它用户名运行,那就给IIS_IUser 勾选读取就行 。如果你指定了用户名运行,比如用户名是:jk,那就给jk分配权限。(还有种偷懒的做法,直接分配给Everyone用户权限。)
如果是域用户,把自己的域用户名加入即正常。
--
使用证书的2种方法:
X509Certificate2 x509 = new X509Certificate2(p12FullName, hfMchId, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
2,从Windows证书库中读取
using System.Security.Cryptography.X509Certificates; namespace CommonUtils { public class CertUtil { /// <summary> /// 使用证书commonName来查找。(也可以用指纹或序列号来找) /// </summary> /// <param name="commonName"></param> /// <param name="storeName"></param> /// <returns></returns> public static X509Certificate2 GetCertificate(string commonName, StoreName storeName) { X509Certificate2 certificate = null; string targetName = $"CN={commonName}"; // Look for a certificate in the local machine store. // We will search for a certificate that has a CN (common name) that matches // the currently logged-in user. using (var store = new X509Store(storeName, StoreLocation.LocalMachine)) { store.Open(OpenFlags.MaxAllowed); foreach (var cert in store.Certificates) { var subjectNames = cert.SubjectName.Name.Split(','); foreach (var subjectName in subjectNames) { if (string.IsNullOrWhiteSpace(subjectName)) continue; //要TRIM,有的证书有空格 if (subjectName.Trim()== targetName) { certificate = cert; break; } } if (certificate != null) { break; } } } return certificate; } } }
使用:
X509Certificate2 clientCer = CertUtil.GetCertificate("SIZZZ", StoreName.My);
if (clientCer == null)
{
clientCer = CertUtil.GetCertificate("SIZZZ", StoreName.Root);
}
--
如果你只是用证书里的私钥签名,可以把证书里的私钥读取出来,存到配置文件或数据库。
转成PKCS1(需要 nuget引用 BouncyCastle 或 Portable.BouncyCastle ):
public string xmlToPem(RSACryptoServiceProvider rsa2) { string priKey = null; var p = rsa2.ExportParameters(true); var key = new RsaPrivateCrtKeyParameters( new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D), new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ), new BigInteger(1, p.InverseQ)); using (TextWriter sw = new StringWriter()) { var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw); pemWriter.WriteObject(key); pemWriter.Writer.Flush(); priKey = sw.ToString(); } return priKey; }
使用:
txtPemPrivateKey.Text = xmlToPem((RSACryptoServiceProvider)x509.PrivateKey);
或是转成.NET XML 格式:
x509.PrivateKey.ToXmlString(true);
--