Created
May 7, 2020 16:33
-
-
Save 5y5tem5/647ca3bd9e3b39c00a9e444b3bc06d33 to your computer and use it in GitHub Desktop.
Powershell PFX extract private key in base64/PEM/key format.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # mostly stolen from the follwoing | |
| #https://github.com/Devolutions/WaykNow-ps/blob/master/WaykNow/Private/RSAHelper.ps1 | |
| #https://stackoverflow.com/questions/23734792/c-sharp-export-private-public-rsa-key-from-rsacryptoserviceprovider-to-pem-strin | |
| # pass a PFX and get the base64/PEM of the privatekey | |
| param ( | |
| [string]$PFXPath = "" | |
| ) | |
| function Get-PrivKey( | |
| [System.Security.Cryptography.RSAParameters]$RSAParams | |
| ){ | |
| [byte]$Sequence = 0x30 | |
| [byte[]]$Version =(0x00) | |
| $stream = [System.IO.MemoryStream]::new() | |
| $writer = [System.IO.BinaryWriter]::new($stream) | |
| $writer.Write($Sequence); # SEQUENCE | |
| $innerStream = [System.IO.MemoryStream]::new() | |
| $innerWriter = [System.IO.BinaryWriter]::new($innerStream) | |
| EncodeIntegerBigEndian $innerWriter $Version | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.Modulus | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.Exponent | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.D | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.P | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.Q | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.DP | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.DQ | |
| EncodeIntegerBigEndian $innerWriter $RSAParams.InverseQ | |
| $length = ([int]($innerStream.Length)) | |
| EncodeLength $writer $length | |
| $writer.Write($innerStream.GetBuffer(), 0, $length) | |
| $base64 = [Convert]::ToBase64String($stream.GetBuffer(), 0, ([int]($stream.Length))) | |
| $offset = 0 | |
| $line_length = 64 | |
| $sb = [System.Text.StringBuilder]::new() | |
| [void]$sb.AppendLine("-----BEGIN RSA PRIVATE KEY-----") | |
| while ($offset -lt $base64.Length) { | |
| $line_end = [Math]::Min($offset + $line_length, $base64.Length) | |
| [void]$sb.AppendLine($base64.Substring($offset, $line_end - $offset)) | |
| $offset = $line_end | |
| } | |
| [void]$sb.AppendLine("-----END RSA PRIVATE KEY-----") | |
| return $sb.ToString() | |
| } | |
| function EncodeLength( | |
| [System.IO.BinaryWriter]$stream, | |
| [int]$length | |
| ){ | |
| [byte]$bytex80 = 0x80 | |
| if($length -lt 0){ | |
| throw "Length must be non-negative" | |
| } | |
| if($length -lt $bytex80){ | |
| $stream.Write(([byte]$length)) | |
| } | |
| else{ | |
| $temp = $length | |
| $bytesRequired = 0; | |
| while ($temp -gt 0) { | |
| $temp = $temp -shr 8 | |
| $bytesRequired++ | |
| } | |
| [byte]$byteToWrite = $bytesRequired -bor $bytex80 | |
| $stream.Write($byteToWrite) | |
| $iValue = ($bytesRequired - 1) | |
| [byte]$0ffByte = 0xff | |
| for ($i = $iValue; $i -ge 0; $i--) { | |
| [byte]$byteToWrite = ($length -shr (8 * $i) -band $0ffByte) | |
| $stream.Write($byteToWrite ) | |
| } | |
| } | |
| } | |
| function EncodeIntegerBigEndian( | |
| [System.IO.BinaryWriter]$stream, | |
| [byte[]]$value, | |
| [bool]$forceUnsigned = $true | |
| ) | |
| { | |
| [byte]$Integer = 0x02 | |
| $stream.Write($Integer); # INTEGER | |
| $prefixZeros = 0 | |
| for ($i = 0; $i -lt $value.Length; $i++) { | |
| if ($value[$i] -ne 0){break} | |
| $prefixZeros++ | |
| } | |
| if(($value.Length - $prefixZeros) -eq 0){ | |
| EncodeLength $stream 1 | |
| $stream.Write(([byte]0)) | |
| } | |
| else{ | |
| [byte]$newByte = 0x7f | |
| if(($forceUnsigned) -AND ($value[$prefixZeros] -gt $newByte)){ | |
| EncodeLength $stream ($value.Length - $prefixZeros +1) | |
| $stream.Write(([byte]0)) | |
| } | |
| else{ | |
| EncodeLength $stream ($value.Length - $prefixZeros) | |
| } | |
| for ($i = $prefixZeros; $i -lt $value.Length; $i++) { | |
| $stream.Write($value[$i]) | |
| } | |
| } | |
| } | |
| function Get-RSAKeyData([String]$PFXPath) | |
| { | |
| if(Test-Path $PFXPath){ | |
| $Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 | |
| $PFXPassword = Read-Host -AsSecureString 'Enter PFX password' | |
| $CertFlags = New-Object System.Security.Cryptography.X509Certificates.X509KeyStorageFlags | |
| $CertFlags.value__ = 4 #exportable | |
| $Cert.Import($PFXPath,$PFXPassword,$CertFlags) | |
| $PrivateKeyParams = $Cert.PrivateKey.ExportParameters($true) | |
| return $PrivateKeyParams | |
| } | |
| else{ | |
| Write-Error 'That pfx does not exist' | |
| } | |
| } | |
| $PrivateKeyParams = Get-RSAKeyData($PFXPath) | |
| $PrivateKey = Get-PrivKey($PrivateKeyParams) | |
| write-host $PrivateKey |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank yo so much ! I love you!