|
1 | 1 | using Codecepticon.Utils; |
2 | | -using Org.BouncyCastle.Asn1; |
3 | | -using Org.BouncyCastle.Asn1.X509; |
4 | | -using Org.BouncyCastle.Crypto; |
5 | | -using Org.BouncyCastle.Crypto.Generators; |
6 | | -using Org.BouncyCastle.Crypto.Operators; |
7 | | -using Org.BouncyCastle.Crypto.Prng; |
8 | | -using Org.BouncyCastle.Math; |
9 | | -using Org.BouncyCastle.Pkcs; |
10 | | -using Org.BouncyCastle.Security; |
11 | | -using Org.BouncyCastle.Utilities; |
12 | | -using Org.BouncyCastle.X509; |
13 | 2 | using System; |
14 | 3 | using System.Collections.Generic; |
15 | 4 | using System.IO; |
| 5 | +using System.Security.Cryptography; |
| 6 | +using System.Security.Cryptography.X509Certificates; |
16 | 7 |
|
17 | 8 | namespace Codecepticon.Modules.Sign |
18 | 9 | { |
19 | 10 | class CertificateManager |
20 | 11 | { |
21 | | - private const string SignatureAlgorithm = "SHA256WithRSA"; |
22 | | - |
23 | 12 | private const int KeyLength = 2048; |
24 | 13 |
|
25 | 14 | public bool GenerateCertificate(string Subject, string Issuer, DateTime NotBefore, DateTime NotAfter, string Password, string PfxOutput) |
26 | 15 | { |
27 | | - // https://mcse.cloud/create-a-self-signed-certificate-with-bouncy-castle-and-c/ |
28 | | - Logger.Debug("Initialising random generators and certificate generators..."); |
29 | | - SecureRandom secureRandom = new SecureRandom(new CryptoApiRandomGenerator()); |
30 | | - |
31 | | - X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); |
32 | | - |
33 | | - // Create and set serial number. |
34 | | - Logger.Verbose("Setting up certificate properties..."); |
35 | | - BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), secureRandom); |
36 | | - certificateGenerator.SetSerialNumber(serialNumber); |
37 | | - |
38 | | - Logger.Debug("Creating Subject: " + Subject); |
39 | | - X509Name subjectDN = new X509Name(true, Subject); |
40 | | - certificateGenerator.SetSubjectDN(subjectDN); |
41 | | - |
42 | | - Logger.Debug("Creating Issuer: " + Issuer); |
43 | | - X509Name issuerDN = new X509Name(true, Issuer); |
44 | | - certificateGenerator.SetIssuerDN(issuerDN); |
45 | | - |
46 | | - Logger.Debug("Setting NotBefore: " + NotBefore); |
47 | | - certificateGenerator.SetNotBefore(NotBefore); |
48 | | - Logger.Debug("Setting NotAfter: " + NotAfter); |
49 | | - certificateGenerator.SetNotAfter(NotAfter); |
50 | | - |
51 | | - KeyGenerationParameters keyGeneration = new KeyGenerationParameters(secureRandom, KeyLength); |
52 | | - |
53 | | - // Create RSA key. |
54 | | - Logger.Verbose("Generating RSA keypair..."); |
55 | | - RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator(); |
56 | | - keyPairGenerator.Init(keyGeneration); |
57 | | - AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateKeyPair(); |
58 | | - |
59 | | - // Add the public/private keys to the certificate generator. |
60 | | - Logger.Debug("Setting public key..."); |
61 | | - certificateGenerator.SetPublicKey(keyPair.Public); |
62 | | - ISignatureFactory signatureFactory = new Asn1SignatureFactory(SignatureAlgorithm, keyPair.Private, secureRandom); |
63 | | - X509Certificate certificate = certificateGenerator.Generate(signatureFactory); |
64 | | - |
65 | | - Logger.Debug("Creating keystore..."); |
66 | | - Pkcs12Store keyStore = new Pkcs12Store(); |
67 | | - X509CertificateEntry certificateEntry = new X509CertificateEntry(certificate); |
68 | | - keyStore.SetCertificateEntry(certificate.SubjectDN.ToString(), certificateEntry); |
69 | | - keyStore.SetKeyEntry(certificate.SubjectDN.ToString(), new AsymmetricKeyEntry(keyPair.Private), new[] { certificateEntry }); |
70 | | - |
71 | | - // Convert to .NET Certificate. |
72 | | - Logger.Debug("Converting to a .NET certificate..."); |
73 | | - MemoryStream stream = new MemoryStream(); |
74 | | - keyStore.Save(stream, Password.ToCharArray(), secureRandom); |
| 16 | + // https://stackoverflow.com/a/48210587/2445959 |
| 17 | + RSA keyPair = RSA.Create(KeyLength); |
| 18 | + |
| 19 | + Logger.Verbose("Generating issuer certificate..."); |
| 20 | + Logger.Verbose("Issuer is " + Issuer); |
| 21 | + X509Certificate2 certificateIssuer = GenerateIssuerCertificate(Issuer, NotBefore, NotAfter); |
| 22 | + |
| 23 | + Logger.Info("Generating signing certificate..."); |
| 24 | + Logger.Verbose("Subject is " + Subject); |
| 25 | + CertificateRequest certRequest = new(Subject, keyPair, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); |
| 26 | + certRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false)); |
| 27 | + //certRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.8") }, true)); |
| 28 | + certRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certRequest.PublicKey, false)); |
| 29 | + X509Certificate2 cert = certRequest.Create(certificateIssuer, NotBefore, NotAfter, new byte[] { 1, 2, 3, 4 }); |
| 30 | + |
| 31 | + // Add the private key back to the certificate. |
| 32 | + X509Certificate2 certificate = cert.CopyWithPrivateKey(keyPair); |
| 33 | + |
| 34 | + Logger.Info("Exporting certificate to file..."); |
| 35 | + File.WriteAllBytes(PfxOutput, certificate.Export(X509ContentType.Pfx, Password)); |
| 36 | + |
| 37 | + return true; |
| 38 | + } |
75 | 39 |
|
76 | | - System.Security.Cryptography.X509Certificates.X509Certificate2 netCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(stream.ToArray(), Password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet | System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable); |
| 40 | + private X509Certificate2 GenerateIssuerCertificate(string Issuer, DateTime NotBefore, DateTime NotAfter) |
| 41 | + { |
| 42 | + RSA keyPair = RSA.Create(KeyLength); |
77 | 43 |
|
78 | | - Logger.Verbose("Writing certificate to " + PfxOutput); |
79 | | - File.WriteAllBytes(PfxOutput, netCertificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pfx, Password)); |
80 | | - return true; |
| 44 | + CertificateRequest issuerRequest = new(Issuer, keyPair, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); |
| 45 | + issuerRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true)); |
| 46 | + issuerRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(issuerRequest.PublicKey, false)); |
| 47 | + return issuerRequest.CreateSelfSigned(NotBefore, NotAfter); |
81 | 48 | } |
82 | 49 |
|
83 | 50 | public bool CheckPfxPassword(string pfxFile, string password) |
84 | 51 | { |
85 | 52 | try |
86 | 53 | { |
87 | | - Pkcs12Store keyStore = new Pkcs12Store(File.OpenRead(pfxFile), password.ToCharArray()); |
88 | | - } catch (Exception e) |
| 54 | + X509Certificate2 certificate = new(pfxFile, password); |
| 55 | + } |
| 56 | + catch (Exception e) |
89 | 57 | { |
90 | 58 | return false; |
91 | 59 | } |
92 | | - |
| 60 | + |
93 | 61 | return true; |
94 | 62 | } |
95 | 63 |
|
96 | | - public System.Security.Cryptography.X509Certificates.X509Certificate GetCertificateFromFile(string signedFile) |
| 64 | + public X509Certificate GetCertificateFromFile(string signedFile) |
97 | 65 | { |
98 | | - return System.Security.Cryptography.X509Certificates.X509Certificate2.CreateFromSignedFile(signedFile); |
| 66 | + return X509Certificate.CreateFromSignedFile(signedFile); |
99 | 67 | } |
100 | 68 | } |
101 | 69 | } |
0 commit comments