Skip to content

Commit fc51ecc

Browse files
Remove X509Certificate2 usage, refactor certConverter usage to cryptoObjectFormatter usage
1 parent 7930e17 commit fc51ecc

File tree

9 files changed

+53
-110
lines changed

9 files changed

+53
-110
lines changed

RemoteFile/ImplementedStoreTypes/DER/DERCertificateStoreSerializer.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
using Keyfactor.PKI.X509;
1818
using Keyfactor.Extensions.Orchestrator.RemoteFile.RemoteHandlers;
1919
using Keyfactor.Extensions.Orchestrator.RemoteFile.Models;
20-
20+
using Keyfactor.PKI.Extensions;
2121
using Microsoft.Extensions.Logging;
2222

2323
using Org.BouncyCastle.Crypto;
@@ -49,12 +49,12 @@ public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContentBytes, s
4949

5050
if (String.IsNullOrEmpty(SeparatePrivateKeyFilePath))
5151
{
52-
store.SetCertificateEntry(CertificateConverterFactory.FromBouncyCastleCertificate(certificate.Certificate).ToX509Certificate2().Thumbprint, certificate);
52+
store.SetCertificateEntry(certificate.Certificate.Thumbprint(), certificate);
5353
}
5454
else
5555
{
5656
AsymmetricKeyEntry keyEntry = GetPrivateKey(storePassword ?? string.Empty, remoteHandler);
57-
store.SetKeyEntry(CertificateConverterFactory.FromBouncyCastleCertificate(certificate.Certificate).ToX509Certificate2().Thumbprint, keyEntry, new X509CertificateEntry[] { certificate });
57+
store.SetKeyEntry(certificate.Certificate.Thumbprint(), keyEntry, new X509CertificateEntry[] { certificate });
5858
}
5959

6060
// Second Pkcs12Store necessary because of an obscure BC bug where creating a Pkcs12Store without .Load (code above using "Set" methods only) does not set all internal hashtables necessary to avoid an error later
@@ -94,6 +94,7 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
9494
throw new RemoteFileException($"DER certificate store has a private key at {SeparatePrivateKeyFilePath}, but no private key was passed with the certificate to this job.");
9595
}
9696

97+
// this still needs refactored to CryptographicObjectFormatter
9798
CertificateConverter certConverter = CertificateConverterFactory.FromBouncyCastleCertificate(certificateStore.GetCertificate(alias).Certificate);
9899
certificateBytes = certConverter.ToDER(string.IsNullOrEmpty(storePassword) ? string.Empty : storePassword);
99100

@@ -140,9 +141,7 @@ private X509CertificateEntry GetCertificate(byte[] storeContentBytes)
140141

141142
try
142143
{
143-
CertificateConverter converter = CertificateConverterFactory.FromDER(storeContentBytes);
144-
X509Certificate bcCert = converter.ToBouncyCastleCertificate();
145-
certificateEntry = new X509CertificateEntry(bcCert);
144+
certificateEntry = new X509CertificateEntry(new X509Certificate(storeContentBytes));
146145
}
147146
catch (Exception ex)
148147
{

RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
using System.Collections.Generic;
1010
using System.Text;
1111
using System.IO;
12-
12+
using System.Linq;
1313
using Newtonsoft.Json;
1414

1515
using Keyfactor.Logging;
1616
using Keyfactor.PKI.PrivateKeys;
17-
using Keyfactor.PKI.X509;
1817
using Keyfactor.PKI.PEM;
1918
using Keyfactor.Extensions.Orchestrator.RemoteFile.RemoteHandlers;
2019
using Keyfactor.Extensions.Orchestrator.RemoteFile.Models;
@@ -26,7 +25,8 @@
2625
using Org.BouncyCastle.Pkcs;
2726
using Org.BouncyCastle.X509;
2827
using System.Security.Cryptography;
29-
using Org.BouncyCastle.OpenSsl;
28+
using Keyfactor.PKI.CryptographicObjects.Formatters;
29+
using Keyfactor.PKI.Extensions;
3030
using Org.BouncyCastle.Crypto.Parameters;
3131
using Org.BouncyCastle.Asn1.X9;
3232

@@ -74,15 +74,15 @@ public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContentBytes, s
7474
{
7575
foreach(X509CertificateEntry certificate in certificates)
7676
{
77-
store.SetCertificateEntry(CertificateConverterFactory.FromBouncyCastleCertificate(certificate.Certificate).ToX509Certificate2().Thumbprint, certificate);
77+
store.SetCertificateEntry(certificate.Certificate.Thumbprint(), certificate);
7878
}
7979
}
8080
else
8181
{
8282
PrivateKeyTypeEnum privateKeyType;
8383
AsymmetricKeyEntry keyEntry = GetPrivateKey(storeContents, storePassword ?? string.Empty, remoteHandler, out privateKeyType);
8484

85-
store.SetKeyEntry(CertificateConverterFactory.FromBouncyCastleCertificate(certificates[0].Certificate).ToX509Certificate2().Thumbprint, keyEntry, certificates);
85+
store.SetKeyEntry(certificates[0].Certificate.Thumbprint(), keyEntry, certificates);
8686
}
8787

8888
// Second Pkcs12Store necessary because of an obscure BC bug where creating a Pkcs12Store without .Load (code above using "Set" methods only) does not set all internal hashtables necessary to avoid an error later
@@ -113,22 +113,21 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
113113
if (certificateStore.IsKeyEntry(alias))
114114
throw new RemoteFileException("Cannot add a certificate with a private key to a PEM trust store.");
115115

116-
CertificateConverter certConverter = CertificateConverterFactory.FromBouncyCastleCertificate(certificateStore.GetCertificate(alias).Certificate);
117-
pemString += certConverter.ToPEM(true);
116+
pemString += CryptographicObjectFormatter.PEM.Format(certificateStore.GetCertificate(alias).Certificate, false);
118117
}
119118
}
120119
else
121120
{
122121
string storeContents = Encoding.ASCII.GetString(remoteHandler.DownloadCertificateFile(storePath + storeFileName));
123122

124-
string begDelim;
125123
string privateKeyContents = String.IsNullOrEmpty(SeparatePrivateKeyFilePath) ? storeContents : Encoding.ASCII.GetString(remoteHandler.DownloadCertificateFile(SeparatePrivateKeyFilePath));
126-
PrivateKeyTypeEnum privateKeyType = GetPrivateKeyType(privateKeyContents, out begDelim);
124+
PrivateKeyTypeEnum privateKeyType = GetPrivateKeyType(privateKeyContents, out _);
127125

128126
if (!string.IsNullOrEmpty(storePassword) && privateKeyType != PrivateKeyTypeEnum.PKCS8)
129127
throw new RemoteFileException("Error retrieving private key. Certificate store password cannot have a non empty value if the private key is in PKCS#1 format (BEGIN [RSA|EC] PRIVATE KEY)");
130128

131129
bool keyEntryProcessed = false;
130+
//todo: why is this a foreach? seems like it either runs once or throws an exception
132131
foreach (string alias in certificateStore.Aliases)
133132
{
134133
if (keyEntryProcessed)
@@ -140,39 +139,24 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
140139
throw new RemoteFileException("No private key found. Private key must be present to add entry to a non-Trust PEM certificate store.");
141140

142141
X509CertificateEntry[] chainEntries = certificateStore.GetCertificateChain(alias);
143-
CertificateConverter certConverter = CertificateConverterFactory.FromBouncyCastleCertificate(chainEntries[0].Certificate);
142+
X509Certificate endCertificate = chainEntries[0].Certificate;
144143

145144
AsymmetricKeyParameter privateKey = certificateStore.GetKey(alias).Key;
146-
AsymmetricKeyParameter publicKey = chainEntries[0].Certificate.GetPublicKey();
145+
PrivateKeyConverter keyConverter = PrivateKeyConverterFactory.FromBCPrivateKeyAndCert(privateKey, endCertificate);
147146

148-
if (privateKeyType == PrivateKeyTypeEnum.PKCS8)
149-
{
150-
PrivateKeyConverter keyConverter = PrivateKeyConverterFactory.FromBCKeyPair(privateKey, publicKey, false);
147+
keyString = CryptographicObjectFormatter.PEM.Format(keyConverter, storePassword);
148+
pemString = string.IsNullOrEmpty(SeparatePrivateKeyFilePath)
149+
? CryptographicObjectFormatter.PEM.Format(endCertificate, keyConverter, storePassword, false)
150+
: CryptographicObjectFormatter.PEM.Format(endCertificate, false);
151151

152-
byte[] privateKeyBytes = string.IsNullOrEmpty(storePassword) ? keyConverter.ToPkcs8BlobUnencrypted() : keyConverter.ToPkcs8Blob(storePassword);
153-
keyString = PemUtilities.DERToPEM(privateKeyBytes, string.IsNullOrEmpty(storePassword) ? PemUtilities.PemObjectType.PrivateKey : PemUtilities.PemObjectType.EncryptedPrivateKey);
154-
}
155-
else
152+
if (!IncludesChain)
156153
{
157-
TextWriter textWriter = new StringWriter();
158-
PemWriter pemWriter = new PemWriter(textWriter);
159-
pemWriter.WriteObject(privateKey);
160-
pemWriter.Writer.Flush();
161-
162-
keyString = textWriter.ToString();
154+
continue;
163155
}
164156

165-
pemString = certConverter.ToPEM(true);
166-
if (string.IsNullOrEmpty(SeparatePrivateKeyFilePath))
167-
pemString += keyString;
168-
169-
if (IncludesChain)
157+
for (int i = 1; i < chainEntries.Length; i++)
170158
{
171-
for (int i = 1; i < chainEntries.Length; i++)
172-
{
173-
CertificateConverter chainConverter = CertificateConverterFactory.FromBouncyCastleCertificate(chainEntries[i].Certificate);
174-
pemString += chainConverter.ToPEM(true);
175-
}
159+
pemString += CryptographicObjectFormatter.PEM.Format(chainEntries[i].Certificate, false);
176160
}
177161
}
178162
}
@@ -215,18 +199,10 @@ private X509CertificateEntry[] GetCertificates(string certificates)
215199

216200
try
217201
{
218-
while (certificates.Contains(CertDelimBeg))
219-
{
220-
int certStart = certificates.IndexOf(CertDelimBeg);
221-
int certLength = certificates.IndexOf(CertDelimEnd) + CertDelimEnd.Length - certStart;
222-
string certificate = certificates.Substring(certStart, certLength);
223-
224-
CertificateConverter c2 = CertificateConverterFactory.FromPEM(Encoding.ASCII.GetBytes(certificate.Replace(CertDelimBeg, string.Empty).Replace(CertDelimEnd, string.Empty)));
225-
X509Certificate bcCert = c2.ToBouncyCastleCertificate();
226-
certificateEntries.Add(new X509CertificateEntry(bcCert));
227-
228-
certificates = certificates.Substring(certStart + certLength - 1);
229-
}
202+
IEnumerable<string> pemCertificates = PemUtilities.SplitCollection(certificates);
203+
certificateEntries.AddRange(pemCertificates.Select(cert =>
204+
new X509CertificateEntry(new X509Certificate(CryptographicObjectFormatter.DER.Format(cert))))
205+
);
230206
}
231207
catch (Exception ex)
232208
{

RemoteFile/InventoryBase.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,13 @@
88
using System;
99
using System.Collections.Generic;
1010
using System.Linq;
11-
using System.Security.Cryptography.X509Certificates;
1211

1312
using Keyfactor.Orchestrators.Extensions;
1413
using Keyfactor.Orchestrators.Common.Enums;
1514
using Keyfactor.Logging;
1615
using Keyfactor.Extensions.Orchestrator.RemoteFile.Models;
17-
16+
using Keyfactor.PKI.Extensions;
1817
using Microsoft.Extensions.Logging;
19-
using Newtonsoft.Json;
2018

2119
namespace Keyfactor.Extensions.Orchestrator.RemoteFile
2220
{
@@ -41,27 +39,27 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd
4139
certificateStore.Initialize(SudoImpersonatedUser);
4240
certificateStore.LoadCertificateStore(certificateStoreSerializer, true);
4341

44-
List<X509Certificate2Collection> collections = certificateStore.GetCertificateChains();
42+
List<List<X509CertificateExt>> collections = certificateStore.GetCertificateChains();
4543

4644
logger.LogDebug($"Format returned certificates BEGIN");
47-
foreach (X509Certificate2Collection collection in collections)
45+
foreach (List<X509CertificateExt> collection in collections)
4846
{
4947
if (collection.Count == 0)
5048
continue;
5149

52-
X509Certificate2Ext issuedCertificate = (X509Certificate2Ext)collection[0];
50+
X509CertificateExt issuedCertificate = collection[0];
5351

5452
List<string> certChain = new List<string>();
55-
foreach (X509Certificate2 certificate in collection)
53+
foreach (X509CertificateExt certificate in collection)
5654
{
57-
certChain.Add(Convert.ToBase64String(certificate.Export(X509ContentType.Cert)));
58-
logger.LogDebug(Convert.ToBase64String(certificate.Export(X509ContentType.Cert)));
55+
certChain.Add(Convert.ToBase64String(certificate.GetEncoded()));
56+
logger.LogDebug(Convert.ToBase64String(certificate.GetEncoded()));
5957
}
6058

6159
inventoryItems.Add(new CurrentInventoryItem()
6260
{
6361
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
64-
Alias = string.IsNullOrEmpty(issuedCertificate.FriendlyNameExt) ? issuedCertificate.Thumbprint : issuedCertificate.FriendlyNameExt,
62+
Alias = string.IsNullOrEmpty(issuedCertificate.FriendlyNameExt) ? issuedCertificate.Thumbprint() : issuedCertificate.FriendlyNameExt,
6563
PrivateKeyEntry = issuedCertificate.HasPrivateKey,
6664
UseChainLevel = collection.Count > 1,
6765
Certificates = certChain.ToArray()

RemoteFile/ManagementBase.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@
66
// and limitations under the License.
77

88
using System;
9-
using System.Collections.Generic;
10-
using System.Security.Cryptography.X509Certificates;
119

1210
using Keyfactor.Logging;
1311
using Keyfactor.Orchestrators.Extensions;
1412
using Keyfactor.Orchestrators.Common.Enums;
15-
13+
using Keyfactor.PKI.Extensions;
1614
using Microsoft.Extensions.Logging;
1715

1816
using Newtonsoft.Json;
17+
using Org.BouncyCastle.X509;
1918

2019
namespace Keyfactor.Extensions.Orchestrator.RemoteFile
2120
{
@@ -52,7 +51,7 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
5251
throw new RemoteFileException($"Certificate store {config.CertificateStoreDetails.StorePath} does not exist on server {config.CertificateStoreDetails.ClientMachine}.");
5352
}
5453
certificateStore.LoadCertificateStore(certificateStoreSerializer, false);
55-
certificateStore.AddCertificate((config.JobCertificate.Alias ?? new X509Certificate2(Convert.FromBase64String(config.JobCertificate.Contents), config.JobCertificate.PrivateKeyPassword, X509KeyStorageFlags.EphemeralKeySet).Thumbprint), config.JobCertificate.Contents, config.Overwrite, config.JobCertificate.PrivateKeyPassword, RemoveRootCertificate);
54+
certificateStore.AddCertificate(config.JobCertificate.Alias ?? new X509Certificate(Convert.FromBase64String(config.JobCertificate.Contents)).Thumbprint(), config.JobCertificate.Contents, config.Overwrite, config.JobCertificate.PrivateKeyPassword, RemoveRootCertificate);
5655
certificateStore.SaveCertificateStore(certificateStoreSerializer.SerializeRemoteCertificateStore(certificateStore.GetCertificateStore(), storePathFile.Path, storePathFile.File, StorePassword, certificateStore.RemoteHandler));
5756

5857
logger.LogDebug($"END add Operation for {config.CertificateStoreDetails.StorePath} on {config.CertificateStoreDetails.ClientMachine}.");

RemoteFile/Models/SerializedStoreInfo.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
66
// and limitations under the License.
77

8-
using System.Security.Cryptography.X509Certificates;
9-
108
namespace Keyfactor.Extensions.Orchestrator.RemoteFile.Models
119
{
1210
internal class SerializedStoreInfo

RemoteFile/Models/X509Certificate2Ext.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

RemoteFile/ReenrollmentBase.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
using Keyfactor.Logging;
1313
using Keyfactor.Orchestrators.Extensions;
1414
using Keyfactor.Orchestrators.Common.Enums;
15-
using Keyfactor.PKI.PEM;
1615

1716
using Microsoft.Extensions.Logging;
1817

19-
using Newtonsoft.Json;
2018
using System.Security.Cryptography;
2119

2220
namespace Keyfactor.Extensions.Orchestrator.RemoteFile

0 commit comments

Comments
 (0)