Advertisement
Guest User

Untitled

a guest
Feb 6th, 2020
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.11 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Security.AccessControl;
  5. using System.Security.Cryptography;
  6. using System.Security.Principal;
  7. using Org.BouncyCastle.Asn1;
  8. using Org.BouncyCastle.Asn1.Pkcs;
  9. using Org.BouncyCastle.Asn1.X509;
  10. using Org.BouncyCastle.Crypto;
  11. using Org.BouncyCastle.Crypto.Generators;
  12. using Org.BouncyCastle.Crypto.Parameters;
  13. using Org.BouncyCastle.Crypto.Prng;
  14. using Org.BouncyCastle.Math;
  15. using Org.BouncyCastle.OpenSsl;
  16. using Org.BouncyCastle.Pkcs;
  17. using Org.BouncyCastle.Security;
  18. using Org.BouncyCastle.Utilities;
  19. using Org.BouncyCastle.X509;
  20.  
  21. namespace EndpointManager.SSL
  22. {
  23.     // From https://granadacoder.wordpress.com/2016/11/04/service-bus-and-custom-self-signed-certificates-with-a-high-availabilitymultiple-computing-nodes-in-the-farm/
  24.     /*
  25.     <?xml version=”1.0″ encoding=”utf-8″?>
  26.     <packages>
  27.     <package id=”BouncyCastle” version=”1.8.1″ targetFramework=”net45″ />
  28.     </packages>
  29.     */
  30.  
  31.     /* Notes, because this code actually places certificates IN YOUR CERTIFICATE STORE, it needs to be run “As Administrator” */
  32.  
  33.     public class BouncyCastleMaker
  34.     {
  35.         public const string DefaultIssuer = "UniversalSearchServerLocalCA";
  36.  
  37.         public void SetupCertificates(string domain, string siteName, out System.Security.Cryptography.X509Certificates.X509Certificate2 cert2, out string storeName)
  38.         {
  39.             string issuerCnName = string.Format("CN={0}", DefaultIssuer);
  40.             string certName = "(Universal Search) " + siteName.Trim();
  41.             List<string> subjectAlternateNames = new List<string>();
  42.             subjectAlternateNames.Add(domain);
  43.             string password = Guid.NewGuid().ToString();
  44.             AsymmetricKeyParameter caPrivKey = GenerateCACertificate(issuerCnName, password);
  45.             System.Security.Cryptography.X509Certificates.X509Certificate2 cert = GenerateSelfSignedCertificate(certName, subjectAlternateNames, password, issuerCnName, caPrivKey);
  46.  
  47.             var store = System.Security.Cryptography.X509Certificates.StoreName.My;
  48.             storeName = "MY";
  49.             AddAccessToCertificate(cert);
  50.             AddCertToStore(cert, store, System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine);
  51.            
  52.            
  53.             cert2 = cert;
  54.  
  55.         }
  56.  
  57.         public System.Security.Cryptography.X509Certificates.X509Certificate2 GenerateSelfSignedCertificate(string certificateName, List<string> subjectAlternateNames,  string privateKeyFilePassword, string issuerName, AsymmetricKeyParameter issuerPrivKey)
  58.         {
  59.             return GenerateSelfSignedCertificate(certificateName, subjectAlternateNames,  privateKeyFilePassword, issuerName, issuerPrivKey, 2048);
  60.         }
  61.  
  62.         public System.Security.Cryptography.X509Certificates.X509Certificate2 GenerateSelfSignedCertificate(string certificateName, List<string> subjectAlternateNames,  string privateKeyFilePassword, string issuerName, AsymmetricKeyParameter issuerPrivKey, int keyStrength)
  63.         {
  64.             string subjectName = string.Format("CN={0}", certificateName);
  65.  
  66.             // Generating Random Numbers
  67.             var randomGenerator = new CryptoApiRandomGenerator();
  68.             var random = new SecureRandom(randomGenerator);
  69.  
  70.             // The Certificate Generator
  71.             X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
  72.  
  73.             // Serial Number
  74.             var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
  75.             certificateGenerator.SetSerialNumber(serialNumber);
  76.  
  77.             // Signature Algorithm
  78.             const string SignatureAlgorithm = "SHA256WithRSA";
  79.             certificateGenerator.SetSignatureAlgorithm(SignatureAlgorithm);
  80.  
  81.             // Issuer and Subject Name
  82.             var subjectDN = new X509Name(subjectName);
  83.  
  84.             // original code var issuerDN = issuerName;
  85.             var issuerDN = new X509Name(issuerName);
  86.             certificateGenerator.SetIssuerDN(issuerDN);
  87.             certificateGenerator.SetSubjectDN(subjectDN);
  88.  
  89.             // Valid For
  90.             var notBefore = DateTime.UtcNow.Date;
  91.             var notAfter = notBefore.AddYears(2);
  92.  
  93.             certificateGenerator.SetNotBefore(notBefore);
  94.             certificateGenerator.SetNotAfter(notAfter);
  95.  
  96.             KeyUsage keyUsage = new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment);
  97.             certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, keyUsage);
  98.  
  99.             // Add the “Extended Key Usage” attribute, specifying “server authentication”.
  100.             var usages = new[] { KeyPurposeID.IdKPServerAuth };
  101.             certificateGenerator.AddExtension(
  102.             X509Extensions.ExtendedKeyUsage.Id,
  103.             false,
  104.             new ExtendedKeyUsage(usages));
  105.  
  106.             /* DNS Name=*.fullyqualified.domainname.com */
  107.             if (subjectAlternateNames.Count <= 1)
  108.             {
  109.                 /* the <=1 is for the simple reason of showing an alternate syntax .. */
  110.                 foreach (string subjectAlternateName in subjectAlternateNames)
  111.                 {
  112.                     GeneralName altName = new GeneralName(GeneralName.DnsName, subjectAlternateName);
  113.                     GeneralNames subjectAltName = new GeneralNames(altName);
  114.                     certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, subjectAltName);
  115.                 }
  116.             }
  117.             else
  118.             {
  119.                 //Asn1Encodable[] ansiEncodeSubjectAlternativeNames = new Asn1Encodable[]
  120.                 // {
  121.                 // //new GeneralName(GeneralName.DnsName, “*.fullyqualified.domainname.com”),
  122.                 // new GeneralName(GeneralName.DnsName, “*.fullyqualified.domainname.com”)
  123.                 // };
  124.  
  125.                 List<Asn1Encodable> asn1EncodableList = new List<Asn1Encodable>();
  126.                 foreach (string subjectAlternateName in subjectAlternateNames)
  127.                 {
  128.                     asn1EncodableList.Add(new GeneralName(GeneralName.DnsName, subjectAlternateName));
  129.                 }
  130.  
  131.                 DerSequence subjectAlternativeNamesExtension = new DerSequence(asn1EncodableList.ToArray());
  132.                 certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false, subjectAlternativeNamesExtension);
  133.             }
  134.  
  135.             // Subject Public Key
  136.             AsymmetricCipherKeyPair subjectKeyPair;
  137.             var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
  138.             var keyPairGenerator = new RsaKeyPairGenerator();
  139.             keyPairGenerator.Init(keyGenerationParameters);
  140.             subjectKeyPair = keyPairGenerator.GenerateKeyPair();
  141.  
  142.             certificateGenerator.SetPublicKey(subjectKeyPair.Public);
  143.  
  144.             // Generating the Certificate
  145.             var issuerKeyPair = subjectKeyPair;
  146.  
  147.             // selfsign certificate
  148.             var certificate = certificateGenerator.Generate(issuerPrivKey, random);
  149.  
  150.             // correcponding private key
  151.             PrivateKeyInfo pinfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
  152.             // merge into X509Certificate2
  153.            
  154.             // As per
  155.             // - https://stackoverflow.com/questions/4198493/x509certificate2-has-private-key-not-exportable
  156.             // - https://docs.microsoft.com/en-us/archive/blogs/webapps/a-fatal-error-occurred-when-attempting-to-access-the-ssl-server-credential-private-key-0x8009030d
  157.             // must set exportable flag
  158.             var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded(),privateKeyFilePassword, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.UserKeySet);
  159.  
  160.             var seq = (Asn1Sequence)Asn1Object.FromByteArray(pinfo.ParsePrivateKey().GetDerEncoded());
  161.             if (seq.Count != 9)
  162.             {
  163.                 throw new PemException("malformed sequence in RSA private key");
  164.             }
  165.  
  166.             var rsa = new RsaPrivateKeyStructure(seq);
  167.             RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
  168.             rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
  169.  
  170.             x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
  171.             return x509;
  172.         }
  173.  
  174.         public AsymmetricKeyParameter GenerateCACertificate(string subjectName, string privateKeyFilePassword,  int keyStrength = 2048)
  175.         {
  176.             // Generating Random Numbers
  177.             var randomGenerator = new CryptoApiRandomGenerator();
  178.             var random = new SecureRandom(randomGenerator);
  179.  
  180.             // The Certificate Generator
  181.             var certificateGenerator = new X509V3CertificateGenerator();
  182.  
  183.             // Serial Number
  184.             var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
  185.             certificateGenerator.SetSerialNumber(serialNumber);
  186.  
  187.             // Signature Algorithm
  188.             const string SignatureAlgorithm = "SHA256WithRSA";
  189.             certificateGenerator.SetSignatureAlgorithm(SignatureAlgorithm);
  190.  
  191.             // Issuer and Subject Name
  192.             var subjectDN = new X509Name(subjectName);
  193.             var issuerDN = subjectDN;
  194.             certificateGenerator.SetIssuerDN(issuerDN);
  195.             certificateGenerator.SetSubjectDN(subjectDN);
  196.  
  197.             // Valid For
  198.             var notBefore = DateTime.UtcNow.Date;
  199.             var notAfter = notBefore.AddYears(2);
  200.  
  201.             certificateGenerator.SetNotBefore(notBefore);
  202.             certificateGenerator.SetNotAfter(notAfter);
  203.  
  204.             KeyUsage keyUsage = new KeyUsage(KeyUsage.KeyCertSign | KeyUsage.CrlSign);
  205.             certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, keyUsage);
  206.  
  207.             // Subject Public Key
  208.             AsymmetricCipherKeyPair subjectKeyPair;
  209.             var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
  210.             var keyPairGenerator = new RsaKeyPairGenerator();
  211.             keyPairGenerator.Init(keyGenerationParameters);
  212.             subjectKeyPair = keyPairGenerator.GenerateKeyPair();
  213.  
  214.             certificateGenerator.SetPublicKey(subjectKeyPair.Public);
  215.  
  216.             // Generating the Certificate
  217.             var issuerKeyPair = subjectKeyPair;
  218.  
  219.             // selfsign certificate
  220.             Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
  221.             System.Security.Cryptography.X509Certificates.X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded(), privateKeyFilePassword, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.UserKeySet);
  222.  
  223.             #region Private Key
  224.  
  225.             // correcponding private key
  226.             PrivateKeyInfo pinfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
  227.  
  228.             var seq = (Asn1Sequence)Asn1Object.FromByteArray(pinfo.ParsePrivateKey().GetDerEncoded());
  229.             if (seq.Count != 9)
  230.             {
  231.                 throw new PemException("malformed sequence in RSA private key");
  232.             }
  233.  
  234.             var rsa = new RsaPrivateKeyStructure(seq);
  235.             RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
  236.             rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
  237.  
  238.             x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
  239.             #endregion
  240.             // Add CA certificate to Root store
  241.             AddAccessToCertificate(x509);
  242.             AddCertToStore(x509, System.Security.Cryptography.X509Certificates.StoreName.Root, System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine);
  243.  
  244.             return issuerKeyPair.Private;
  245.         }
  246.  
  247.         public void AddCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
  248.         {
  249.             System.Security.Cryptography.X509Certificates.X509Store store = new System.Security.Cryptography.X509Certificates.X509Store(st, sl);
  250.             store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadWrite);
  251.             store.Add(cert);
  252.             store.Close();
  253.         }
  254.  
  255.         private static void AddAccessToCertificate(System.Security.Cryptography.X509Certificates.X509Certificate2 cert)
  256.         {
  257.             RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
  258.  
  259.             if (rsa != null)
  260.             {
  261.                 if (TryFindKeyLocation(rsa.CspKeyContainerInfo.UniqueKeyContainerName, out string keyfilepath))
  262.                 {
  263.  
  264.                     FileInfo file = new FileInfo(keyfilepath + "\\" +
  265.                         rsa.CspKeyContainerInfo.UniqueKeyContainerName);
  266.  
  267.                     FileSecurity fs = file.GetAccessControl();
  268.                     var sid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
  269.                     fs.AddAccessRule(new FileSystemAccessRule(sid,
  270.                     FileSystemRights.FullControl, AccessControlType.Allow));
  271.  
  272.                     file.SetAccessControl(fs);
  273.                 } else
  274.                 {
  275.                     throw new Exception(keyfilepath);
  276.                 }
  277.             }
  278.         }
  279.  
  280.         private static bool TryFindKeyLocation(string keyFileName, out string location)
  281.         {
  282.             string text1 =
  283.             Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
  284.             string text2 = text1 + @"\Microsoft\Crypto\RSA\MachineKeys";
  285.             string[] textArray1 = Directory.GetFiles(text2, keyFileName);
  286.             if (textArray1.Length > 0)
  287.             {
  288.                 location = text2;
  289.                 return true;
  290.             }
  291.             string text3 =
  292.             Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
  293.             string text4 = text3 + @"\Microsoft\Crypto\RSA\";
  294.             textArray1 = Directory.GetDirectories(text4);
  295.             if (textArray1.Length > 0)
  296.             {
  297.                 foreach (string text5 in textArray1)
  298.                 {
  299.                     textArray1 = Directory.GetFiles(text5, keyFileName);
  300.                     if (textArray1.Length != 0)
  301.                     {
  302.                         location = text5;
  303.                         return true;
  304.                     }
  305.                 }
  306.             }
  307.             location = "Private key exists but is not accessible";
  308.             return false;
  309.         }
  310.     }
  311. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement