using System.Collections;
using System.Globalization;
using System.IO;
using System.Text;
using Common.DEncrypt;
using Email.Models;
using NHibernate;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
 using Org.BouncyCastle.X509;
 using Org.BouncyCastle.X509.Extension;
 using Common;
 namespace CA.Models
 {
     public static class CaOperator
     {
         /// <summary>
         /// 根证书
         /// </summary>
         public static readonly X509Certificate RootCert =
              new X509CertificateParser().ReadCertificate(Encoding.Default.GetBytes(
              “—–BEGIN CERTIFICATE—–\n” +
              “MIIBrDCCARWgAwIBAgIBATANBgkqhkiG9w0BAQUFADAcMRowGAYDVQQDDBHlronl\n” +
              “hahDQeagueivgeS5pjAgFw0xMzA4MTQxNzAwMTBaGA8yMDYzMDgxNjE3MDAxMFow\n” +
              “HDEaMBgGA1UEAwwR5a6J5YWoQ0HmoLnor4HkuaYwgZ0wDQYJKoZIhvcNAQEBBQAD\n” +
              “gYsAMIGHAoGBAIVzPUIiMfkLyDCoyAOKOhoSAjkW8X6GJK7DiLL5cC9R2iWhGB+p\n” +
              “lYWlaFC7MWK0HW7Dk3FygsbZcJXSe41npyY2MUUiXJ8GYj8H9JZ3dlLTKwAUbeen\n” +
              “/WtnpJStj5JqeeXz0po4huq7xExThxSuT7dNiC58Qmi977j7EYe5/K6vAgEDMA0G\n” +
              “CSqGSIb3DQEBBQUAA4GBABEdxlmihCWuB7J0pZ602Q6U/tlaiC5r9m03H21CoJG1\n” +
              “slryxg8Oy365/KKyysYIzx9VplT1D0dC+A3Gsn+DSGIb3j7UDXymkd03KbBHNe2C\n” +
              “ZLrAuesQIzOyv/sea/Mqs0jMwfJQROPSxEgWRHJBjf+kKzjSwqMWhl6Rvq84WkJ0\n” +
              “—–END CERTIFICATE—–“));
         /// <summary>
         /// 根证书私钥
         /// </summary>
         private static readonly AsymmetricKeyParameter RootKey =
             PrivateKeyFactory.CreateKey(Convert.FromBase64String(
             “MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAIVzPUIiMfkLyDCoyAOKOhoSAjkW8X6GJK7DiLL5cC9R2iWhGB+” +
             “plYWlaFC7MWK0HW7Dk3FygsbZcJXSe41npyY2MUUiXJ8GYj8H9JZ3dlLTKwAUbeen/WtnpJStj5JqeeXz0po4huq7xExThxSuT7dNiC58” +
             “Qmi977j7EYe5/K6vAgEDAoGAWPd+LBbL+10wIHCFV7F8EWFW0Ln2VFltydewd1D1dOE8GRYQFRu5A8Oa4HzLlyK+Sde3oPcB2eZLDox” +
             “SXkUaGHnC0IhtBwLB1LWHdt1fSPHE/VpdV5ktdkImrBJbeGtnZ5lD7KHLjb9JlnS7UB7QtGlQgkY9fNZFVoKuWwUNI3sCQQDy6Jsl/” +
             “WC4lwXLxxgnTxBGR9tiuNUrFJ7sN3dqmWjl68WarEZ8yKIGf+IVwRAOezbppmLor9dmd1/hz/QEm0XtAkEAjKRxL7uzyah6K+JMBBhVIj” +
             “uoqikPFySbGDMbJ2z043ME80BwyQz0FlYIjq0McZtxxekIKjZWFhBXVTwLLc2ziwJBAKHwZ26o6yW6A90vZW+KCtmFPOx7OMdjFJ16T” +
             “5xmRe6dLmcdhFMwbARVQWPWCrRSJJvEQfB1OkRPlUE1TVhng/MCQF3C9h/Sd9vFpsfsMq1ljhbScHFwtLoYZ2V3Z2+d+JeiA0zVoIY” +
             “IormOsF8eCEu89oPwsBwkOWQK5ON9XMkzzQcCQGnW8f/Z4Am8llagjpEGH3XXWPDqymj/4EbMDrN2e9KRq1QL1cmR2uH+Ek6qvZdmmtM” +
             “xFo6wZQ5wlX4hNTYqNfQ=”));
         /// <summary>
         /// 验证用户证书是否由CA 机构颁发
         /// </summary>
         /// <param name=”privKeyStr”>私钥字符串</param>
         /// <param name=”x509CertStr”>证书字符串</param>
         /// <returns></returns>
         public static bool VeryifyX509(string privKeyStr, string x509CertStr)
         {
             try
             {
                 var certObj = new X509CertificateParser().ReadCertificate(new MemoryStream(Encoding.Default.GetBytes(x509CertStr)));
                 var privKey = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privKeyStr));
                 //公钥 私钥是否相等
                 var pubKey = (RsaKeyParameters)certObj.GetPublicKey();
                 certObj.Verify(pubKey);
                 return pubKey.Exponent.Equals(privKey.PublicExponent);
             }
             catch
             {
                 return false;
             }
         }
         /// <summary>
         /// 生成证书
         /// </summary>
         /// <param name=”user”>用户对象</param>
         /// <param name=”serialNumber”>证书序列号</param>
         /// <param name=”startDate”>生效日期</param>
         /// <param name=”endDate”>过期日期</param>
         /// <param name=”algorithm”>算法  “SHA1WITHRSAENCRYPTION” 等等</param>
         /// <param name=”keyLength”>密钥长度 1024 2048 4096</param>
         /// <param name=”useAge”>用途 1 签名 2 交换 3  两者</param>
         /// <param name=”privKeyStr”>私钥字符串</param>
         /// <param name=”x509CertStr”>证书字符串</param>
         public static void NewX509Cert(Users user,
             BigInteger serialNumber,
             DateTime startDate,
             DateTime endDate,
             string algorithm,
             int keyLength,
             int useAge,
             out string privKeyStr,
             out string x509CertStr)
         {
             var r = new RsaKeyPairGenerator();
             r.Init(new RsaKeyGenerationParameters(
                         BigInteger.ValueOf(3),
                         new SecureRandom(),
                         keyLength,   //密钥长度  
                         25));
             var keys = r.GenerateKeyPair();
             var certGen = new X509V3CertificateGenerator();
             certGen.Reset();
             certGen.SetSerialNumber(serialNumber);
             certGen.SetIssuerDN(RootCert.SubjectDN);//颁发者
             certGen.SetNotBefore(startDate);
             certGen.SetNotAfter(endDate);
             certGen.SetSubjectDN(RawToX509Name(user));//颁发给
             certGen.SetPublicKey(keys.Public);
             //ca签名算法
             certGen.SetSignatureAlgorithm(algorithm);
             //根证书
             certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier,
                 false, new AuthorityKeyIdentifierStructure(RootCert));
             certGen.AddExtension(X509Extensions.BasicConstraints,
                 true, new BasicConstraints(true));
             certGen.AddExtension(X509Extensions.SubjectKeyIdentifier,
                 false, new SubjectKeyIdentifierStructure(keys.Public));
             
             //密钥用途
             int iuseAge;
             switch (useAge)
             {
                 case 1:
                     iuseAge = KeyUsage.DigitalSignature;
                     break;
                 case 2:
                     iuseAge = KeyUsage.DataEncipherment;
                     break;
                 default:
                     iuseAge = KeyUsage.DigitalSignature | KeyUsage.DataEncipherment;
                     break;
             }
certGen.AddExtension(X509Extensions.KeyUsage, true,new KeyUsage(iuseAge));
             //使用根证书私钥来签名证书 这样客户端安装根证书后 可验证证书的合法性
             var cert = certGen.Generate(RootKey);
             x509CertStr = RawCert(cert);
             privKeyStr = RawPrivateKey(keys);
         }
         /// <summary>
         /// 生成Pfx密钥文件
         /// </summary>
         /// <param name=”privKeyStr”>私钥</param>
         /// <param name=”x509CertStr”>证书</param>
         /// <param name=”pwd”>密码</param>
         /// <returns>pfx文件</returns>
         public static string NewX509Pfx(string privKeyStr, string x509CertStr, string pwd)
         {
             var certObj = new X509CertificateParser().ReadCertificate(new MemoryStream(Encoding.Default.GetBytes(x509CertStr)));
             var privKey = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privKeyStr));
             var certEntry = new X509CertificateEntry(certObj);
             var store = new Pkcs12StoreBuilder().SetUseDerEncoding(true).Build();
             store.SetCertificateEntry(“安全CA用户身份证书”, certEntry);   //设置证书  
             store.SetKeyEntry(“安全CA用户身份证书”, new AsymmetricKeyEntry(privKey),
                 new[] { certEntry });   //设置私钥  
             using (var tx = new MemoryStream())
             {
                 store.Save(tx, pwd.ToCharArray(), new SecureRandom());
                 return Convert.ToBase64String(tx.ToArray());
             }
         }
         /// <summary>
         /// 
         /// </summary>
         /// <param name=”user”></param>
         /// <returns></returns>
         private static X509Name RawToX509Name(Users user)
         {
             var attrs = new Hashtable();
             IList order = new ArrayList();
             attrs[X509Name.OU] = user.Unit == null ? string.Empty : user.Unit.FullUnitName;
             attrs[X509Name.CN] = user.UserNameWithAlias + “用户证书”;//证书名字
             attrs[X509Name.O] = SettingCopyright.Organization;
             attrs[X509Name.C] = “Zh”;
             attrs[X509Name.UID] = user.UID.ToString(CultureInfo.InvariantCulture);
             attrs[X509Name.T] = user.UserName;
             order.Add(X509Name.OU);
             order.Add(X509Name.CN);
             order.Add(X509Name.O);
             order.Add(X509Name.C);
             order.Add(X509Name.UID);
             order.Add(X509Name.T);
return new X509Name(order, attrs);
}
         /// <summary>
         /// 生成私钥base64字符串
         /// </summary>
         /// <param name=”x509CertStr”>证书字符串</param>
         /// <returns>私钥字符串</returns>
         private static string RawPrivateKey(AsymmetricCipherKeyPair x509CertStr)
         {
             var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(x509CertStr.Private);
             return Convert.ToBase64String(privateKeyInfo.ToAsn1Object().GetDerEncoded());
         }
         /// <summary>
         /// 生成证书
         /// </summary>
         /// <param name=”v3Cert”>证书对象</param>
         /// <returns>证书字符串</returns>
         private static string RawCert(X509Certificate v3Cert)
         {
             string cert;
             using (var tx = new StringWriter())
             {
                 var pemWriter = new PemWriter(tx);
                 pemWriter.WriteObject(v3Cert);
                 pemWriter.Writer.Flush();
                 cert = tx.ToString();
             }
             return cert;
         }
         /// <summary>
         /// 生成认证原文并保存到数据库
         /// </summary>
         /// <param name=”session”>nhibernate session对象</param>
         /// <param name=”user”>用户对象</param>
         /// <param name=”cert”>证书对象</param>
         /// <returns>生成认证原文</returns>
         public static string NewOriginalCode(ISession session,Users user, CaCertificate cert)
         {
             var guid = Guid.NewGuid().ToString().Replace(“-“, “”);
             //前32位为guid 后面的为用户密码
             guid +=user.Pwd;
             guid = guid.ToLower();
             var caRandom = new CaRandom
             {
                 UID = cert.UID,
                 Random = guid
             };
             session.SaveOrUpdate(caRandom);
             session.Flush();
             return MacAtivex.EnPubKey(guid, cert.Cert);
         }
         /// <summary>
         ///  生成认证用户 认证原文
         /// </summary>
         /// <param name=”session”></param>
         /// <param name=”uid”></param>
         /// <param name=”code”></param>
         /// <returns></returns>
         public static bool VerifyOriginalCode(ISession session, int uid, string code)
         {
             var r = session.QueryOver<CaRandom>().Where(o => o.UID == uid)
                   .Take(1).SingleOrDefault();
             return r != null && r.Random.Equals(code);
         }
     }
 }
                
