Skip to content

Commit b58a11c

Browse files
committed
KEX with Elliptic Curve curve25519
Add Kex Algos curve25519-sha256(@libssh.org)
1 parent 4654519 commit b58a11c

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

src/Renci.SshNet/ConnectionInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
322322

323323
KeyExchangeAlgorithms = new Dictionary<string, Type>
324324
{
325+
{"curve25519-sha256", typeof(KeyExchangeECCurve25519)},
326+
{"[email protected]", typeof(KeyExchangeECCurve25519)},
325327
{"ecdh-sha2-nistp256", typeof(KeyExchangeECDH256)},
326328
{"ecdh-sha2-nistp384", typeof(KeyExchangeECDH384)},
327329
{"ecdh-sha2-nistp521", typeof(KeyExchangeECDH521)},

src/Renci.SshNet/Renci.SshNet.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@
310310
<Compile Include="Security\IKeyExchange.cs" />
311311
<Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs" />
312312
<Compile Include="Security\KeyExchangeEC.cs" />
313+
<Compile Include="Security\KeyExchangeECCurve25519.cs" />
313314
<Compile Include="Security\KeyExchangeECDH.cs" />
314315
<Compile Include="Security\KeyExchangeECDH521.cs" />
315316
<Compile Include="Security\KeyExchangeECDH384.cs" />
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using Renci.SshNet.Common;
3+
using Renci.SshNet.Messages.Transport;
4+
using Renci.SshNet.Security.Chaos.NaCl;
5+
using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;
6+
7+
namespace Renci.SshNet.Security
8+
{
9+
internal class KeyExchangeECCurve25519 : KeyExchangeEC
10+
{
11+
private byte[] _privateKey;
12+
13+
/// <summary>
14+
/// Gets algorithm name.
15+
/// </summary>
16+
public override string Name
17+
{
18+
get { return "curve25519-sha256"; }
19+
}
20+
21+
/// <summary>
22+
/// Gets the size, in bits, of the computed hash code.
23+
/// </summary>
24+
/// <value>
25+
/// The size, in bits, of the computed hash code.
26+
/// </value>
27+
protected override int HashSize
28+
{
29+
get { return 256; }
30+
}
31+
32+
/// <summary>
33+
/// Starts key exchange algorithm
34+
/// </summary>
35+
/// <param name="session">The session.</param>
36+
/// <param name="message">Key exchange init message.</param>
37+
public override void Start(Session session, KeyExchangeInitMessage message)
38+
{
39+
base.Start(session, message);
40+
41+
Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
42+
43+
Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;
44+
45+
var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
46+
basepoint[0] = 9;
47+
48+
var rnd = new Random();
49+
_privateKey = new byte[MontgomeryCurve25519.PrivateKeySizeInBytes];
50+
rnd.NextBytes(_privateKey);
51+
52+
_clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
53+
MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);
54+
55+
SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
56+
}
57+
58+
/// <summary>
59+
/// Finishes key exchange algorithm.
60+
/// </summary>
61+
public override void Finish()
62+
{
63+
base.Finish();
64+
65+
Session.KeyExchangeEcdhReplyMessageReceived -= Session_KeyExchangeEcdhReplyMessageReceived;
66+
}
67+
68+
private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMessage> e)
69+
{
70+
var message = e.Message;
71+
72+
// Unregister message once received
73+
Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
74+
75+
HandleServerEcdhReply(message.KS, message.QS, message.Signature);
76+
77+
// When SSH_MSG_KEXDH_REPLY received key exchange is completed
78+
Finish();
79+
}
80+
81+
/// <summary>
82+
/// Handles the server DH reply message.
83+
/// </summary>
84+
/// <param name="hostKey">The host key.</param>
85+
/// <param name="serverExchangeValue">The server exchange value.</param>
86+
/// <param name="signature">The signature.</param>
87+
protected override void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, byte[] signature)
88+
{
89+
_serverExchangeValue = serverExchangeValue;
90+
_hostKey = hostKey;
91+
_serverExchangeValue = serverExchangeValue;
92+
_signature = signature;
93+
94+
var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
95+
MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);
96+
SharedKey = sharedKey.ToBigInteger2();
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)