| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 | using Renci.SshNet.Abstractions;using Renci.SshNet.Common;using Renci.SshNet.Messages.Transport;using Renci.SshNet.Security.Chaos.NaCl;using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;namespace Renci.SshNet.Security{    internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC    {        private byte[] _privateKey;        /// <summary>        /// Gets algorithm name.        /// </summary>        public override string Name        {            get { return "curve25519-sha256"; }        }        /// <summary>        /// Gets the size, in bits, of the computed hash code.        /// </summary>        /// <value>        /// The size, in bits, of the computed hash code.        /// </value>        protected override int HashSize        {            get { return 256; }        }        /// <inheritdoc/>        public override void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage)        {            base.Start(session, message, sendClientInitMessage);            Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");            Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;            var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];            basepoint[0] = 9;            _privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes);            _clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];            MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);            SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));        }        /// <summary>        /// Finishes key exchange algorithm.        /// </summary>        public override void Finish()        {            base.Finish();            Session.KeyExchangeEcdhReplyMessageReceived -= Session_KeyExchangeEcdhReplyMessageReceived;        }        /// <summary>        /// Hashes the specified data bytes.        /// </summary>        /// <param name="hashData">The hash data.</param>        /// <returns>        /// The hash of the data.        /// </returns>        protected override byte[] Hash(byte[] hashData)        {            using (var sha256 = CryptoAbstraction.CreateSHA256())            {                return sha256.ComputeHash(hashData, 0, hashData.Length);            }        }        private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMessage> e)        {            var message = e.Message;            // Unregister message once received            Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY");            HandleServerEcdhReply(message.KS, message.QS, message.Signature);            // When SSH_MSG_KEXDH_REPLY received key exchange is completed            Finish();        }        /// <summary>        /// Handles the server DH reply message.        /// </summary>        /// <param name="hostKey">The host key.</param>        /// <param name="serverExchangeValue">The server exchange value.</param>        /// <param name="signature">The signature.</param>        private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, byte[] signature)        {            _serverExchangeValue = serverExchangeValue;            _hostKey = hostKey;            _signature = signature;            var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];            MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);            SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse();        }    }}
 |