using System.Text;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
namespace Renci.SshNet.Security
{
internal abstract class KeyExchangeEC : KeyExchange
{
///
/// Specifies client payload
///
protected byte[] _clientPayload;
///
/// Specifies server payload
///
protected byte[] _serverPayload;
///
/// Specifies client exchange.
///
protected byte[] _clientExchangeValue;
///
/// Specifies server exchange.
///
protected byte[] _serverExchangeValue;
///
/// Specifies host key data.
///
protected byte[] _hostKey;
///
/// Specifies signature data.
///
protected byte[] _signature;
///
/// Gets the size, in bits, of the computed hash code.
///
///
/// The size, in bits, of the computed hash code.
///
protected abstract int HashSize { get; }
///
/// Calculates key exchange hash value.
///
///
/// Key exchange hash.
///
protected override byte[] CalculateHash()
{
var hashData = new KeyExchangeHashData
{
ClientVersion = Session.ClientVersion,
ServerVersion = Session.ServerVersion,
ClientPayload = _clientPayload,
ServerPayload = _serverPayload,
HostKey = _hostKey,
ClientExchangeValue = _clientExchangeValue,
ServerExchangeValue = _serverExchangeValue,
SharedKey = SharedKey,
};
return Hash(hashData.GetBytes());
}
///
/// Validates the exchange hash.
///
///
/// true if exchange hash is valid; otherwise false.
///
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;
}
///
/// Starts key exchange algorithm.
///
/// The session.
/// Key exchange init message.
public override void Start(Session session, KeyExchangeInitMessage message)
{
base.Start(session, message);
_serverPayload = message.GetBytes();
_clientPayload = Session.ClientInitMessage.GetBytes();
}
}
}