-
-
Save cdelashmutt-pivotal/03aca91a9d01e6fc72771d3fa01cf5ea to your computer and use it in GitHub Desktop.
<# | |
.SYNOPSIS | |
Create an OpenSSH compatible Public and Private Key in pure Powershell | |
.DESCRIPTION | |
Many scripts rely on the openssh or openssl tools to be available to generate public and private keys compatible with OpenSSH, but this script relies purely on Powershell (and some .NET classes already included) to generate public and private keys. | |
.EXAMPLE | |
PS /git/scripts> ./Create-OpenSSHPubAndPrivateKeys.ps1 -PublicKeyPath my-key.pub -PrivateKeyPath my-key | |
.LINK | |
mailto:grog@grogscave.net | |
#> | |
[CmdletBinding()] | |
param ( | |
# The path to use to store the public key file | |
[Parameter(Mandatory=$true)] | |
[string] | |
$PublicKeyFile, | |
# The path to use to store the private key file | |
[Parameter(Mandatory=$true)] | |
[string] | |
$PrivateKeyFile | |
) | |
# SSH key generation significantly cribbed from https://stackoverflow.com/posts/3588388/revisions | |
# and https://www.thedigitalcatonline.com/blog/2018/04/25/rsa-keys/ | |
function Export-SSHPublicKey([System.Security.Cryptography.RSACryptoServiceProvider] $csp) { | |
$result = @((Get-LengthAndData ([System.Text.Encoding]::ASCII.GetBytes("ssh-rsa")))) | |
$rsaParams = $rsa.ExportParameters($false) | |
$result += Get-LengthAndData $rsaParams.Exponent | |
$result += Get-LengthAndData $(@(0x0)+$rsaParams.Modulus) | |
return [System.Convert]::ToBase64String($result) | |
} | |
function Get-LengthAndData([byte[]] $data) { | |
$reverseSize = [System.BitConverter]::GetBytes($data.Length) | |
[System.Array]::Reverse($reverseSize) | |
return $reverseSize + $data | |
} | |
# Generate RSA Key Pair | |
Write-Host "Creating a 2048-bit RSA Keypair" | |
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider -ArgumentList 2048 | |
Write-Host "Saving private and public keys as $PrivateKeyFile and $PublicKeyFile" | |
#Private Key | |
"-----BEGIN RSA PRIVATE KEY-----`n" + [System.Convert]::ToBase64String( $rsa.ExportRSAPrivateKey(), [Base64FormattingOptions]::InsertLineBreaks) + "`n-----END RSA PRIVATE KEY-----" | Out-File -Encoding utf8NoBOM $PrivateKeyFile | |
#Public Key | |
"ssh-rsa " + (Export-SSHPublicKey $rsa) + " tkg-vms" | Out-File -Encoding utf8NoBOM $PublicKeyFile |
Hello, @schittli, I'm glad you found the script interesting.
As to the method call, I took a look at the docs for that API call at https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsa.exportrsaprivatekey?view=net-6.0&viewFallbackFrom=netframework-4.8#system-security-cryptography-rsa-exportrsaprivatekey. It seems like that method was available in .NET Core 3.0, .NET Core 3.1, and .NET 5 and beyond.
I suspect that you might be on an older version of .NET? There are some instructions at https://docs.microsoft.com/en-us/dotnet/core/install/how-to-detect-installed-versions?pivots=os-windows to check which versions of the .NET Runtime you have installed, but I think those instructions might only work if you are on a later version of your OS. I'll have to do some checking to see if there is an alternative way in older .NET Framework versions to get an RSA type Private Key exported.
Also, it looks like older versions of Powershell (even up to Powershell 5.1) still use the older .NET Framework 4.8 and lower. You might have better luck on Powershell 6+ if you can use those on whatever machine you are on.
Hello
Thank you very much for sharing your Script!
Do you know why
$rsa.ExportRSAPrivateKey()
no longer works?It looks like
System.Security.Cryptography.RSACryptoServiceProvider
no longer has anExportRSAPrivateKey()
method: