From 3d9017009ec21ee908ac2689222745872bc400ee Mon Sep 17 00:00:00 2001 From: Stefan Rinkes Date: Tue, 19 Mar 2024 06:54:16 +0100 Subject: [PATCH] Add Tests for PuTTY-Format --- SshNet.Keygen.Tests/TestKey.cs | 77 +++++++++++++++++++---------- SshNet.Keygen/SshKey.cs | 2 +- SshNet.Keygen/SshKeyGenerateInfo.cs | 2 +- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/SshNet.Keygen.Tests/TestKey.cs b/SshNet.Keygen.Tests/TestKey.cs index eb7b7d0..39b6db9 100644 --- a/SshNet.Keygen.Tests/TestKey.cs +++ b/SshNet.Keygen.Tests/TestKey.cs @@ -28,6 +28,9 @@ public void TestExceptions() keyInfo.KeyType = SshKeyType.RSA; Assert.Throws(() => SshKey.Generate(keyInfo)); + + var key = SshKey.Generate(); + Assert.Throws(() => key.ToPuttyFormat(SshKeyFormat.OpenSSH)); } [Test] @@ -41,7 +44,7 @@ public void TestDefaultKey() private static void KeyGenTest(SshKeyType keyType, int keyLength = 0) { const string password = "12345"; - var comments = new[] { "", "Generated by SshNet.Keygen"}; + var comments = new[] { null, "", "Generated by SshNet.Keygen"}; var sshKeyEncryptions = new List() { @@ -57,24 +60,14 @@ private static void KeyGenTest(SshKeyType keyType, int keyLength = 0) { foreach (var sshKeyEncryption in sshKeyEncryptions) { - TestContext.WriteLine($"File: {path} - Encryption: {sshKeyEncryption}"); + TestContext.WriteLine($"File: '{path}' - Encryption: '{sshKeyEncryption}' - Comment: '{comment}'"); var keyInfo = new SshKeyGenerateInfo(keyType) { Encryption = sshKeyEncryption, - KeyLength = keyLength - }; - if (!string.IsNullOrEmpty(comment)) - keyInfo.Comment = comment; - - var puttyKeyInfo = new SshKeyGenerateInfo(keyType) - { - KeyFormat = SshKeyFormat.PuTTYv3, - Encryption = sshKeyEncryption, - KeyLength = keyLength + KeyLength = keyLength, + Comment = comment }; - if (!string.IsNullOrEmpty(comment)) - puttyKeyInfo.Comment = comment; IPrivateKeySource keyFile; if (string.IsNullOrEmpty(path)) @@ -89,16 +82,49 @@ private static void KeyGenTest(SshKeyType keyType, int keyLength = 0) keyFile = new PrivateKeyFile(path, password); ClassicAssert.IsTrue(File.Exists(path)); - switch (sshKeyEncryption.CipherName) + foreach (var keyFormat in new List { SshKeyFormat.PuTTYv2 , SshKeyFormat.PuTTYv3 }) { - case "aes256-ctr": - Assert.Throws(() => SshKey.Generate($"{path}.ppk", FileMode.Create, puttyKeyInfo)); - break; - default: - File.Delete($"{path}.ppk"); - _ = SshKey.Generate($"{path}.ppk", FileMode.Create, puttyKeyInfo); - ClassicAssert.IsTrue(File.Exists($"{path}.ppk")); - break; + keyInfo.KeyFormat = keyFormat; + var puttyFile = $"{path}-{keyFormat}.ppk"; + + switch (sshKeyEncryption.CipherName) + { + case "aes256-ctr": + Assert.Throws(() => SshKey.Generate(puttyFile, FileMode.Create, keyInfo)); + break; + default: + File.Delete(puttyFile); + _ = SshKey.Generate(puttyFile, FileMode.Create, keyInfo); + ClassicAssert.IsTrue(File.Exists(puttyFile)); + + var puttyContent = File.ReadAllText(puttyFile); + + StringAssert.Contains( + comment is null + ? $"Comment: {SshKeyGenerateInfo.DefaultSshKeyComment}" + : $"Comment: {comment}", puttyContent); + + StringAssert.Contains($"Encryption: {sshKeyEncryption.CipherName}", puttyContent); + + switch (keyFormat) + { + case SshKeyFormat.PuTTYv2: + StringAssert.Contains("PuTTY-User-Key-File-2: ", puttyContent); + break; + case SshKeyFormat.PuTTYv3: + StringAssert.Contains("PuTTY-User-Key-File-3: ", puttyContent); + if (keyInfo.Encryption is SshKeyEncryptionAes256) + { + StringAssert.Contains("Key-Derivation: Argon2id", puttyContent); + StringAssert.Contains("Argon2-Memory: 8192", puttyContent); + StringAssert.Contains("Argon2-Passes: 22", puttyContent); + StringAssert.Contains("Argon2-Parallelism: 1", puttyContent); + StringAssert.Contains("Argon2-Salt:", puttyContent); + } + break; + } + break; + } } } @@ -106,10 +132,7 @@ private static void KeyGenTest(SshKeyType keyType, int keyLength = 0) if (keyLength != 0) ClassicAssert.AreEqual(keyLength, (((KeyHostAlgorithm) keyFile.HostKeyAlgorithms.First()).Key.KeyLength)); - ClassicAssert.AreEqual( - string.IsNullOrEmpty(comment) - ? $"{Environment.UserName}@{Environment.MachineName}" - : comment, + ClassicAssert.AreEqual(comment ?? SshKeyGenerateInfo.DefaultSshKeyComment, ((KeyHostAlgorithm) keyFile.HostKeyAlgorithms.First()).Key.Comment); } } diff --git a/SshNet.Keygen/SshKey.cs b/SshNet.Keygen/SshKey.cs index e961975..ef69cf0 100644 --- a/SshNet.Keygen/SshKey.cs +++ b/SshNet.Keygen/SshKey.cs @@ -119,7 +119,7 @@ public static GeneratedPrivateKey Generate(SshKeyGenerateInfo info) throw new NotSupportedException($"Unsupported KeyType: {info.KeyType}"); } - key.Comment = info.Comment; + key.Comment = info.Comment ?? SshKeyGenerateInfo.DefaultSshKeyComment; return new GeneratedPrivateKey(key, info); } diff --git a/SshNet.Keygen/SshKeyGenerateInfo.cs b/SshNet.Keygen/SshKeyGenerateInfo.cs index a617cc9..ef0aaa6 100644 --- a/SshNet.Keygen/SshKeyGenerateInfo.cs +++ b/SshNet.Keygen/SshKeyGenerateInfo.cs @@ -23,7 +23,7 @@ public class SshKeyGenerateInfo public ISshKeyEncryption Encryption { get; set; } - public string Comment { get; set; } + public string? Comment { get; set; } public SshKeyFormat KeyFormat { get; set; }