KeyExchangeDiffieHellmanGroupExchangeSha256.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Renci.SshNet.Messages.Transport;
  6. using System.Security.Cryptography;
  7. using Renci.SshNet.Messages;
  8. using Renci.SshNet.Common;
  9. using System.Diagnostics;
  10. using Renci.SshNet.Security.Cryptography;
  11. namespace Renci.SshNet.Security
  12. {
  13. /// <summary>
  14. /// Represents "diffie-hellman-group-exchange-sha256" algorithm implementation.
  15. /// </summary>
  16. public class KeyExchangeDiffieHellmanGroupExchangeSha256 : KeyExchangeDiffieHellman
  17. {
  18. /// <summary>
  19. /// Gets algorithm name.
  20. /// </summary>
  21. public override string Name
  22. {
  23. get { return "diffie-hellman-group-exchange-sha256"; }
  24. }
  25. /// <summary>
  26. /// Starts key exchange algorithm
  27. /// </summary>
  28. /// <param name="session">The session.</param>
  29. /// <param name="message">Key exchange init message.</param>
  30. public override void Start(Session session, KeyExchangeInitMessage message)
  31. {
  32. base.Start(session, message);
  33. this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
  34. this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
  35. this.Session.MessageReceived += Session_MessageReceived;
  36. // 1. send SSH_MSG_KEY_DH_GEX_REQUEST
  37. this.SendMessage(new KeyExchangeDhGroupExchangeRequest(1024,1024,1024));
  38. }
  39. /// <summary>
  40. /// Finishes key exchange algorithm.
  41. /// </summary>
  42. public override void Finish()
  43. {
  44. base.Finish();
  45. this.Session.MessageReceived -= Session_MessageReceived;
  46. }
  47. /// <summary>
  48. /// Calculates key exchange hash value.
  49. /// </summary>
  50. /// <returns>
  51. /// Key exchange hash.
  52. /// </returns>
  53. protected override byte[] CalculateHash()
  54. {
  55. var hashData = new _ExchangeHashData
  56. {
  57. ClientVersion = this.Session.ClientVersion,
  58. ServerVersion = this.Session.ServerVersion,
  59. ClientPayload = this._clientPayload,
  60. ServerPayload = this._serverPayload,
  61. HostKey = this._hostKey,
  62. MinimumGroupSize = 1024,
  63. PreferredGroupSize = 1024,
  64. MaximumGroupSize = 1024,
  65. Prime = this._prime,
  66. SubGroup = this._group,
  67. ClientExchangeValue = this._clientExchangeValue,
  68. ServerExchangeValue = this._serverExchangeValue,
  69. SharedKey = this.SharedKey,
  70. }.GetBytes();
  71. return this.Hash(hashData);
  72. }
  73. /// <summary>
  74. /// Hashes the specified data bytes.
  75. /// </summary>
  76. /// <param name="hashBytes">Data to hash.</param>
  77. /// <returns>
  78. /// Hashed bytes
  79. /// </returns>
  80. protected override byte[] Hash(byte[] hashBytes)
  81. {
  82. using (var md = new SHA256Hash())
  83. {
  84. return md.ComputeHash(hashBytes);
  85. }
  86. }
  87. private void Session_MessageReceived(object sender, MessageEventArgs<Message> e)
  88. {
  89. var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup;
  90. if (groupMessage != null)
  91. {
  92. // Unregister message once received
  93. this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
  94. // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP
  95. this._prime = groupMessage.SafePrime;
  96. this._group = groupMessage.SubGroup;
  97. this.PopulateClientExchangeValue();
  98. // 3. Send SSH_MSG_KEX_DH_GEX_INIT
  99. this.SendMessage(new KeyExchangeDhGroupExchangeInit(this._clientExchangeValue));
  100. }
  101. var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply;
  102. if (replyMessage != null)
  103. {
  104. // Unregister message once received
  105. this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
  106. this.HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
  107. // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
  108. this.Finish();
  109. }
  110. }
  111. private class _ExchangeHashData : SshData
  112. {
  113. public string ServerVersion { get; set; }
  114. public string ClientVersion { get; set; }
  115. public byte[] ClientPayload { get; set; }
  116. public byte[] ServerPayload { get; set; }
  117. public byte[] HostKey { get; set; }
  118. public UInt32 MinimumGroupSize { get; set; }
  119. public UInt32 PreferredGroupSize { get; set; }
  120. public UInt32 MaximumGroupSize { get; set; }
  121. public BigInteger Prime { get; set; }
  122. public BigInteger SubGroup { get; set; }
  123. public BigInteger ClientExchangeValue { get; set; }
  124. public BigInteger ServerExchangeValue { get; set; }
  125. public BigInteger SharedKey { get; set; }
  126. protected override void LoadData()
  127. {
  128. throw new System.NotImplementedException();
  129. }
  130. protected override void SaveData()
  131. {
  132. this.Write(this.ClientVersion);
  133. this.Write(this.ServerVersion);
  134. this.WriteBinaryString(this.ClientPayload);
  135. this.WriteBinaryString(this.ServerPayload);
  136. this.WriteBinaryString(this.HostKey);
  137. this.Write(this.MinimumGroupSize);
  138. this.Write(this.PreferredGroupSize);
  139. this.Write(this.MaximumGroupSize);
  140. this.Write(this.Prime);
  141. this.Write(this.SubGroup);
  142. this.Write(this.ClientExchangeValue);
  143. this.Write(this.ServerExchangeValue);
  144. this.Write(this.SharedKey);
  145. }
  146. }
  147. }
  148. }