Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Lee Fine committed Jan 17, 2025
1 parent 6fd6ed5 commit 482541f
Showing 1 changed file with 43 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,25 @@
using Org.BouncyCastle.X509;
using System.Security.Cryptography;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto.Parameters;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.PEM
{
class PEMCertificateStoreSerializer : ICertificateStoreSerializer
{
string[] PrivateKeyDelimetersPkcs8 = new string[] { "-----BEGIN PRIVATE KEY-----", "-----BEGIN ENCRYPTED PRIVATE KEY-----" };
string[] PrivateKeyDelimetersPkcs1 = new string[] { "-----BEGIN RSA PRIVATE KEY-----" };
string[] PrivateKeyDelimetersEC = new string[] { "-----BEGIN EC PRIVATE KEY-----", "-----BEGIN EC ENCRYPTED PRIVATE KEY-----", "-----BEGIN ENCRYPTED EC PRIVATE KEY-----" };
string CertDelimBeg = "-----BEGIN CERTIFICATE-----";
string CertDelimEnd = "-----END CERTIFICATE-----";

private enum PrivateKeyTypeEnum
{
EC,
PKCS1,
PKCS8
}

private bool IsTrustStore { get; set; }
private bool IncludesChain { get; set; }
private string SeparatePrivateKeyFilePath { get; set; }
Expand Down Expand Up @@ -68,10 +77,10 @@ public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContentBytes, s
}
else
{
bool isRSAPrivateKey = false;
AsymmetricKeyEntry keyEntry = GetPrivateKey(storeContents, storePassword ?? string.Empty, remoteHandler, out isRSAPrivateKey);
PrivateKeyTypeEnum privateKeyType;
AsymmetricKeyEntry keyEntry = GetPrivateKey(storeContents, storePassword ?? string.Empty, remoteHandler, out privateKeyType);

if (isRSAPrivateKey && !string.IsNullOrEmpty(storePassword))
if (privateKeyType == PrivateKeyTypeEnum.PKCS1 && !string.IsNullOrEmpty(storePassword))
throw new RemoteFileException($"Certificate store with an RSA Private Key cannot contain a store password. Invalid store format not supported.");

store.SetKeyEntry(CertificateConverterFactory.FromBouncyCastleCertificate(certificates[0].Certificate).ToX509Certificate2().Thumbprint, keyEntry, certificates);
Expand Down Expand Up @@ -112,14 +121,14 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
else
{
string storeContents = Encoding.ASCII.GetString(remoteHandler.DownloadCertificateFile(storePath + storeFileName));
bool isRSAPrivateKey = false;
PrivateKeyTypeEnum privateKeyType = PrivateKeyTypeEnum.PKCS8;
try
{
GetPrivateKey(storeContents, storePassword, remoteHandler, out isRSAPrivateKey);
GetPrivateKey(storeContents, storePassword, remoteHandler, out privateKeyType);
}
catch (RemoteFileException) { }

if (isRSAPrivateKey && !string.IsNullOrEmpty(storePassword))
if (privateKeyType == PrivateKeyTypeEnum.PKCS1 && !string.IsNullOrEmpty(storePassword))
throw new RemoteFileException($"Certificate store with an RSA Private Key cannot contain a store password. Invalid store format not supported.");

bool keyEntryProcessed = false;
Expand All @@ -135,7 +144,7 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer

X509CertificateEntry[] chainEntries = certificateStore.GetCertificateChain(alias);
CertificateConverter certConverter = CertificateConverterFactory.FromBouncyCastleCertificate(chainEntries[0].Certificate);

ECDiffieHellman
AsymmetricKeyParameter privateKey = certificateStore.GetKey(alias).Key;

Check failure on line 148 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

; expected

Check failure on line 148 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

; expected
X509CertificateEntry[] certEntries = certificateStore.GetCertificateChain(alias);
AsymmetricKeyParameter publicKey = certEntries[0].Certificate.GetPublicKey();
Expand Down Expand Up @@ -230,7 +239,7 @@ private X509CertificateEntry[] GetCertificates(string certificates)
return certificateEntries.ToArray();
}

private AsymmetricKeyEntry GetPrivateKey(string storeContents, string storePassword, IRemoteHandler remoteHandler, out bool isRSA)
private AsymmetricKeyEntry GetPrivateKey(string storeContents, string storePassword, IRemoteHandler remoteHandler, out PrivateKeyTypeEnum? privateKeyType)
{
logger.MethodEntry(LogLevel.Debug);

Expand All @@ -239,16 +248,18 @@ private AsymmetricKeyEntry GetPrivateKey(string storeContents, string storePassw
storeContents = Encoding.ASCII.GetString(remoteHandler.DownloadCertificateFile(SeparatePrivateKeyFilePath));
}

isRSA = false;
foreach (string begDelim in PrivateKeyDelimetersPkcs1)
privateKeyType = GetPrivateKeyType(PrivateKeyDelimetersPkcs8, storeContents, PrivateKeyTypeEnum.PKCS8) ? PrivateKeyTypeEnum.PKCS8 : null;
if (!privateKeyType.HasValue)
privateKeyType = GetPrivateKeyType(PrivateKeyDelimetersPkcs1, storeContents, PrivateKeyTypeEnum.PKCS1) ? PrivateKeyTypeEnum.PKCS1 : null;
if (!privateKeyType.HasValue)
privateKeyType = GetPrivateKeyType(PrivateKeyDelimetersEC, storeContents, PrivateKeyTypeEnum.EC) ? PrivateKeyTypeEnum.EC : null;

if (privateKeyType == null)
{
if (storeContents.Contains(begDelim))
{
isRSA = true;
break;
}
throw new RemoteFileException("Invalid or unsupported private key.");
}


string privateKey = string.Empty;
foreach (string begDelim in isRSA ? PrivateKeyDelimetersPkcs1 : PrivateKeyDelimetersPkcs8)
{
Expand Down Expand Up @@ -281,10 +292,26 @@ private AsymmetricKeyEntry GetPrivateKey(string storeContents, string storePassw
{
c = PrivateKeyConverterFactory.FromPkcs8Blob(Convert.FromBase64String(privateKey), storePassword);
}

ec

Check failure on line 295 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Identifier expected

Check failure on line 295 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

; expected

Check failure on line 295 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Identifier expected

Check failure on line 295 in RemoteFile/ImplementedStoreTypes/PEM/PEMCertificateStoreSerializer.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

; expected
logger.MethodExit(LogLevel.Debug);

return new AsymmetricKeyEntry(c.ToBCPrivateKey());
}

private bool GetPrivateKeyType(string[] begDelims, string storeContents, PrivateKeyTypeEnum typeCheckingFor)
{
bool found = false;

foreach (string begDelim in begDelims)
{
if (storeContents.Contains(begDelim))
{
found = true;
break;
}
}

return found;
}
}
}

0 comments on commit 482541f

Please sign in to comment.