Skip to content

Instantly share code, notes, and snippets.

@5y5tem5
Created May 7, 2020 16:33
Show Gist options
  • Select an option

  • Save 5y5tem5/647ca3bd9e3b39c00a9e444b3bc06d33 to your computer and use it in GitHub Desktop.

Select an option

Save 5y5tem5/647ca3bd9e3b39c00a9e444b3bc06d33 to your computer and use it in GitHub Desktop.

Revisions

  1. 5y5tem5 created this gist May 7, 2020.
    132 changes: 132 additions & 0 deletions get-privkeyfrompfx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    # 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