diff --git a/Toolkit/Functions/ConvertFrom-CertificateToPEM.ps1 b/Toolkit/Functions/ConvertFrom-CertificateToPEM.ps1 index 6a0ce89..cbb493c 100644 --- a/Toolkit/Functions/ConvertFrom-CertificateToPEM.ps1 +++ b/Toolkit/Functions/ConvertFrom-CertificateToPEM.ps1 @@ -588,37 +588,53 @@ Function ConvertFrom-CertificateToPEM Switch ($Null -ine $X509Certificate2.Object.PublicKey) { {($_ -eq $True)} - { - Switch ($X509Certificate2.OID.FriendlyName) + { + Try { - {($_ -iin @('RSA'))} + Switch ($X509Certificate2.OID.FriendlyName) { - $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPublicKey($X509Certificate2.Object) - $X509Certificate2.CNG = [System.Security.Cryptography.RSACNG]($X509Certificate2.DSA) + {($_ -iin @('RSA'))} + { + $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPublicKey($X509Certificate2.Object) + $X509Certificate2.CNG = [System.Security.Cryptography.RSACNG]($X509Certificate2.DSA) + } + + {($_ -iin @('ECC'))} + { + $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.ECDSACertificateExtensions]::GetECDSAPublicKey($X509Certificate2.Object) + $X509Certificate2.CNG = [System.Security.Cryptography.ECDSACNG]($X509Certificate2.DSA) + } + + Default + { + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The certificate key algorithm of `"$($X509Certificate2.OID.FriendlyName)`" [OID: $($X509Certificate2.OID.Value)] is unsupported for public key blob extraction." + Write-Verbose -Message ($LoggingDetails.LogMessage) + } } - {($_ -iin @('ECC'))} + Switch ($Null -ine $X509Certificate2.CNG) { - $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.ECDSACertificateExtensions]::GetECDSAPublicKey($X509Certificate2.Object) - $X509Certificate2.CNG = [System.Security.Cryptography.ECDSACNG]($X509Certificate2.DSA) - } + {($_ -eq $True)} + { + $X509Certificate2.PublicKey = $X509Certificate2.CNG.Key - Default - { - $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The certificate key algorithm of `"$($X509Certificate2.OID.FriendlyName)`" [OID: $($X509Certificate2.OID.Value)] is unsupported for public key extraction." - Write-Warning -Message ($LoggingDetails.LogMessage) + $X509Certificate2.PublicKeyEncoded = [System.Convert]::ToBase64String(($X509Certificate2.PublicKey.Export([System.Security.Cryptography.CngKeyBlobFormat]::GenericPublicBlob)), [System.Base64FormattingOptions]::InsertLineBreaks) + + $Null = $StringBuilders.PublicKey.Append('-----BEGIN PUBLIC KEY-----').AppendLine() + $Null = $StringBuilders.PublicKey.Append($X509Certificate2.PublicKeyEncoded).AppendLine() + $Null = $StringBuilders.PublicKey.Append('-----END PUBLIC KEY-----') + + $OutputObjectProperties.Blobs.PublicKey = $StringBuilders.PublicKey.ToString() + } } } - - $X509Certificate2.PublicKey = $X509Certificate2.CNG.Key - - $X509Certificate2.PublicKeyEncoded = [System.Convert]::ToBase64String(($X509Certificate2.PublicKey.Export([System.Security.Cryptography.CngKeyBlobFormat]::GenericPublicBlob)), [System.Base64FormattingOptions]::InsertLineBreaks) - - $Null = $StringBuilders.PublicKey.Append('-----BEGIN PUBLIC KEY-----').AppendLine() - $Null = $StringBuilders.PublicKey.Append($X509Certificate2.PublicKeyEncoded).AppendLine() - $Null = $StringBuilders.PublicKey.Append('-----END PUBLIC KEY-----') - - $OutputObjectProperties.Blobs.PublicKey = $StringBuilders.PublicKey.ToString() + Catch + { + #Note: Some certificates use RSABCrypt or other non-CNG implementations that cannot be cast to RSACng/ECDsaCng. + #The certificate PEM blob is still valid - only the separate public key blob extraction fails. + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Public key blob extraction skipped (key implementation: $($X509Certificate2.DSA.GetType().Name)). Certificate PEM is still valid." + Write-Verbose -Message ($LoggingDetails.LogMessage) + } } Default @@ -640,44 +656,53 @@ Function ConvertFrom-CertificateToPEM $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to extract private key (as requested by -IncludePrivateKey)..." Write-Verbose -Message ($LoggingDetails.LogMessage) - Switch ($X509Certificate2.OID.FriendlyName) + Try { - {($_ -iin @('RSA'))} + Switch ($X509Certificate2.OID.FriendlyName) { - $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($X509Certificate2.Object) - $X509Certificate2.CNG = [System.Security.Cryptography.RSACNG]($X509Certificate2.DSA) + {($_ -iin @('RSA'))} + { + $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($X509Certificate2.Object) + $X509Certificate2.CNG = [System.Security.Cryptography.RSACNG]($X509Certificate2.DSA) + } + + {($_ -iin @('ECC'))} + { + $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions]::GetECDSAPrivateKey($X509Certificate2.Object) + $X509Certificate2.CNG = [System.Security.Cryptography.ECDSACNG]($X509Certificate2.DSA) + } + + Default + { + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The certificate key algorithm of `"$($X509Certificate2.OID.FriendlyName)`" [OID: $($X509Certificate2.OID.Value)] is unsupported for private key extraction." + Write-Warning -Message ($LoggingDetails.LogMessage) + } } - {($_ -iin @('ECC'))} + Switch ($Null -ine $X509Certificate2.CNG) { - $X509Certificate2.DSA = [System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions]::GetECDSAPrivateKey($X509Certificate2.Object) - $X509Certificate2.CNG = [System.Security.Cryptography.ECDSACNG]($X509Certificate2.DSA) - } + {($_ -eq $True)} + { + $X509Certificate2.PrivateKey = $X509Certificate2.CNG.Key - Default - { - $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The certificate key algorithm of `"$($X509Certificate2.OID.FriendlyName)`" [OID: $($X509Certificate2.OID.Value)] is unsupported for private key extraction." - Write-Warning -Message ($LoggingDetails.LogMessage) + $X509Certificate2.PrivateKeyEncoded = [System.Convert]::ToBase64String(($X509Certificate2.PrivateKey.Export([System.Security.Cryptography.CngKeyBlobFormat]::PKCS8PrivateBlob)), [System.Base64FormattingOptions]::InsertLineBreaks) + + $Null = $StringBuilders.PrivateKey.Append('-----BEGIN PRIVATE KEY-----').AppendLine() + $Null = $StringBuilders.PrivateKey.Append($X509Certificate2.PrivateKeyEncoded).AppendLine() + $Null = $StringBuilders.PrivateKey.Append('-----END PRIVATE KEY-----') + + $OutputObjectProperties.Blobs.PrivateKey = $StringBuilders.PrivateKey.ToString() + + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Private key successfully extracted." + Write-Verbose -Message ($LoggingDetails.LogMessage) + } } } - - Switch ($Null -ine $X509Certificate2.CNG) + Catch { - {($_ -eq $True)} - { - $X509Certificate2.PrivateKey = $X509Certificate2.CNG.Key - - $X509Certificate2.PrivateKeyEncoded = [System.Convert]::ToBase64String(($X509Certificate2.PrivateKey.Export([System.Security.Cryptography.CngKeyBlobFormat]::PKCS8PrivateBlob)), [System.Base64FormattingOptions]::InsertLineBreaks) - - $Null = $StringBuilders.PrivateKey.Append('-----BEGIN PRIVATE KEY-----').AppendLine() - $Null = $StringBuilders.PrivateKey.Append($X509Certificate2.PrivateKeyEncoded).AppendLine() - $Null = $StringBuilders.PrivateKey.Append('-----END PRIVATE KEY-----') - - $OutputObjectProperties.Blobs.PrivateKey = $StringBuilders.PrivateKey.ToString() - - $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Private key successfully extracted." - Write-Verbose -Message ($LoggingDetails.LogMessage) - } + #Note: Some certificates use RSABCrypt or other non-CNG implementations that cannot be cast to RSACng/ECDsaCng. + $LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Private key extraction failed (key implementation: $($X509Certificate2.DSA.GetType().Name)). This key type does not support CNG export." + Write-Warning -Message ($LoggingDetails.LogMessage) } }