Recently I was working with a particular application that used certificates to secure communication. I wanted to put the certificates into Azure KeyVault. Azure KeyVault naturally allows you to store certificates. However, it only lets you upload certificates that are in PFX (PKCS#12) or CER (DER or BASE64 encoded). I needed to convert my RSA XML Private Key to PEM Format (DER encoded in Base64). Naturally using PowerShell. The script snippet I created to do this is in this post as I know I’ll need it again in the future.
Overview
The RSA XML format for storing private keys is a specific serialization format where the RSA cryptographic key details are stored as XML. This format is widely used in Microsoft environments and is particularly convenient for interoperability within .NET applications.
RSA Private Key in XML Format example
<RSAKeyValue>
<Modulus>oNsp...b9M=</Modulus>
<Exponent>AQAB</Exponent>
<P>6Bq...1M=</P>
<Q>x4R...Ak=</Q>
<DP>VjL...QI=</DP>
<DQ>Vx5...BI=</DQ>
<InverseQ>C4t...3g=</InverseQ>
<D>HIk...0M=</D>
</RSAKeyValue>
PEM Format example
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCk9C3ciPLVubsD
92oRPARUs/o90rCgQ7/9HCr6sVVROrCxEk9rNx4wK2byCBubG4gZFg66p2elCg7w
eI5aGyxgJHqcQ268R1sSud59AtvF1xi6iUNNU5U2ea6Y7bTHoOUijYx28aTr6VMM
....
8PTz6covjoOJqxQJOvM7nM0CsJawG9ccw3YXyd9KgRIdSt6ooEhb7N8W2EXYoKl3
g1i2t41Q/SC3HUGC5mJjpO8=
-----END PRIVATE KEY-----
Certificate Conversion Script
Here is my small script to convert RSA XML Private Key to PEM Format with PowerShell. It takes in the private key from a file in the local directory named private.key converts it to PEM format and outputs it to private_key.pem in the local directory.
# Example RSAKeyValue XML format
$xmlPrivateKey = Get-Content .\private.key
# Load the XML string into an XmlDocument
$xml = New-Object System.Xml.XmlDocument
$xml.LoadXml($xmlPrivateKey)
# Function to properly format and convert Base64
function Convert-ToBase64Pem {
param (
$data,
$type
)
$base64 = [Convert]::ToBase64String($data)
$output = "-----BEGIN $type-----`n"
for ($i = 0; $i -lt $base64.Length; $i += 64) {
$output += ($base64.Substring($i, [Math]::Min(64, $base64.Length - $i)) + "`n")
}
$output += "-----END $type-----"
return $output
}
# Create the RSA parameters object
$rsaParams = New-Object System.Security.Cryptography.RSAParameters
$rsaParams.Modulus = [Convert]::FromBase64String($xml.RSAKeyValue.Modulus)
$rsaParams.Exponent = [Convert]::FromBase64String($xml.RSAKeyValue.Exponent)
$rsaParams.D = [Convert]::FromBase64String($xml.RSAKeyValue.D)
$rsaParams.P = [Convert]::FromBase64String($xml.RSAKeyValue.P)
$rsaParams.Q = [Convert]::FromBase64String($xml.RSAKeyValue.Q)
$rsaParams.DP = [Convert]::FromBase64String($xml.RSAKeyValue.DP)
$rsaParams.DQ = [Convert]::FromBase64String($xml.RSAKeyValue.DQ)
$rsaParams.InverseQ = [Convert]::FromBase64String($xml.RSAKeyValue.InverseQ)
# Create an RSA object and import the parameters
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$rsa.ImportParameters($rsaParams)
# Export the RSA parameters to PEM-format private key
$rsaPrivateParams = $rsa.ExportParameters([System.Security.Cryptography.RSAParameters]::$true)
$rsaPrivateBlob = $rsa.ExportRSAPrivateKey()
$privateKeyPem = Convert-ToBase64Pem $rsaPrivateBlob "RSA PRIVATE KEY"
# Save to PEM file
$privateKeyPem | Out-File -FilePath ".\private_key.pem"
Summary
For some reason I didn’t find examples on how to do this and needed to figure it out. As always documenting it here for future me and anyone else with a similar need.