I wish to create an ssh-rsa public key from an existing private key string
for example:
for the following private rsa key string:
-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAvyN0aQKoYl/LAZ/1dQt0rWuSNyOty88k3439HT3rcT/vhaSk d5lbnNKiYTzdDEkAxAnx4rxw6bEdD/8A9ISs0jy3pFRORFdbgBVFjIPR2NKbwVbs 9fcQNOQHcNslAyHA/yy57ktw+/6VyHYnHfXFlhkt1Jx4A1ubFIGzXttnXkwuNhdn 2JLJ5+JA3zRDJNBZR7p7NHVu9cRBwADm/WSzPqI6Sgs8kkU0eBcfy7qJRao3cmR5 95lLxkhFARufSW8lD/tCs2k99T2ZwZpKJpliA5VGjIC3iHhck3tpXs5w9sQ5Axhv n1kTq5GKNi48r132KgRNJO+jIY0QSI60A6akbwIDAQABAoIBACCB3SiG5TBl7lbG Z66SVjOwWdu627IP9st2kJfKkiJep1PpXndgw632PNugyE9wkwrETjkrp2B3WOQB kJ4Feob/AJSYKf+Bg/RSqdNuD+B6YTcOm5pxfHYiWgmdm7ven75GUxDuD7cr4zmG rrxvsj0G5z6Dpf2cNNHWBTWaxwfITaC8yXp6dx8o8V86/T0qrsEl+S0YJ5VQWt6L I5GzipFNhhjcaemkOxDJg2T/g0FbpBEuj3RnwWNfRiiTCt+AuROg6/4M2oyLBE9W e8n8KAUhZvRJA2dFwzZY38U9MfX9k9zIkJXtpkeghGx3M2zG3cQcFOaly6aFNHjr QuEd6kECgYEA7NQgfqxuJ34kMnmtZeYccFGI6WUosuXUlgMhqU8CUnjIaRX8u8Ho UjvjbezHNsI8tyH3vopgHNqTkcuElyuxKZQBTtUOFGG4a1HUS5tlo913DcnuSVIa qL8kn3XVDHvuTr8tJbsb4KXrEMFfGoJBemU4ixSDiYWk/FdXvyyEEbECgYEAzpx6 JPOktmdaLf8U7snvlRY9daBqKfPqtKDxYgsC3xOp90Z3FMWQi5OyPmBsLGmjHxhe YrPYQ3lbRh2JuRgZ7rTAxXN9dnDNgrh4tFjEEqQiFBCGlhP6syNM9Kx0YYNAoJN4 U29Tv71rxHJiFaLiRTh3Nopdn5ir4Raoj2fQgB8CgYBxCCFmNAfzA2plSNuwia5D ETcmJejR0Y2v91imhRYXpJwKQ7s3JaorLXgzq9G82eG+ihDDOSn8O3o5GIh02h6Z OJGTPW6V3bn2RrzrRQSyu+2pgBohlnUw2uGw1b1UUwX/QZFbs7zvcGELwy8P6OE1 eIAPKUBKb6W55jnz/VwfUQKBgGPTpQyPkAj1vNO2iLWrag/dtApOXJ0yljd5/8cA TP3dsWShbk3h+yoFTbznt7xpuf//NTN5c8d+LkSdZvrAk18LhIyidX8xl4pOeTui G/JpzXFmXrDKrHm7V6ZsYLrwwNwVBLFDe/KLojNDlPKhRbRuSONYTU4cZQeXfA/1 9/6/AoGAarF4JSdpzMzfacpLy2nsOM6XmL76B218uKANSHQy9k1X/Hp1u1StY8tQ H4+DSrRUQBb4sdxkCRXVvMH3zttDGoIrSUvDqN3k4opcP8nmzMc/EDwD3xFgri/p yBXBhE99r1B0p7fneXt58tTqtcevk5dQPzyF9SdsfUxD5PrnZRI= -----END RSA PRIVATE KEY-----
I wish to get the following output:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/I3RpAqhiX8sBn/V1C3Sta5I3I63LzyTfjf0dPetxP++FpKR3mVuc0qJhPN0MSQDECfHivHDpsR0P/wD0hKzSPLekVE5EV1uAFUWMg9HY0pvBVuz19xA05Adw2yUDIcD/LLnuS3D7/pXIdicd9cWWGS3UnHgDW5sUgbNe22deTC42F2fYksnn4kDfNEMk0FlHuns0dW71xEHAAOb9ZLM+ojpKCzySRTR4Fx/LuolFqjdyZHn3mUvGSEUBG59JbyUP+0KzaT31PZnBmkommWIDlUaMgLeIeFyTe2leznD2xDkDGG+fWROrkYo2LjyvXfYqBE0k76MhjRBIjrQDpqRv administrator@LovelyTrust
I tried few ways but unfortunately nothing gave me the desired output, for example, I was able to generate RSA object from my private key using:
public static string ExtractPublicKeyFromPrivate(string privateKey)
{
var rsa = RSA.Create();
rsa.ImportFromPem(privateKey.ToCharArray());
return ""
}
but both
rsa.ExportRSAPublicKey()
rsa.ExportSubjectPublicKeyInfo()
didn't give me the desired output, any ideas?
SSH key format is a bit complex. Moreover, .NET doesn't have a method to directly get the key in this format. However, something like this will work (I tried in a .NET 6 console application, and got the public key exactly how you want it.):
// See https://aka.ms/new-console-template for more information
using System.Security.Cryptography;
using System.Text;
static byte[] ToBytes(int i)
{
byte[] bytes = BitConverter.GetBytes(i);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return bytes;
}
string privateKey = "-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAvyN0aQKoYl/LAZ/1dQt0rWuSNyOty88k3439HT3rcT/vhaSk d5lbnNKiYTzdDEkAxAnx4rxw6bEdD/8A9ISs0jy3pFRORFdbgBVFjIPR2NKbwVbs 9fcQNOQHcNslAyHA/yy57ktw+/6VyHYnHfXFlhkt1Jx4A1ubFIGzXttnXkwuNhdn 2JLJ5+JA3zRDJNBZR7p7NHVu9cRBwADm/WSzPqI6Sgs8kkU0eBcfy7qJRao3cmR5 95lLxkhFARufSW8lD/tCs2k99T2ZwZpKJpliA5VGjIC3iHhck3tpXs5w9sQ5Axhv n1kTq5GKNi48r132KgRNJO+jIY0QSI60A6akbwIDAQABAoIBACCB3SiG5TBl7lbG Z66SVjOwWdu627IP9st2kJfKkiJep1PpXndgw632PNugyE9wkwrETjkrp2B3WOQB kJ4Feob/AJSYKf+Bg/RSqdNuD+B6YTcOm5pxfHYiWgmdm7ven75GUxDuD7cr4zmG rrxvsj0G5z6Dpf2cNNHWBTWaxwfITaC8yXp6dx8o8V86/T0qrsEl+S0YJ5VQWt6L I5GzipFNhhjcaemkOxDJg2T/g0FbpBEuj3RnwWNfRiiTCt+AuROg6/4M2oyLBE9W e8n8KAUhZvRJA2dFwzZY38U9MfX9k9zIkJXtpkeghGx3M2zG3cQcFOaly6aFNHjr QuEd6kECgYEA7NQgfqxuJ34kMnmtZeYccFGI6WUosuXUlgMhqU8CUnjIaRX8u8Ho UjvjbezHNsI8tyH3vopgHNqTkcuElyuxKZQBTtUOFGG4a1HUS5tlo913DcnuSVIa qL8kn3XVDHvuTr8tJbsb4KXrEMFfGoJBemU4ixSDiYWk/FdXvyyEEbECgYEAzpx6 JPOktmdaLf8U7snvlRY9daBqKfPqtKDxYgsC3xOp90Z3FMWQi5OyPmBsLGmjHxhe YrPYQ3lbRh2JuRgZ7rTAxXN9dnDNgrh4tFjEEqQiFBCGlhP6syNM9Kx0YYNAoJN4 U29Tv71rxHJiFaLiRTh3Nopdn5ir4Raoj2fQgB8CgYBxCCFmNAfzA2plSNuwia5D ETcmJejR0Y2v91imhRYXpJwKQ7s3JaorLXgzq9G82eG+ihDDOSn8O3o5GIh02h6Z OJGTPW6V3bn2RrzrRQSyu+2pgBohlnUw2uGw1b1UUwX/QZFbs7zvcGELwy8P6OE1 eIAPKUBKb6W55jnz/VwfUQKBgGPTpQyPkAj1vNO2iLWrag/dtApOXJ0yljd5/8cA TP3dsWShbk3h+yoFTbznt7xpuf//NTN5c8d+LkSdZvrAk18LhIyidX8xl4pOeTui G/JpzXFmXrDKrHm7V6ZsYLrwwNwVBLFDe/KLojNDlPKhRbRuSONYTU4cZQeXfA/1 9/6/AoGAarF4JSdpzMzfacpLy2nsOM6XmL76B218uKANSHQy9k1X/Hp1u1StY8tQ H4+DSrRUQBb4sdxkCRXVvMH3zttDGoIrSUvDqN3k4opcP8nmzMc/EDwD3xFgri/p yBXBhE99r1B0p7fneXt58tTqtcevk5dQPzyF9SdsfUxD5PrnZRI= -----END RSA PRIVATE KEY-----";
var rsa = RSA.Create();
rsa.ImportFromPem(privateKey.ToCharArray());
byte[] sshrsaBytes = Encoding.Default.GetBytes("ssh-rsa");
byte[] n = rsa.ExportParameters(false).Modulus;
byte[] e = rsa.ExportParameters(false).Exponent;
string buffer64;
using (var ms = new MemoryStream())
{
ms.Write(ToBytes(sshrsaBytes.Length), 0, 4);
ms.Write(sshrsaBytes, 0, sshrsaBytes.Length);
ms.Write(ToBytes(e.Length), 0, 4);
ms.Write(e, 0, e.Length);
ms.Write(ToBytes(n.Length + 1), 0, 4);
ms.Write(new byte[] { 0 }, 0, 1);
ms.Write(n, 0, n.Length);
ms.Flush();
buffer64 = Convert.ToBase64String(ms.ToArray());
}
string comment = "administrator@LovelyTrust";
string publicKey = $"ssh-rsa {buffer64} {comment}";
Console.WriteLine(publicKey);
ToBytes
method is simply checks your machine's endianness and converts bytes into correct order if necessary.
We first create an RSA
object and import the private key, just like you did. After that, the complex part I mentioned starts, and continues until the end of the using
block. Finally, we concatenate that value with ssh-rsa word from the left and the comment (this is the value entered in Key comment text field if you use PuTTY Key Generator) from the right.
This code is heavily inspired from the code of SshKeyGenerator library. Unfortunately, the library itself does not support key import. On the other hand, if you want randomly generated SSH private and public key pairs, using directly the library will be probably easier and more convenient.