You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.0 KiB
C#
131 lines
4.0 KiB
C#
using System;
|
|
using System.Text;
|
|
using Renci.SshNet.Messages.Transport;
|
|
using Renci.SshNet.Common;
|
|
|
|
namespace Renci.SshNet.Security
|
|
{
|
|
/// <summary>
|
|
/// Represents base class for Diffie Hellman key exchange algorithm
|
|
/// </summary>
|
|
public abstract class KeyExchangeDiffieHellman : KeyExchange
|
|
{
|
|
/// <summary>
|
|
/// Specifies key exchange group number.
|
|
/// </summary>
|
|
protected BigInteger _group;
|
|
|
|
/// <summary>
|
|
/// Specifies key exchange prime number.
|
|
/// </summary>
|
|
protected BigInteger _prime;
|
|
|
|
/// <summary>
|
|
/// Specifies client payload
|
|
/// </summary>
|
|
protected byte[] _clientPayload;
|
|
|
|
/// <summary>
|
|
/// Specifies server payload
|
|
/// </summary>
|
|
protected byte[] _serverPayload;
|
|
|
|
/// <summary>
|
|
/// Specifies client exchange number.
|
|
/// </summary>
|
|
protected BigInteger _clientExchangeValue;
|
|
|
|
/// <summary>
|
|
/// Specifies server exchange number.
|
|
/// </summary>
|
|
protected BigInteger _serverExchangeValue;
|
|
|
|
/// <summary>
|
|
/// Specifies random generated number.
|
|
/// </summary>
|
|
protected BigInteger _randomValue;
|
|
|
|
/// <summary>
|
|
/// Specifies host key data.
|
|
/// </summary>
|
|
protected byte[] _hostKey;
|
|
|
|
/// <summary>
|
|
/// Specifies signature data.
|
|
/// </summary>
|
|
protected byte[] _signature;
|
|
|
|
/// <summary>
|
|
/// Validates the exchange hash.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// true if exchange hash is valid; otherwise false.
|
|
/// </returns>
|
|
protected override bool ValidateExchangeHash()
|
|
{
|
|
var exchangeHash = CalculateHash();
|
|
|
|
var length = Pack.BigEndianToUInt32(_hostKey);
|
|
var algorithmName = Encoding.UTF8.GetString(_hostKey, 4, (int)length);
|
|
var key = Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](_hostKey);
|
|
|
|
Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName;
|
|
|
|
if (CanTrustHostKey(key))
|
|
{
|
|
return key.VerifySignature(exchangeHash, _signature);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts key exchange algorithm
|
|
/// </summary>
|
|
/// <param name="session">The session.</param>
|
|
/// <param name="message">Key exchange init message.</param>
|
|
public override void Start(Session session, KeyExchangeInitMessage message)
|
|
{
|
|
base.Start(session, message);
|
|
|
|
_serverPayload = message.GetBytes();
|
|
_clientPayload = Session.ClientInitMessage.GetBytes();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populates the client exchange value.
|
|
/// </summary>
|
|
protected void PopulateClientExchangeValue()
|
|
{
|
|
if (_group.IsZero)
|
|
throw new ArgumentNullException("_group");
|
|
|
|
if (_prime.IsZero)
|
|
throw new ArgumentNullException("_prime");
|
|
|
|
var bitLength = _prime.BitLength;
|
|
|
|
do
|
|
{
|
|
_randomValue = BigInteger.Random(bitLength);
|
|
|
|
_clientExchangeValue = BigInteger.ModPow(_group, _randomValue, _prime);
|
|
|
|
} while (_clientExchangeValue < 1 || _clientExchangeValue > (_prime - 1));
|
|
}
|
|
|
|
/// <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>
|
|
protected virtual void HandleServerDhReply(byte[] hostKey, BigInteger serverExchangeValue, byte[] signature)
|
|
{
|
|
_serverExchangeValue = serverExchangeValue;
|
|
_hostKey = hostKey;
|
|
SharedKey = BigInteger.ModPow(serverExchangeValue, _randomValue, _prime);
|
|
_signature = signature;
|
|
}
|
|
}
|
|
}
|