using System; using System.IO; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Threading; using BWP.ABCClient.Exceptions; using TSingSoft.WebPluginFramework.TimerTasks; namespace BWP.ABCClient { public class CertManager { public static CertManager MainSystemCertManager { get { return new CertManager("MainSystemABCCerts"); } } CertManager(string storeName) { _store = new X509Store(storeName, StoreLocation.LocalMachine); new StorePermission(StorePermissionFlags.AllFlags).Assert(); } private readonly X509Store _store; public CertManager():this("ABCCerts") { } volatile static object _lockObj = new object(); public void SetupPfx(Stream stream, string password) { if (!Monitor.TryEnter(_lockObj)) { throw new ApplicationException("另一名操作员正在导入证书,请稍后再试"); } try { _store.Open(OpenFlags.ReadWrite); using (var binaryReader = new BinaryReader(stream)) { var bytes = binaryReader.ReadBytes((int)stream.Length); var cert = new X509Certificate2(bytes, password); if (_store.Certificates.Find(X509FindType.FindBySerialNumber, cert.SerialNumber, false).Count == 0) { _store.Add(new X509Certificate2(bytes, password, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet)); } } _store.Close(); } finally { Monitor.Exit(_lockObj); } } public void SetupPfx(string fileName, string password) { using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { SetupPfx(stream, password); } } public X509Certificate2 Fetch(string merchantID) { return Fetch(X509FindType.FindBySubjectName, merchantID); } public X509Certificate2 Fetch(X509FindType findType, string findValue) { _store.Open(OpenFlags.ReadOnly); var certs = _store.Certificates.Find(findType, findValue, false); _store.Close(); if (certs.Count == 0) { throw new RSAException("找不到商户号对应的证书"); } if (certs.Count > 1) { throw new RSAException("同一个商户号有多张证书"); } return certs[0]; } public bool TryFetch(string merchantID, out X509Certificate2 cert) { cert = null; _store.Open(OpenFlags.ReadOnly); var certs = _store.Certificates.Find(X509FindType.FindBySubjectName, merchantID, false); _store.Close(); if (certs.Count == 0) { return false; } cert = certs[0]; return true; } public void Remove(string merchantID) { var cert = Fetch(merchantID); _store.Open(OpenFlags.ReadWrite); _store.Remove(cert); _store.Close(); } public void Remove(X509Certificate2 cert) { _store.Open(OpenFlags.ReadWrite); _store.Remove(cert); _store.Close(); } public void ClearAll() { _store.Open(OpenFlags.ReadWrite); _store.RemoveRange(_store.Certificates); _store.Close(); } public X509Certificate2Collection FetchAll() { _store.Open(OpenFlags.ReadWrite); var certs = _store.Certificates; _store.Close(); return certs; } public void Export(string merchantID, string password, Stream stream) { var cert = Fetch(merchantID); var bytes = cert.Export(X509ContentType.Pfx, password); stream.Write(bytes, 0, bytes.Length); } public void SetupABCPubKey(string fileName) { _store.Open(OpenFlags.ReadWrite); _store.Add(new X509Certificate2(fileName)); _store.Close(); } public X509Certificate2 GetABCPubKey() { _store.Open(OpenFlags.ReadOnly); var certs = _store.Certificates.Find(X509FindType.FindBySerialNumber, "7b97ca10275a0000d99d", false); if (certs.Count == 0) { throw new RSAException("找不到农行公钥"); } return certs[0]; } public X509Certificate2 GetABCTestPubKey() { _store.Open(OpenFlags.ReadOnly); var certs = _store.Certificates.Find(X509FindType.FindBySerialNumber, "50 3a ca 10 53 5b 00 00 02 7f", false); if (certs.Count == 0) { throw new RSAException("找不到农行公钥"); } return certs[0]; } } }