2
2
using Renci . SshNet . Common ;
3
3
using Renci . SshNet . Messages . Transport ;
4
4
5
- using Renci . SshNet . Security . Org . BouncyCastle . Asn1 . X9 ;
5
+ using Renci . SshNet . Security . Org . BouncyCastle . Asn1 . Sec ;
6
6
using Renci . SshNet . Security . Org . BouncyCastle . Crypto . Agreement ;
7
7
using Renci . SshNet . Security . Org . BouncyCastle . Crypto . Generators ;
8
8
using Renci . SshNet . Security . Org . BouncyCastle . Crypto . Parameters ;
@@ -13,13 +13,17 @@ namespace Renci.SshNet.Security
13
13
{
14
14
internal abstract class KeyExchangeECDH : KeyExchangeEC
15
15
{
16
+ #if NET8_0_OR_GREATER
17
+ private System . Security . Cryptography . ECDiffieHellman _clientECDH ;
18
+ #endif
19
+
16
20
/// <summary>
17
- /// Gets the parameter of the curve.
21
+ /// Gets the name of the curve.
18
22
/// </summary>
19
23
/// <value>
20
- /// The parameter of the curve.
24
+ /// The name of the curve.
21
25
/// </value>
22
- protected abstract X9ECParameters CurveParameter { get ; }
26
+ protected abstract string CurveName { get ; }
23
27
24
28
private ECDHCBasicAgreement _keyAgreement ;
25
29
private ECDomainParameters _domainParameters ;
@@ -33,11 +37,30 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool
33
37
34
38
Session . KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived ;
35
39
36
- _domainParameters = new ECDomainParameters ( CurveParameter . Curve ,
37
- CurveParameter . G ,
38
- CurveParameter . N ,
39
- CurveParameter . H ,
40
- CurveParameter . GetSeed ( ) ) ;
40
+ #if NET8_0_OR_GREATER
41
+ if ( IsNonWindowsOrWindowsVersionAtLeast ( 10 ) )
42
+ {
43
+ _clientECDH = System . Security . Cryptography . ECDiffieHellman . Create ( ) ;
44
+ _clientECDH . GenerateKey ( System . Security . Cryptography . ECCurve . CreateFromFriendlyName ( CurveName ) ) ;
45
+
46
+ var q = _clientECDH . PublicKey . ExportParameters ( ) . Q ;
47
+
48
+ _clientExchangeValue = new byte [ 1 + q . X . Length + q . Y . Length ] ;
49
+ _clientExchangeValue [ 0 ] = 0x04 ;
50
+ Buffer . BlockCopy ( q . X , 0 , _clientExchangeValue , 1 , q . X . Length ) ;
51
+ Buffer . BlockCopy ( q . Y , 0 , _clientExchangeValue , q . X . Length + 1 , q . Y . Length ) ;
52
+
53
+ SendMessage ( new KeyExchangeEcdhInitMessage ( _clientExchangeValue ) ) ;
54
+
55
+ return ;
56
+ }
57
+ #endif
58
+ var curveParameter = SecNamedCurves . GetByName ( CurveName ) ;
59
+ _domainParameters = new ECDomainParameters ( curveParameter . Curve ,
60
+ curveParameter . G ,
61
+ curveParameter . N ,
62
+ curveParameter . H ,
63
+ curveParameter . GetSeed ( ) ) ;
41
64
42
65
var g = new ECKeyPairGenerator ( ) ;
43
66
g . Init ( new ECKeyGenerationParameters ( _domainParameters , new SecureRandom ( ) ) ) ;
@@ -46,7 +69,6 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool
46
69
_keyAgreement = new ECDHCBasicAgreement ( ) ;
47
70
_keyAgreement . Init ( aKeyPair . Private ) ;
48
71
_clientExchangeValue = ( ( ECPublicKeyParameters ) aKeyPair . Public ) . Q . GetEncoded ( ) ;
49
-
50
72
SendMessage ( new KeyExchangeEcdhInitMessage ( _clientExchangeValue ) ) ;
51
73
}
52
74
@@ -91,12 +113,49 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b
91
113
var y = new byte [ cordSize ] ;
92
114
Buffer . BlockCopy ( serverExchangeValue , cordSize + 1 , y , 0 , y . Length ) ;
93
115
116
+ #if NET8_0_OR_GREATER
117
+ if ( IsNonWindowsOrWindowsVersionAtLeast ( 10 ) )
118
+ {
119
+ using var serverECDH = System . Security . Cryptography . ECDiffieHellman . Create ( new System . Security . Cryptography . ECParameters
120
+ {
121
+ Curve = System . Security . Cryptography . ECCurve . CreateFromFriendlyName ( CurveName ) ,
122
+ Q =
123
+ {
124
+ X = x ,
125
+ Y = y ,
126
+ } ,
127
+ } ) ;
128
+
129
+ var k = _clientECDH . DeriveRawSecretAgreement ( serverECDH . PublicKey ) ;
130
+ SharedKey = k . ToBigInteger2 ( ) . ToByteArray ( ) . Reverse ( ) ;
131
+
132
+ return ;
133
+ }
134
+ #endif
94
135
var c = ( FpCurve ) _domainParameters . Curve ;
95
136
var q = c . CreatePoint ( new Org . BouncyCastle . Math . BigInteger ( 1 , x ) , new Org . BouncyCastle . Math . BigInteger ( 1 , y ) ) ;
96
137
var publicKey = new ECPublicKeyParameters ( "ECDH" , q , _domainParameters ) ;
97
138
98
139
var k1 = _keyAgreement . CalculateAgreement ( publicKey ) ;
99
140
SharedKey = k1 . ToByteArray ( ) . ToBigInteger2 ( ) . ToByteArray ( ) . Reverse ( ) ;
100
141
}
142
+
143
+ #if NET8_0_OR_GREATER
144
+
145
+ /// <inheritdoc/>
146
+ protected override void Dispose ( bool disposing )
147
+ {
148
+ base . Dispose ( disposing ) ;
149
+ if ( disposing )
150
+ {
151
+ _clientECDH ? . Dispose ( ) ;
152
+ }
153
+ }
154
+
155
+ private static bool IsNonWindowsOrWindowsVersionAtLeast ( int major )
156
+ {
157
+ return Environment . OSVersion . Platform != PlatformID . Win32NT || Environment . OSVersion . Version . Major >= major ;
158
+ }
159
+ #endif
101
160
}
102
161
}
0 commit comments