Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/mRemoteNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ExternalConnectors/PuttyKeyFileGenerator.cs')
-rw-r--r--ExternalConnectors/PuttyKeyFileGenerator.cs109
1 files changed, 109 insertions, 0 deletions
diff --git a/ExternalConnectors/PuttyKeyFileGenerator.cs b/ExternalConnectors/PuttyKeyFileGenerator.cs
new file mode 100644
index 00000000..6c62bca7
--- /dev/null
+++ b/ExternalConnectors/PuttyKeyFileGenerator.cs
@@ -0,0 +1,109 @@
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace ExternalConnectors;
+
+public class PuttyKeyFileGenerator
+{
+ private const int prefixSize = 4;
+ private const int paddedPrefixSize = prefixSize + 1;
+ private const int lineLength = 64;
+ private const string keyType = "ssh-rsa";
+ private const string encryptionType = "none";
+
+ // source from
+ // https://gist.github.com/canton7/5670788?permalink_comment_id=3240331
+ // https://gist.github.com/bosima/ee6630d30b533c7d7b2743a849e9b9d0
+
+ public static string ToPuttyPrivateKey(RSACryptoServiceProvider cryptoServiceProvider, string Comment = "imported-openssh-key")
+ {
+ var publicParameters = cryptoServiceProvider.ExportParameters(false);
+ byte[] publicBuffer = new byte[3 + keyType.Length + GetPrefixSize(publicParameters.Exponent) + publicParameters.Exponent.Length +
+ GetPrefixSize(publicParameters.Modulus) + publicParameters.Modulus.Length + 1];
+
+ using (var bw = new BinaryWriter(new MemoryStream(publicBuffer)))
+ {
+ bw.Write(new byte[] { 0x00, 0x00, 0x00 });
+ bw.Write(keyType);
+ PutPrefixed(bw, publicParameters.Exponent, CheckIsNeddPadding(publicParameters.Exponent));
+ PutPrefixed(bw, publicParameters.Modulus, CheckIsNeddPadding(publicParameters.Modulus));
+ }
+ var publicBlob = System.Convert.ToBase64String(publicBuffer);
+
+ var privateParameters = cryptoServiceProvider.ExportParameters(true);
+ byte[] privateBuffer = new byte[paddedPrefixSize + privateParameters.D.Length + paddedPrefixSize + privateParameters.P.Length + paddedPrefixSize + privateParameters.Q.Length + paddedPrefixSize + privateParameters.InverseQ.Length];
+
+ using (var bw = new BinaryWriter(new MemoryStream(privateBuffer)))
+ {
+ PutPrefixed(bw, privateParameters.D, true);
+ PutPrefixed(bw, privateParameters.P, true);
+ PutPrefixed(bw, privateParameters.Q, true);
+ PutPrefixed(bw, privateParameters.InverseQ, true);
+ }
+ var privateBlob = System.Convert.ToBase64String(privateBuffer);
+
+ HMACSHA1 hmacsha1 = new HMACSHA1(new SHA1CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes("putty-private-key-file-mac-key")));
+ //byte[] bytesToHash = new byte[4 + 7 + 4 + 4 + 4 + Comment.Length + 4 + publicBuffer.Length + 4 + privateBuffer.Length];
+ byte[] bytesToHash = new byte[prefixSize + keyType.Length + prefixSize + encryptionType.Length + prefixSize + Comment.Length +
+ prefixSize + publicBuffer.Length + prefixSize + privateBuffer.Length];
+
+ using (var bw = new BinaryWriter(new MemoryStream(bytesToHash)))
+ {
+ PutPrefixed(bw, Encoding.ASCII.GetBytes("ssh-rsa"));
+ PutPrefixed(bw, Encoding.ASCII.GetBytes("none"));
+ PutPrefixed(bw, Encoding.ASCII.GetBytes(Comment));
+ PutPrefixed(bw, publicBuffer);
+ PutPrefixed(bw, privateBuffer);
+ }
+
+ var hash = string.Join("", hmacsha1.ComputeHash(bytesToHash).Select(x => string.Format("{0:x2}", x)));
+
+ var sb = new StringBuilder();
+ sb.AppendLine("PuTTY-User-Key-File-2: " + keyType);
+ sb.AppendLine("Encryption: " + encryptionType);
+ sb.AppendLine("Comment: " + Comment);
+
+ var publicLines = SpliceText(publicBlob, lineLength);
+ sb.AppendLine("Public-Lines: " + publicLines.Length);
+ foreach (var line in publicLines)
+ {
+ sb.AppendLine(line);
+ }
+
+ var privateLines = SpliceText(privateBlob, lineLength);
+ sb.AppendLine("Private-Lines: " + privateLines.Length);
+ foreach (var line in privateLines)
+ {
+ sb.AppendLine(line);
+ }
+
+ sb.AppendLine("Private-MAC: " + hash);
+
+ return sb.ToString();
+ }
+ private static void PutPrefixed(BinaryWriter bw, byte[] bytes, bool addLeadingNull = false)
+ {
+ bw.Write(BitConverter.GetBytes(bytes.Length + (addLeadingNull ? 1 : 0)).Reverse().ToArray());
+ if (addLeadingNull)
+ bw.Write(new byte[] { 0x00 });
+ bw.Write(bytes);
+ }
+
+ private static string[] SpliceText(string text, int lineLength)
+ {
+ return Regex.Matches(text, ".{1," + lineLength + "}").Cast<Match>().Select(m => m.Value).ToArray();
+ }
+ private static int GetPrefixSize(byte[] bytes)
+ {
+ return CheckIsNeddPadding(bytes) ? paddedPrefixSize : prefixSize;
+ }
+ private static bool CheckIsNeddPadding(byte[] bytes)
+ {
+ // 128 == 10000000
+ // This means that the number of bits can be divided by 8.
+ // According to the algorithm in putty, you need to add a padding.
+ return bytes[0] >= 128;
+ }
+
+} \ No newline at end of file