diff --git a/SafeguardDevOpsService/ConfigDb/LiteDbConfigurationRepository.cs b/SafeguardDevOpsService/ConfigDb/LiteDbConfigurationRepository.cs index 86affdcd..e1a467ae 100644 --- a/SafeguardDevOpsService/ConfigDb/LiteDbConfigurationRepository.cs +++ b/SafeguardDevOpsService/ConfigDb/LiteDbConfigurationRepository.cs @@ -12,6 +12,7 @@ using OneIdentity.DevOps.Data; using OneIdentity.DevOps.Data.Spp; using OneIdentity.DevOps.Exceptions; +using OneIdentity.DevOps.Extensions; using OneIdentity.DevOps.Logic; using CredentialType = CredentialManagement.CredentialType; @@ -653,7 +654,7 @@ public X509Certificate2 UserCertificate try { var bytes = Convert.FromBase64String(UserCertificateBase64Data); - var cert = X509CertificateLoader.LoadPkcs12(bytes, UserCertificatePassphrase); + var cert = CertificateExtensions.LoadFromBytes(bytes,UserCertificatePassphrase); return cert; } catch (Exception) @@ -699,7 +700,7 @@ public X509Certificate2 WebSslCertificate try { var bytes = Convert.FromBase64String(WebSslCertificateBase64Data); - var cert = X509CertificateLoader.LoadPkcs12(bytes, WebSslCertificatePassphrase); + var cert = CertificateExtensions.LoadFromBytes(bytes, WebSslCertificatePassphrase); return cert; } catch (Exception) diff --git a/SafeguardDevOpsService/Extensions/CertificateExtensions.cs b/SafeguardDevOpsService/Extensions/CertificateExtensions.cs new file mode 100644 index 00000000..8ee98d41 --- /dev/null +++ b/SafeguardDevOpsService/Extensions/CertificateExtensions.cs @@ -0,0 +1,52 @@ +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace OneIdentity.DevOps.Extensions +{ + public static class CertificateExtensions + { + public static X509Certificate2 LoadFromBytes(byte[] rawData, string? password = null, X509KeyStorageFlags? keyStorageFlags = null) + { + // 1. Detect if the byte array is PKCS12 or PEM + X509ContentType contentType = X509Certificate2.GetCertContentType(rawData); + + if (contentType == X509ContentType.Pkcs12) + { + if (keyStorageFlags.HasValue) + { + // Use the new .NET 9 Loader for binary PKCS12/PFX + return X509CertificateLoader.LoadPkcs12(rawData, password, keyStorageFlags.Value); + } + else + { + // Use the new .NET 9 Loader for binary PKCS12/PFX + return X509CertificateLoader.LoadPkcs12(rawData, password); + } + + } + else + { + // It's likely PEM (text-based). + // We convert the bytes to a string to use the PEM parser. + string pemString = Encoding.UTF8.GetString(rawData); + + // 1. Load the public certificate + var cert = X509CertificateLoader.LoadCertificate(rawData); + + // 2. Load the private key if it exists in the string + if (pemString.Contains("PRIVATE KEY")) + { + using var rsa = RSA.Create(); + // ImportFromPem automatically handles both 'Universal 2' and 'Universal 16' + rsa.ImportFromPem(pemString); + + // 3. Link them together + return cert.CopyWithPrivateKey(rsa); + } + + return cert; + } + } + } +} diff --git a/SafeguardDevOpsService/Logic/CertificateData.cs b/SafeguardDevOpsService/Logic/CertificateData.cs index 94a35ef9..7f9bae2d 100644 --- a/SafeguardDevOpsService/Logic/CertificateData.cs +++ b/SafeguardDevOpsService/Logic/CertificateData.cs @@ -4,6 +4,7 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using OneIdentity.DevOps.Exceptions; +using OneIdentity.DevOps.Extensions; namespace OneIdentity.DevOps.Logic { @@ -16,7 +17,7 @@ internal class CertificateData : ICertificateData, IDisposable public CertificateData(string certB64, string password) { Password = password; - cert = X509CertificateLoader.LoadPkcs12(Convert.FromBase64String(certB64), password, X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable); + cert = CertificateExtensions.LoadFromBytes(Convert.FromBase64String(certB64), password, X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable); } public string Base64Certificate => Convert.ToBase64String(cert.Export(X509ContentType.Cert)); diff --git a/SafeguardDevOpsService/Logic/SafeguardLogic.cs b/SafeguardDevOpsService/Logic/SafeguardLogic.cs index fc128b10..db1b76b3 100644 --- a/SafeguardDevOpsService/Logic/SafeguardLogic.cs +++ b/SafeguardDevOpsService/Logic/SafeguardLogic.cs @@ -1640,7 +1640,7 @@ public void InstallCertificate(CertificateInfo certificate, CertificateType cert X509Certificate2 cert; try { - cert = X509CertificateLoader.LoadPkcs12(certificateBytes, certificate.Passphrase); + cert = CertificateExtensions.LoadFromBytes(certificateBytes, certificate.Passphrase); _logger.Debug( $"Parsed certificate for installation: subject={cert.SubjectName.Name}, thumbprint={cert.Thumbprint}"); } @@ -2304,7 +2304,7 @@ private CertificateInfo AddTrustedCertificate(string base64CertificateData, stri try { var certificateBytes = CertificateHelper.ConvertPemToData(base64CertificateData); - var cert = X509CertificateLoader.LoadPkcs12(certificateBytes, passPhrase); + var cert = CertificateExtensions.LoadFromBytes(certificateBytes, passPhrase); _logger.Debug( $"Parsed new trusted certificate: subject={cert.SubjectName}, thumbprint={cert.Thumbprint}.");