Skip to content

Commit dab8a11

Browse files
authored
Use BouncyCastle for Diffie-Hellman key exchange (#1654)
Removes another vestige of hand-rolled crypto, and makes the classes public + configurable for if/when we remove certain algorithms.
1 parent b7c5f1a commit dab8a11

25 files changed

+496
-1009
lines changed

src/Renci.SshNet/ConnectionInfo.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
using Microsoft.Extensions.Logging;
99

10+
using Org.BouncyCastle.Crypto.Agreement;
11+
1012
using Renci.SshNet.Common;
1113
using Renci.SshNet.Compression;
1214
using Renci.SshNet.Messages.Authentication;
@@ -357,12 +359,13 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
357359
{ "ecdh-sha2-nistp256", () => new KeyExchangeECDH256() },
358360
{ "ecdh-sha2-nistp384", () => new KeyExchangeECDH384() },
359361
{ "ecdh-sha2-nistp521", () => new KeyExchangeECDH521() },
360-
{ "diffie-hellman-group-exchange-sha256", () => new KeyExchangeDiffieHellmanGroupExchangeSha256() },
361-
{ "diffie-hellman-group-exchange-sha1", () => new KeyExchangeDiffieHellmanGroupExchangeSha1() },
362-
{ "diffie-hellman-group16-sha512", () => new KeyExchangeDiffieHellmanGroup16Sha512() },
363-
{ "diffie-hellman-group14-sha256", () => new KeyExchangeDiffieHellmanGroup14Sha256() },
364-
{ "diffie-hellman-group14-sha1", () => new KeyExchangeDiffieHellmanGroup14Sha1() },
365-
{ "diffie-hellman-group1-sha1", () => new KeyExchangeDiffieHellmanGroup1Sha1() },
362+
{ "diffie-hellman-group-exchange-sha256", () => new KeyExchangeDiffieHellmanGroupExchange("diffie-hellman-group-exchange-sha256", HashAlgorithmName.SHA256) },
363+
{ "diffie-hellman-group16-sha512", () => new KeyExchangeDiffieHellman("diffie-hellman-group16-sha512", DHStandardGroups.rfc3526_4096, HashAlgorithmName.SHA512) },
364+
{ "diffie-hellman-group18-sha512", () => new KeyExchangeDiffieHellman("diffie-hellman-group18-sha512", DHStandardGroups.rfc3526_8192, HashAlgorithmName.SHA512) },
365+
{ "diffie-hellman-group14-sha256", () => new KeyExchangeDiffieHellman("diffie-hellman-group14-sha256", DHStandardGroups.rfc3526_2048, HashAlgorithmName.SHA256) },
366+
{ "diffie-hellman-group-exchange-sha1", () => new KeyExchangeDiffieHellmanGroupExchange("diffie-hellman-group-exchange-sha1", HashAlgorithmName.SHA1) },
367+
{ "diffie-hellman-group14-sha1", () => new KeyExchangeDiffieHellman("diffie-hellman-group14-sha1", DHStandardGroups.rfc3526_2048, HashAlgorithmName.SHA1) },
368+
{ "diffie-hellman-group1-sha1", () => new KeyExchangeDiffieHellman("diffie-hellman-group1-sha1", DHStandardGroups.rfc2409_1024, HashAlgorithmName.SHA1) },
366369
};
367370

368371
Encryptions = new OrderedDictionary<string, CipherInfo>

src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ namespace Renci.SshNet.Messages.Transport
99
/// </summary>
1010
public class KeyExchangeDhGroupExchangeGroup : Message
1111
{
12-
private byte[] _safePrime;
13-
private byte[] _subGroup;
12+
internal byte[] SafePrimeBytes { get; private set; }
13+
internal byte[] SubGroupBytes { get; private set; }
1414

1515
/// <inheritdoc />
1616
public override string MessageName
@@ -38,7 +38,7 @@ public override byte MessageNumber
3838
/// </value>
3939
public BigInteger SafePrime
4040
{
41-
get { return _safePrime.ToBigInteger(); }
41+
get { return SafePrimeBytes.ToBigInteger(); }
4242
}
4343

4444
/// <summary>
@@ -49,7 +49,7 @@ public BigInteger SafePrime
4949
/// </value>
5050
public BigInteger SubGroup
5151
{
52-
get { return _subGroup.ToBigInteger(); }
52+
get { return SubGroupBytes.ToBigInteger(); }
5353
}
5454

5555
/// <summary>
@@ -64,9 +64,9 @@ protected override int BufferCapacity
6464
{
6565
var capacity = base.BufferCapacity;
6666
capacity += 4; // SafePrime length
67-
capacity += _safePrime.Length; // SafePrime
67+
capacity += SafePrimeBytes.Length; // SafePrime
6868
capacity += 4; // SubGroup length
69-
capacity += _subGroup.Length; // SubGroup
69+
capacity += SubGroupBytes.Length; // SubGroup
7070

7171
return capacity;
7272
}
@@ -77,17 +77,17 @@ protected override int BufferCapacity
7777
/// </summary>
7878
protected override void LoadData()
7979
{
80-
_safePrime = ReadBinary();
81-
_subGroup = ReadBinary();
80+
SafePrimeBytes = ReadBinary();
81+
SubGroupBytes = ReadBinary();
8282
}
8383

8484
/// <summary>
8585
/// Called when type specific data need to be saved.
8686
/// </summary>
8787
protected override void SaveData()
8888
{
89-
WriteBinaryString(_safePrime);
90-
WriteBinaryString(_subGroup);
89+
WriteBinaryString(SafePrimeBytes);
90+
WriteBinaryString(SubGroupBytes);
9191
}
9292

9393
internal override void Process(Session session)

src/Renci.SshNet/Security/GroupExchangeHashData.cs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Numerics;
32

43
using Renci.SshNet.Common;
54

@@ -9,8 +8,6 @@ internal sealed class GroupExchangeHashData : SshData
98
{
109
private byte[] _serverVersion;
1110
private byte[] _clientVersion;
12-
private byte[] _prime;
13-
private byte[] _subGroup;
1411

1512
public string ServerVersion
1613
{
@@ -36,17 +33,9 @@ public string ClientVersion
3633

3734
public uint MaximumGroupSize { get; set; }
3835

39-
public BigInteger Prime
40-
{
41-
private get { return _prime.ToBigInteger(); }
42-
set { _prime = value.ToByteArray(isBigEndian: true); }
43-
}
36+
public byte[] Prime { get; set; }
4437

45-
public BigInteger SubGroup
46-
{
47-
private get { return _subGroup.ToBigInteger(); }
48-
set { _subGroup = value.ToByteArray(isBigEndian: true); }
49-
}
38+
public byte[] SubGroup { get; set; }
5039

5140
public byte[] ClientExchangeValue { get; set; }
5241

@@ -79,9 +68,9 @@ protected override int BufferCapacity
7968
capacity += 4; // PreferredGroupSize
8069
capacity += 4; // MaximumGroupSize
8170
capacity += 4; // Prime length
82-
capacity += _prime.Length; // Prime
71+
capacity += Prime.Length; // Prime
8372
capacity += 4; // SubGroup length
84-
capacity += _subGroup.Length; // SubGroup
73+
capacity += SubGroup.Length; // SubGroup
8574
capacity += 4; // ClientExchangeValue length
8675
capacity += ClientExchangeValue.Length; // ClientExchangeValue
8776
capacity += 4; // ServerExchangeValue length
@@ -107,8 +96,8 @@ protected override void SaveData()
10796
Write(MinimumGroupSize);
10897
Write(PreferredGroupSize);
10998
Write(MaximumGroupSize);
110-
WriteBinaryString(_prime);
111-
WriteBinaryString(_subGroup);
99+
WriteBinaryString(Prime);
100+
WriteBinaryString(SubGroup);
112101
WriteBinaryString(ClientExchangeValue);
113102
WriteBinaryString(ServerExchangeValue);
114103
WriteBinaryString(SharedKey);

src/Renci.SshNet/Security/KeyExchange.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ protected bool CanTrustHostKey(KeyHostAlgorithm host)
482482
/// <summary>
483483
/// Validates the exchange hash.
484484
/// </summary>
485-
/// <returns>true if exchange hash is valid; otherwise false.</returns>
485+
/// <returns><see langword="true"/> if exchange hash is valid; otherwise <see langword="false"/>.</returns>
486486
protected abstract bool ValidateExchangeHash();
487487

488488
private protected bool ValidateExchangeHash(byte[] encodedKey, byte[] encodedSignature)

0 commit comments

Comments
 (0)