runliuv

runliuv@cnblogs

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

微信 连接被意外关闭、密钥集不存在,p12私钥证书的使用

 

报错1: 基础连接已关闭 连接被意外关闭 。

报错2: 密钥集不存在 。

其实是权限问题导致没访问到证书。

 

微信的.P12私钥证书,如果是在WINDOWS上,需要先导入到系统库,分配权限,才能在代码中正常使用。 

 

 

解决方法是

1.开始-运行 输入mmc

2.文件-添加/删除管理单元 在可用的管理单元中选择 证书 添加到右侧 弹框选择计算机帐户

3.展开个人-证书 选择你导入的证书或从这里右键导入

4.右击证书-所有任务-管理私钥

5.根据你的实际情况,给对应用户名添加权限,比如你的程序部署在IIS上,没指定其它用户名运行,那就给IIS_IUser 勾选读取就行 。如果你指定了用户名运行,比如用户名是:jk,那就给jk分配权限。(还有种偷懒的做法,直接分配给Everyone用户权限。)

 

如果是域用户,把自己的域用户名加入即正常。

 

--

使用证书的2种方法:

1.直接路径读取。(这种每调用一次,会在C盘生成一个文件,:C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys)

注意:X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable。这三个ENUM要加上。

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);

 

--

 

posted on 2015-02-05 19:03  runliuv  阅读(892)  评论(0)    收藏  举报