KeyExchangeDiffieHellmanGroupExchangeShaBase.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using Renci.SshNet.Messages.Transport;
  2. namespace Renci.SshNet.Security
  3. {
  4. /// <summary>
  5. /// Base class for "diffie-hellman-group-exchange" algorithms.
  6. /// </summary>
  7. internal abstract class KeyExchangeDiffieHellmanGroupExchangeShaBase : KeyExchangeDiffieHellman
  8. {
  9. private const int MinimumGroupSize = 1024;
  10. private const int PreferredGroupSize = 1024;
  11. private const int MaximumProupSize = 8192;
  12. /// <summary>
  13. /// Calculates key exchange hash value.
  14. /// </summary>
  15. /// <returns>
  16. /// Key exchange hash.
  17. /// </returns>
  18. protected override byte[] CalculateHash()
  19. {
  20. var hashData = new GroupExchangeHashData
  21. {
  22. ClientVersion = Session.ClientVersion,
  23. ServerVersion = Session.ServerVersion,
  24. ClientPayload = _clientPayload,
  25. ServerPayload = _serverPayload,
  26. HostKey = _hostKey,
  27. MinimumGroupSize = MinimumGroupSize,
  28. PreferredGroupSize = PreferredGroupSize,
  29. MaximumGroupSize = MaximumProupSize,
  30. Prime = _prime,
  31. SubGroup = _group,
  32. ClientExchangeValue = _clientExchangeValue,
  33. ServerExchangeValue = _serverExchangeValue,
  34. SharedKey = SharedKey,
  35. }.GetBytes();
  36. return Hash(hashData);
  37. }
  38. /// <summary>
  39. /// Starts key exchange algorithm
  40. /// </summary>
  41. /// <param name="session">The session.</param>
  42. /// <param name="message">Key exchange init message.</param>
  43. public override void Start(Session session, KeyExchangeInitMessage message)
  44. {
  45. base.Start(session, message);
  46. // Register SSH_MSG_KEX_DH_GEX_GROUP message
  47. Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
  48. // Subscribe to KeyExchangeDhGroupExchangeGroupReceived events
  49. Session.KeyExchangeDhGroupExchangeGroupReceived += Session_KeyExchangeDhGroupExchangeGroupReceived;
  50. // 1. client sends SSH_MSG_KEY_DH_GEX_REQUEST
  51. SendMessage(new KeyExchangeDhGroupExchangeRequest(MinimumGroupSize, PreferredGroupSize,
  52. MaximumProupSize));
  53. }
  54. /// <summary>
  55. /// Finishes key exchange algorithm.
  56. /// </summary>
  57. public override void Finish()
  58. {
  59. base.Finish();
  60. Session.KeyExchangeDhGroupExchangeGroupReceived -= Session_KeyExchangeDhGroupExchangeGroupReceived;
  61. Session.KeyExchangeDhGroupExchangeReplyReceived -= Session_KeyExchangeDhGroupExchangeReplyReceived;
  62. }
  63. private void Session_KeyExchangeDhGroupExchangeGroupReceived(object sender, MessageEventArgs<KeyExchangeDhGroupExchangeGroup> e)
  64. {
  65. // 2. server sends SSH_MSG_KEX_DH_GEX_GROUP
  66. var groupMessage = e.Message;
  67. // Unregister SSH_MSG_KEX_DH_GEX_GROUP message once received
  68. Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
  69. // Unsubscribe from KeyExchangeDhGroupExchangeGroupReceived events
  70. Session.KeyExchangeDhGroupExchangeGroupReceived -= Session_KeyExchangeDhGroupExchangeGroupReceived;
  71. // Register in order to be able to receive SSH_MSG_KEX_DH_GEX_REPLY message
  72. Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
  73. // Subscribe to KeyExchangeDhGroupExchangeReplyReceived events
  74. Session.KeyExchangeDhGroupExchangeReplyReceived += Session_KeyExchangeDhGroupExchangeReplyReceived;
  75. _prime = groupMessage.SafePrime;
  76. _group = groupMessage.SubGroup;
  77. PopulateClientExchangeValue();
  78. // 3. client sends SSH_MSG_KEX_DH_GEX_INIT
  79. SendMessage(new KeyExchangeDhGroupExchangeInit(_clientExchangeValue));
  80. }
  81. private void Session_KeyExchangeDhGroupExchangeReplyReceived(object sender, MessageEventArgs<KeyExchangeDhGroupExchangeReply> e)
  82. {
  83. // 4. server sends SSH_MSG_KEX_DH_GEX_REPLY
  84. var replyMessage = e.Message;
  85. // Unregister SSH_MSG_KEX_DH_GEX_REPLY message once received
  86. Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
  87. // Unsubscribe from KeyExchangeDhGroupExchangeReplyReceived events
  88. Session.KeyExchangeDhGroupExchangeReplyReceived -= Session_KeyExchangeDhGroupExchangeReplyReceived;
  89. HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
  90. // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
  91. Finish();
  92. }
  93. }
  94. }