CertificateHostAlgorithmTest.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using Renci.SshNet.Security;
  9. using Renci.SshNet.Security.Cryptography;
  10. using Renci.SshNet.Tests.Common;
  11. namespace Renci.SshNet.Tests.Classes.Security
  12. {
  13. [TestClass]
  14. public class CertificateHostAlgorithmTest : TestBase
  15. {
  16. [TestMethod]
  17. public void NoSuppliedDigitalSignature_PropertyIsKeyDigitalSignature()
  18. {
  19. (RsaKey key, Certificate certificate) = GetRsaKey();
  20. CertificateHostAlgorithm algorithm = new("ssh-rsa-cert-v01@openssh.com", key, certificate);
  21. Assert.AreEqual("ssh-rsa-cert-v01@openssh.com", algorithm.Name);
  22. Assert.AreSame(key, algorithm.Key);
  23. Assert.AreSame(certificate, algorithm.Certificate);
  24. Assert.AreSame(key.DigitalSignature, algorithm.DigitalSignature);
  25. }
  26. [TestMethod]
  27. public void SuppliedDigitalSignature_PropertyIsSuppliedDigitalSignature()
  28. {
  29. (RsaKey key, Certificate certificate) = GetRsaKey();
  30. RsaDigitalSignature rsaDigitalSignature = new(key, HashAlgorithmName.SHA256);
  31. CertificateHostAlgorithm algorithm = new(
  32. "rsa-sha2-256-cert-v01@openssh.com",
  33. key,
  34. certificate,
  35. rsaDigitalSignature);
  36. Assert.AreEqual("rsa-sha2-256-cert-v01@openssh.com", algorithm.Name);
  37. Assert.AreSame(key, algorithm.Key);
  38. Assert.AreSame(certificate, algorithm.Certificate);
  39. Assert.AreSame(rsaDigitalSignature, algorithm.DigitalSignature);
  40. }
  41. [TestMethod]
  42. public void HostAlgorithmData_IsRawCertificateBytes()
  43. {
  44. PrivateKeyFile pkFile;
  45. byte[] certificateData;
  46. using (Stream keyStream = GetData("Key.OPENSSH.RSA.txt"))
  47. using (Stream certStream = GetData("Key.OPENSSH.RSA-cert.pub"))
  48. {
  49. using MemoryStream ms = new();
  50. certStream.CopyTo(ms);
  51. certificateData = Convert.FromBase64String(Encoding.UTF8.GetString(ms.ToArray()).Split(' ')[1]);
  52. ms.Position = 0;
  53. pkFile = new PrivateKeyFile(keyStream, null, ms);
  54. }
  55. List<CertificateHostAlgorithm> certAlgs = pkFile.HostKeyAlgorithms.OfType<CertificateHostAlgorithm>().ToList();
  56. Assert.AreEqual(3, certAlgs.Count);
  57. for (int i = 0; i < 3; i++)
  58. {
  59. Assert.IsNotNull(certAlgs[i].Certificate);
  60. Assert.AreSame(pkFile.Certificate, certAlgs[i].Certificate);
  61. CollectionAssert.AreEqual(certificateData, certAlgs[i].Data);
  62. }
  63. }
  64. [TestMethod]
  65. public void SshRsa_SignAndVerify()
  66. {
  67. byte[] data = Encoding.UTF8.GetBytes("hello world");
  68. (RsaKey key, Certificate certificate) = GetRsaKey();
  69. CertificateHostAlgorithm algorithm = new("ssh-rsa-cert-v01@openssh.com", key, certificate);
  70. byte[] expectedEncodedSignatureBytes = new byte[]
  71. {
  72. 0, 0, 0, 7, // byte count of "ssh-rsa"
  73. (byte)'s', (byte)'s', (byte)'h', (byte)'-', (byte)'r', (byte)'s', (byte)'a', // ssh-rsa
  74. 0, 0, 1, 0, // byte count of signature (=256)
  75. // ssh-keygen -e -f Key.OPENSSH.RSA.txt -m PEM -p
  76. // echo -n 'hello world' | openssl dgst -sha1 -sign Key.OPENSSH.RSA.txt -out test.signed
  77. 0x2d, 0x54, 0x2e, 0x6a, 0x5f, 0x7c, 0x29, 0x7d, 0x2d, 0x81, 0xf6, 0x34, 0x45, 0x7a, 0x3f, 0xd0,
  78. 0xa5, 0x06, 0x55, 0x9c, 0xab, 0x8c, 0x28, 0x76, 0x27, 0xc0, 0x8a, 0x32, 0x23, 0xa4, 0x62, 0xd1,
  79. 0x8c, 0x72, 0x05, 0x52, 0x47, 0x4d, 0xd0, 0xde, 0x86, 0xdd, 0xfc, 0x38, 0x54, 0x47, 0x4e, 0x17,
  80. 0xef, 0x6b, 0x9a, 0x2e, 0x4d, 0x55, 0xf3, 0x2a, 0x11, 0xa7, 0x3a, 0x8b, 0x37, 0xbb, 0x61, 0x2d,
  81. 0xb8, 0x4c, 0x1f, 0xa1, 0x0f, 0xb4, 0xbe, 0x06, 0xea, 0xc1, 0x4e, 0x17, 0x3c, 0x53, 0x01, 0x1b,
  82. 0x41, 0x3b, 0x3c, 0x86, 0xb7, 0x55, 0x4d, 0xe6, 0xcb, 0x9d, 0x0e, 0x6f, 0x18, 0x10, 0x63, 0x3c,
  83. 0xcd, 0x02, 0x32, 0x9f, 0xbe, 0x58, 0x22, 0xa1, 0x24, 0x61, 0xf3, 0x1e, 0xa8, 0xbd, 0xf7, 0x0e,
  84. 0x9a, 0xeb, 0x42, 0x5c, 0xf5, 0xdb, 0x3b, 0x65, 0x22, 0xb1, 0x54, 0x7f, 0xe0, 0x62, 0xae, 0xb3,
  85. 0xab, 0x7b, 0xfe, 0x4b, 0x80, 0x7a, 0xd1, 0x5e, 0xd2, 0x0a, 0xa3, 0x4d, 0x1a, 0xf5, 0xa8, 0xbf,
  86. 0x87, 0xfc, 0x91, 0x57, 0xf1, 0xc2, 0x58, 0xea, 0x7a, 0xbc, 0xdf, 0x86, 0xb4, 0x24, 0x32, 0x10,
  87. 0x72, 0x2e, 0x91, 0x15, 0xa7, 0x39, 0xb5, 0x22, 0x7a, 0xe1, 0x88, 0xbd, 0x23, 0xa6, 0x05, 0xe2,
  88. 0x20, 0x22, 0x46, 0x68, 0x56, 0x34, 0x2e, 0x08, 0x35, 0xa7, 0x4b, 0x4f, 0x54, 0xcb, 0xf9, 0x53,
  89. 0xd1, 0x41, 0xf6, 0xac, 0x23, 0xf8, 0x0e, 0x90, 0x1e, 0xea, 0x4c, 0xdb, 0xa3, 0xb6, 0xdb, 0x5f,
  90. 0xf9, 0xc4, 0xf3, 0x08, 0x12, 0x32, 0xa8, 0xa2, 0xa1, 0x8c, 0x1d, 0x5f, 0xf7, 0x18, 0x79, 0x4c,
  91. 0xd4, 0x28, 0xc6, 0xe9, 0x55, 0xbc, 0x80, 0xc2, 0x08, 0x1f, 0x8f, 0x8d, 0x35, 0x0b, 0xa9, 0x49,
  92. 0x80, 0xba, 0x32, 0xba, 0xe0, 0xf6, 0x2f, 0x7f, 0xf2, 0xb7, 0xaf, 0xfa, 0xfd, 0xc8, 0x7a, 0x66,
  93. };
  94. CollectionAssert.AreEqual(expectedEncodedSignatureBytes, algorithm.Sign(data));
  95. algorithm = new CertificateHostAlgorithm(
  96. "ssh-rsa-cert-v01@openssh.com",
  97. certificate,
  98. DefaultKeyAlgs);
  99. Assert.IsTrue(algorithm.VerifySignature(data, expectedEncodedSignatureBytes));
  100. }
  101. [TestMethod]
  102. public void RsaSha256_SignAndVerify()
  103. {
  104. byte[] data = Encoding.UTF8.GetBytes("hello world");
  105. (RsaKey key, Certificate certificate) = GetRsaKey();
  106. CertificateHostAlgorithm algorithm = new(
  107. "rsa-sha2-256-cert-v01@openssh.com",
  108. key,
  109. certificate,
  110. new RsaDigitalSignature(key, HashAlgorithmName.SHA256));
  111. byte[] expectedEncodedSignatureBytes = new byte[]
  112. {
  113. 0, 0, 0, 12, // byte count of "rsa-sha2-256"
  114. (byte)'r', (byte)'s', (byte)'a', (byte)'-', (byte)'s', (byte)'h', (byte)'a', (byte)'2',
  115. (byte)'-', (byte)'2', (byte)'5', (byte)'6',
  116. 0, 0, 1, 0, // byte count of signature (=256)
  117. // ssh-keygen -e -f Key.OPENSSH.RSA.txt -m PEM -p
  118. // echo -n 'hello world' | openssl dgst -sha256 -sign Key.OPENSSH.RSA.txt -out test.signed
  119. 0x18, 0xf4, 0x3e, 0xa9, 0xdf, 0x89, 0x92, 0x6b, 0xc1, 0x6a, 0x35, 0x72, 0x42, 0x56, 0xf7, 0x50,
  120. 0x32, 0x33, 0xff, 0xc4, 0x91, 0x3d, 0x49, 0x12, 0x37, 0x52, 0x98, 0x37, 0xb8, 0xeb, 0xeb, 0xaa,
  121. 0xe5, 0x4e, 0xd4, 0x99, 0x74, 0xfd, 0xea, 0xd6, 0x8f, 0x34, 0xa0, 0x3a, 0x0e, 0xfd, 0xcb, 0xae,
  122. 0x04, 0x20, 0x01, 0x1c, 0x67, 0x98, 0x94, 0x6c, 0xdb, 0x26, 0x9a, 0x0c, 0x5b, 0xcf, 0x9a, 0x06,
  123. 0xa5, 0x90, 0xfb, 0x62, 0xe8, 0x56, 0x91, 0xdf, 0x63, 0x1f, 0xc3, 0xb1, 0xd3, 0x4f, 0x18, 0x2b,
  124. 0x2e, 0xfa, 0xb4, 0x61, 0x1d, 0x54, 0xdd, 0x63, 0x14, 0x17, 0x31, 0x8e, 0x86, 0xe3, 0xc2, 0xb1,
  125. 0x30, 0x42, 0x1e, 0x5a, 0x43, 0x87, 0x54, 0x64, 0xd5, 0xbb, 0xcb, 0x37, 0x7b, 0xa6, 0x97, 0x75,
  126. 0xca, 0x3b, 0x0d, 0xb2, 0x24, 0x34, 0x0b, 0xfc, 0xde, 0x67, 0xbf, 0xdf, 0x2a, 0x8b, 0xc6, 0xac,
  127. 0x51, 0x0d, 0x98, 0x54, 0xed, 0x57, 0x5e, 0xa9, 0xbe, 0x0f, 0x0c, 0x0f, 0x30, 0x23, 0x96, 0x83,
  128. 0x65, 0x74, 0x87, 0x91, 0x99, 0x21, 0x88, 0x80, 0x6d, 0xe4, 0xec, 0xcb, 0x51, 0xe5, 0xe5, 0x3a,
  129. 0x2b, 0x34, 0x9b, 0x10, 0x70, 0xef, 0x57, 0x40, 0x59, 0x45, 0x94, 0x58, 0xd0, 0x65, 0x84, 0x23,
  130. 0x5e, 0xcd, 0x49, 0xea, 0x18, 0x51, 0x29, 0xdd, 0x84, 0x05, 0x24, 0xe4, 0x65, 0x0c, 0x38, 0x8e,
  131. 0x42, 0x33, 0xdf, 0xcb, 0x3c, 0xa0, 0x0d, 0xe2, 0x2d, 0x13, 0xbd, 0xea, 0x51, 0x06, 0xdd, 0x61,
  132. 0x87, 0x05, 0xbe, 0xef, 0xaa, 0x77, 0xe4, 0xef, 0x25, 0x6b, 0xbf, 0x24, 0xd7, 0xe4, 0xba, 0x25,
  133. 0x28, 0x49, 0x26, 0xc2, 0x31, 0xca, 0xbb, 0x1a, 0x2c, 0x19, 0xa3, 0x7b, 0x62, 0x12, 0x59, 0x75,
  134. 0x12, 0x03, 0x38, 0xc9, 0x69, 0x93, 0xe6, 0xec, 0xc8, 0x13, 0x25, 0x48, 0xd2, 0x6c, 0x67, 0x10,
  135. };
  136. CollectionAssert.AreEqual(expectedEncodedSignatureBytes, algorithm.Sign(data));
  137. algorithm = new CertificateHostAlgorithm(
  138. "rsa-sha2-256-cert-v01@openssh.com",
  139. certificate,
  140. new RsaDigitalSignature((RsaKey)certificate.Key, HashAlgorithmName.SHA256),
  141. DefaultKeyAlgs);
  142. Assert.IsTrue(algorithm.VerifySignature(data, expectedEncodedSignatureBytes));
  143. }
  144. [TestMethod]
  145. public void RsaSha512_SignAndVerify()
  146. {
  147. byte[] data = Encoding.UTF8.GetBytes("hello world");
  148. (RsaKey key, Certificate certificate) = GetRsaKey();
  149. CertificateHostAlgorithm algorithm = new(
  150. "rsa-sha2-512-cert-v01@openssh.com",
  151. key,
  152. certificate,
  153. new RsaDigitalSignature(key, HashAlgorithmName.SHA512));
  154. byte[] expectedEncodedSignatureBytes = new byte[]
  155. {
  156. 0, 0, 0, 12, // byte count of "rsa-sha2-512"
  157. (byte)'r', (byte)'s', (byte)'a', (byte)'-', (byte)'s', (byte)'h', (byte)'a', (byte)'2',
  158. (byte)'-', (byte)'5', (byte)'1', (byte)'2',
  159. 0, 0, 1, 0, // byte count of signature (=256)
  160. // ssh-keygen -e -f Key.OPENSSH.RSA.txt -m PEM -p
  161. // echo -n 'hello world' | openssl dgst -sha512 -sign Key.OPENSSH.RSA.txt -out test.signed
  162. 0x1d, 0x64, 0xc6, 0x82, 0xb0, 0xc4, 0x2b, 0xe1, 0x71, 0x13, 0x1f, 0x62, 0xab, 0x8f, 0xf8, 0x72,
  163. 0x43, 0xe8, 0x95, 0x4c, 0x8d, 0xa6, 0xf7, 0xcd, 0x62, 0xc9, 0x6f, 0xe5, 0xbf, 0x23, 0x1b, 0xc7,
  164. 0xa0, 0x93, 0xc6, 0xc0, 0xa2, 0x06, 0x2d, 0x07, 0x16, 0x59, 0xbc, 0x0d, 0xe5, 0x00, 0x39, 0x56,
  165. 0xa7, 0xde, 0x4b, 0x17, 0xf4, 0x02, 0xf6, 0x5d, 0x8f, 0xc5, 0x76, 0xe2, 0xb7, 0xae, 0xe5, 0xa2,
  166. 0x7f, 0xd8, 0x34, 0x04, 0x2c, 0xbc, 0xdf, 0x84, 0x51, 0x69, 0x83, 0xda, 0x7a, 0x74, 0x19, 0xe9,
  167. 0x6e, 0x02, 0xf8, 0x51, 0x20, 0xa2, 0x67, 0x43, 0xbb, 0xde, 0x7a, 0xa7, 0x12, 0xe7, 0x89, 0x7c,
  168. 0x50, 0xf3, 0xd5, 0x07, 0xc9, 0x70, 0x22, 0xed, 0x2e, 0x45, 0x1e, 0x49, 0x23, 0x94, 0x69, 0xae,
  169. 0x8f, 0x5d, 0x3b, 0x34, 0xdb, 0xc8, 0x49, 0x26, 0x09, 0x81, 0x7d, 0xad, 0x77, 0xb5, 0x6d, 0xad,
  170. 0x0c, 0x9f, 0x66, 0x29, 0x56, 0xff, 0xea, 0xa7, 0x6f, 0x7f, 0xcd, 0xc0, 0x15, 0x05, 0xdc, 0xee,
  171. 0xfb, 0xac, 0xfd, 0x59, 0x19, 0x30, 0x32, 0x6e, 0x16, 0xe0, 0x4e, 0x74, 0x6a, 0x13, 0xa7, 0x9f,
  172. 0x5b, 0x71, 0x75, 0x13, 0xcf, 0xa5, 0xf3, 0x07, 0x8f, 0xfb, 0xa2, 0xa2, 0x92, 0xc2, 0x41, 0xc4,
  173. 0xbc, 0x14, 0x75, 0x22, 0xe3, 0x4b, 0xb7, 0xc0, 0x54, 0xc3, 0x25, 0x87, 0xbb, 0x52, 0xde, 0x70,
  174. 0x69, 0xc6, 0x68, 0x66, 0x3a, 0x88, 0xf6, 0x3b, 0x8e, 0x44, 0x00, 0x25, 0x17, 0xc9, 0x44, 0x7c,
  175. 0xcc, 0x0c, 0x63, 0xab, 0xa3, 0x2c, 0xaa, 0x4c, 0x34, 0xda, 0xe0, 0x96, 0x71, 0x83, 0xe5, 0x7a,
  176. 0xec, 0x56, 0xbe, 0x85, 0x27, 0x7c, 0xe7, 0x79, 0xfd, 0xb8, 0x77, 0x41, 0x05, 0x25, 0x30, 0x57,
  177. 0x24, 0x45, 0xa9, 0x12, 0x9e, 0xdc, 0x9e, 0x23, 0x43, 0x13, 0x67, 0x38, 0x59, 0xae, 0x4b, 0x76,
  178. };
  179. CollectionAssert.AreEqual(expectedEncodedSignatureBytes, algorithm.Sign(data));
  180. algorithm = new CertificateHostAlgorithm(
  181. "rsa-sha2-512-cert-v01@openssh.com",
  182. certificate,
  183. new RsaDigitalSignature((RsaKey)certificate.Key, HashAlgorithmName.SHA512),
  184. DefaultKeyAlgs);
  185. Assert.IsTrue(algorithm.VerifySignature(data, expectedEncodedSignatureBytes));
  186. }
  187. [TestMethod]
  188. public void VerifySignature_NoCorrespondingAlgorithm_ReturnsFalse()
  189. {
  190. byte[] data = Encoding.UTF8.GetBytes("hello world");
  191. (RsaKey key, Certificate certificate) = GetRsaKey();
  192. CertificateHostAlgorithm algorithm = new(
  193. "rsa-sha2-512-cert-v01@openssh.com",
  194. key,
  195. certificate,
  196. new RsaDigitalSignature(key, HashAlgorithmName.SHA512));
  197. byte[] signature = algorithm.Sign(data);
  198. algorithm = new CertificateHostAlgorithm(
  199. "rsa-sha2-512-cert-v01@openssh.com",
  200. certificate,
  201. new RsaDigitalSignature((RsaKey)certificate.Key, HashAlgorithmName.SHA512),
  202. new Dictionary<string, Func<byte[], KeyHostAlgorithm>>());
  203. Assert.IsFalse(algorithm.VerifySignature(data, signature));
  204. }
  205. [TestMethod]
  206. public void VerifySignature_NoSuppliedAlgorithms_Throws()
  207. {
  208. byte[] data = Encoding.UTF8.GetBytes("hello world");
  209. (RsaKey key, Certificate certificate) = GetRsaKey();
  210. CertificateHostAlgorithm algorithm = new(
  211. "rsa-sha2-512-cert-v01@openssh.com",
  212. key,
  213. certificate,
  214. new RsaDigitalSignature(key, HashAlgorithmName.SHA512));
  215. byte[] signature = algorithm.Sign(data);
  216. var ex = Assert.ThrowsException<InvalidOperationException>(() => algorithm.VerifySignature(data, signature));
  217. Assert.IsTrue(ex.Message.StartsWith("Invalid usage", StringComparison.Ordinal));
  218. }
  219. [TestMethod]
  220. public void CertificateBadCASignature_VerifySignatureReturnsFalse()
  221. {
  222. // ssh-keygen -s Key.OPENSSH.ED25519.txt -I test Key.OPENSSH.ECDSA.txt
  223. string goodCertString = "ecdsa-sha2-nistp256-cert-v01@openssh.com " +
  224. "AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AA" +
  225. "AAg1vQFCYTYufJiCBFJBWc63sOGwnJ3BHQn4ig499dtB0AAAAAIbmlzdHAyNT" +
  226. "YAAABBBI/dlNvfssW9KYrB67TcDmz9zBzDf7eMvUupAroP3b3FjUnYnpL3Utc" +
  227. "4GkF/PiX7w2DuxaG70/+EX/CYHZBHKCsAAAAAAAAAAAAAAAEAAAAEdGVzdAAA" +
  228. "AAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3Y" +
  229. "XJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcG" +
  230. "VybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAA" +
  231. "OcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAg" +
  232. "DQlmcNCvFBlw0At9lgbss8BbUxgQa9VbmeN7s6UwYyIAAABTAAAAC3NzaC1lZ" +
  233. "DI1NTE5AAAAQA8+LXQ++nb1/gNEtURKt5Yo/geUc/+3+Bv3EPGno5JhxvekjJ" +
  234. "PD7/nXcyxnY3zALlPQTxb19EVx5lz58BS96gg=";
  235. char[] chars = goodCertString.ToCharArray();
  236. chars[^10] = 'a';
  237. string badCertString = new string(chars);
  238. Assert.IsTrue(VerifySignature(goodCertString));
  239. Assert.IsFalse(VerifySignature(badCertString));
  240. static bool VerifySignature(string certString)
  241. {
  242. PrivateKeyFile pk;
  243. using (Stream keyStream = GetData("Key.OPENSSH.ECDSA.txt"))
  244. using (MemoryStream certStream = new MemoryStream(Encoding.UTF8.GetBytes(certString)))
  245. {
  246. pk = new PrivateKeyFile(keyStream, null, certStream);
  247. }
  248. Assert.IsNotNull(pk.Certificate);
  249. byte[] data = Encoding.UTF8.GetBytes("hello world");
  250. CertificateHostAlgorithm certificateAlgorithm = new(
  251. "ecdsa-sha2-nistp256-cert-v01@openssh.com",
  252. pk.Certificate,
  253. DefaultKeyAlgs);
  254. KeyHostAlgorithm keyHostAlgorithm = new KeyHostAlgorithm("ecdsa-sha2-nistp256", pk.Key);
  255. byte[] signature = keyHostAlgorithm.Sign(data);
  256. Assert.IsTrue(keyHostAlgorithm.VerifySignature(data, signature));
  257. return certificateAlgorithm.VerifySignature(data, signature);
  258. }
  259. }
  260. [TestMethod]
  261. public void CertificateValidityPeriodExpired_VerifySignatureReturnsFalse()
  262. {
  263. // ssh-keygen -s Key.OPENSSH.ED25519.txt -I nolongervalid -V always:20240101 Key.OPENSSH.ECDSA.txt
  264. string certString = "ecdsa-sha2-nistp256-cert-v01@openssh.com " +
  265. "AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb" +
  266. "20AAAAg5BUo6CqGzTDc0UgNcLUqna2bH3C69NZCzd9CrQ8apQUAAAAIbm" +
  267. "lzdHAyNTYAAABBBI/dlNvfssW9KYrB67TcDmz9zBzDf7eMvUupAroP3b3" +
  268. "FjUnYnpL3Utc4GkF/PiX7w2DuxaG70/+EX/CYHZBHKCsAAAAAAAAAAAAA" +
  269. "AAEAAAANbm9sb25nZXJ2YWxpZAAAAAAAAAAAAAAAAAAAAABlkgCAAAAAA" +
  270. "AAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaX" +
  271. "QtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2F" +
  272. "yZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXIt" +
  273. "cmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgDQlmcNCvFBlw0" +
  274. "At9lgbss8BbUxgQa9VbmeN7s6UwYyIAAABTAAAAC3NzaC1lZDI1NTE5AA" +
  275. "AAQMonLi0J282GmuMVyHGKS/PRoLpdj5GgmR0wrIkExRRCzKZaycLfPDL" +
  276. "+CGMa2jsH2QhFhTCG5AtKWVQbkqdHVAY= (null)";
  277. PrivateKeyFile pk;
  278. using (Stream keyStream = GetData("Key.OPENSSH.ECDSA.txt"))
  279. using (MemoryStream certStream = new MemoryStream(Encoding.UTF8.GetBytes(certString)))
  280. {
  281. pk = new PrivateKeyFile(keyStream, null, certStream);
  282. }
  283. Assert.IsNotNull(pk.Certificate);
  284. Assert.AreEqual(0uL, pk.Certificate.ValidAfterUnixSeconds);
  285. Assert.AreEqual(new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero), pk.Certificate.ValidBefore);
  286. byte[] data = Encoding.UTF8.GetBytes("hello world");
  287. CertificateHostAlgorithm certificateAlgorithm = new(
  288. "ecdsa-sha2-nistp256-cert-v01@openssh.com",
  289. pk.Certificate,
  290. DefaultKeyAlgs);
  291. KeyHostAlgorithm keyHostAlgorithm = new KeyHostAlgorithm("ecdsa-sha2-nistp256", pk.Key);
  292. byte[] signature = keyHostAlgorithm.Sign(data);
  293. Assert.IsTrue(keyHostAlgorithm.VerifySignature(data, signature));
  294. Assert.IsFalse(certificateAlgorithm.VerifySignature(data, signature));
  295. }
  296. private static (RsaKey Key, Certificate Certificate) GetRsaKey()
  297. {
  298. using (Stream keyStream = GetData("Key.OPENSSH.RSA.txt"))
  299. using (Stream certStream = GetData("Key.OPENSSH.RSA-cert.pub"))
  300. {
  301. var pkFile = new PrivateKeyFile(keyStream, null, certStream);
  302. return (Key: (RsaKey)pkFile.Key, pkFile.Certificate);
  303. }
  304. }
  305. private static IReadOnlyDictionary<string, Func<byte[], KeyHostAlgorithm>> DefaultKeyAlgs
  306. {
  307. get
  308. {
  309. return new Dictionary<string, Func<byte[], KeyHostAlgorithm>>(
  310. new PasswordConnectionInfo("x", "y", "z").HostKeyAlgorithms);
  311. }
  312. }
  313. }
  314. }