forked from sshnet/SSH.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKeyExchangeECDH.cs
More file actions
108 lines (87 loc) · 3.22 KB
/
KeyExchangeECDH.cs
File metadata and controls
108 lines (87 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using Org.BouncyCastle.Asn1.X9;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
namespace Renci.SshNet.Security
{
internal abstract partial class KeyExchangeECDH : KeyExchangeEC
{
#if NET
private Impl _impl;
/// <summary>
/// Gets the curve.
/// </summary>
/// <value>
/// The curve.
/// </value>
protected abstract System.Security.Cryptography.ECCurve Curve { get; }
#else
private BouncyCastleImpl _impl;
#endif
/// <summary>
/// Gets the parameter of the curve.
/// </summary>
/// <value>
/// The parameter of the curve.
/// </value>
protected abstract X9ECParameters CurveParameter { get; }
/// <inheritdoc/>
public override void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage)
{
base.Start(session, message, sendClientInitMessage);
Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY");
Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;
#if NET
if (!System.OperatingSystem.IsWindows() || System.OperatingSystem.IsWindowsVersionAtLeast(10))
{
_impl = new BclImpl(Curve);
}
else
#endif
{
_impl = new BouncyCastleImpl(CurveParameter);
}
_clientExchangeValue = _impl.GenerateClientPublicKey();
SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
}
/// <summary>
/// Finishes key exchange algorithm.
/// </summary>
public override void Finish()
{
base.Finish();
Session.KeyExchangeEcdhReplyMessageReceived -= Session_KeyExchangeEcdhReplyMessageReceived;
}
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_KEX_ECDH_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 agreement = _impl.CalculateAgreement(serverExchangeValue);
SharedKey = agreement.ToBigInteger2().ToByteArray(isBigEndian: true);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_impl?.Dispose();
}
}
}
}