You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

165 lines
4.2 KiB

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];
}
}
}