<PackageReference Include="SSH.NET" Version="2025.1.0" />

KeyExchangeDiffieHellman

Provides the implementation of "diffie-hellman-groupN" algorithms.
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Agreement; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; using System; using System.Runtime.CompilerServices; using System.Security.Cryptography; namespace Renci.SshNet.Security { [NullableContext(1)] [Nullable(0)] public class KeyExchangeDiffieHellman : KeyExchange { [Nullable(2)] private byte[] _clientPayload; [Nullable(2)] private byte[] _serverPayload; [Nullable(2)] private byte[] _clientExchangeValue; [Nullable(2)] private byte[] _serverExchangeValue; [Nullable(2)] private byte[] _hostKey; [Nullable(2)] private byte[] _signature; private readonly DHParameters _dhParameters; private readonly IncrementalHash _hash; [Nullable(2)] private DHBasicAgreement _keyAgreement; public override string Name { get; } public KeyExchangeDiffieHellman(string name, DHParameters parameters, HashAlgorithmName hashAlgorithm) { ThrowHelper.ThrowIfNull(name, "name"); ThrowHelper.ThrowIfNull(parameters, "parameters"); ThrowHelper.ThrowIfNullOrEmpty(hashAlgorithm.Name, "hashAlgorithm"); Name = name; _dhParameters = parameters; try { _hash = IncrementalHash.CreateHash(hashAlgorithm); } catch (CryptographicException innerException) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 2); defaultInterpolatedStringHandler.AppendLiteral("Could not create "); defaultInterpolatedStringHandler.AppendFormatted("HashAlgorithm"); defaultInterpolatedStringHandler.AppendLiteral(" from `"); defaultInterpolatedStringHandler.AppendFormatted(hashAlgorithm); defaultInterpolatedStringHandler.AppendLiteral("`."); throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear(), "hashAlgorithm", innerException); } } public override void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage) { base.Start(session, message, sendClientInitMessage); _serverPayload = message.GetBytes(); _clientPayload = base.Session.ClientInitMessage.GetBytes(); DHKeyPairGenerator val = new DHKeyPairGenerator(); val.Init(new DHKeyGenerationParameters(CryptoAbstraction.SecureRandom, _dhParameters)); AsymmetricCipherKeyPair val2 = val.GenerateKeyPair(); _keyAgreement = new DHBasicAgreement(); _keyAgreement.Init(val2.get_Private()); _clientExchangeValue = val2.get_Public().get_Y().ToByteArray(); base.Session.RegisterMessage("SSH_MSG_KEXDH_REPLY"); base.Session.KeyExchangeDhReplyMessageReceived += Session_KeyExchangeDhReplyMessageReceived; SendMessage(new KeyExchangeDhInitMessage(_clientExchangeValue)); } protected override byte[] CalculateHash() { KeyExchangeHashData keyExchangeHashData = new KeyExchangeHashData { ClientVersion = base.Session.ClientVersion, ServerVersion = base.Session.ServerVersion, ClientPayload = _clientPayload, ServerPayload = _serverPayload, HostKey = _hostKey, ClientExchangeValue = _clientExchangeValue, ServerExchangeValue = _serverExchangeValue, SharedKey = base.SharedKey }; return Hash(keyExchangeHashData.GetBytes()); } private void Session_KeyExchangeDhReplyMessageReceived([Nullable(2)] object sender, MessageEventArgs<KeyExchangeDhReplyMessage> e) { KeyExchangeDhReplyMessage message = e.Message; base.Session.KeyExchangeDhReplyMessageReceived -= Session_KeyExchangeDhReplyMessageReceived; base.Session.UnRegisterMessage("SSH_MSG_KEXDH_REPLY"); _serverExchangeValue = message.F; _hostKey = message.HostKey; _signature = message.Signature; DHPublicKeyParameters val = new DHPublicKeyParameters(new BigInteger(message.F), _dhParameters); base.SharedKey = _keyAgreement.CalculateAgreement(val).ToByteArray(); Finish(); } protected override bool ValidateExchangeHash() { return ValidateExchangeHash(_hostKey, _signature); } protected override byte[] Hash(byte[] hashData) { _hash.AppendData(hashData); return _hash.GetHashAndReset(); } protected override void Dispose(bool disposing) { if (disposing) _hash.Dispose(); base.Dispose(disposing); } } }