2
0

KeyExchangeECCurve25519.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using Renci.SshNet.Abstractions;
  2. using Renci.SshNet.Common;
  3. using Renci.SshNet.Messages.Transport;
  4. using Renci.SshNet.Security.Chaos.NaCl;
  5. using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;
  6. namespace Renci.SshNet.Security
  7. {
  8. internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC
  9. {
  10. private byte[] _privateKey;
  11. /// <summary>
  12. /// Gets algorithm name.
  13. /// </summary>
  14. public override string Name
  15. {
  16. get { return "curve25519-sha256"; }
  17. }
  18. /// <summary>
  19. /// Gets the size, in bits, of the computed hash code.
  20. /// </summary>
  21. /// <value>
  22. /// The size, in bits, of the computed hash code.
  23. /// </value>
  24. protected override int HashSize
  25. {
  26. get { return 256; }
  27. }
  28. /// <inheritdoc/>
  29. public override void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage)
  30. {
  31. base.Start(session, message, sendClientInitMessage);
  32. Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
  33. Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;
  34. var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
  35. basepoint[0] = 9;
  36. _privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes);
  37. _clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
  38. MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);
  39. SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
  40. }
  41. /// <summary>
  42. /// Finishes key exchange algorithm.
  43. /// </summary>
  44. public override void Finish()
  45. {
  46. base.Finish();
  47. Session.KeyExchangeEcdhReplyMessageReceived -= Session_KeyExchangeEcdhReplyMessageReceived;
  48. }
  49. /// <summary>
  50. /// Hashes the specified data bytes.
  51. /// </summary>
  52. /// <param name="hashData">The hash data.</param>
  53. /// <returns>
  54. /// The hash of the data.
  55. /// </returns>
  56. protected override byte[] Hash(byte[] hashData)
  57. {
  58. using (var sha256 = CryptoAbstraction.CreateSHA256())
  59. {
  60. return sha256.ComputeHash(hashData, 0, hashData.Length);
  61. }
  62. }
  63. private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMessage> e)
  64. {
  65. var message = e.Message;
  66. // Unregister message once received
  67. Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
  68. HandleServerEcdhReply(message.KS, message.QS, message.Signature);
  69. // When SSH_MSG_KEXDH_REPLY received key exchange is completed
  70. Finish();
  71. }
  72. /// <summary>
  73. /// Handles the server DH reply message.
  74. /// </summary>
  75. /// <param name="hostKey">The host key.</param>
  76. /// <param name="serverExchangeValue">The server exchange value.</param>
  77. /// <param name="signature">The signature.</param>
  78. private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, byte[] signature)
  79. {
  80. _serverExchangeValue = serverExchangeValue;
  81. _hostKey = hostKey;
  82. _signature = signature;
  83. var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
  84. MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);
  85. SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse();
  86. }
  87. }
  88. }