Skip to content
Permalink
bc99ada7da
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
114 lines (95 sloc) 3.84 KB
using System;
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 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; }
}
/// <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);
Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;
var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
basepoint[0] = 9;
var rnd = new Random();
_privateKey = new byte[MontgomeryCurve25519.PrivateKeySizeInBytes];
rnd.NextBytes(_privateKey);
_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>
/// Hashed bytes
/// </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();
}
}
}