Skip to content

Commit 71e2909

Browse files
Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl (#1447)
* Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl * Abstract SecureRandom --------- Co-authored-by: Wojciech Nagórski <[email protected]>
1 parent 4cc1278 commit 71e2909

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

src/Renci.SshNet/Abstractions/CryptoAbstraction.cs

+5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
using System.Security.Cryptography;
22

3+
using Org.BouncyCastle.Crypto.Prng;
4+
using Org.BouncyCastle.Security;
5+
36
namespace Renci.SshNet.Abstractions
47
{
58
internal static class CryptoAbstraction
69
{
710
private static readonly RandomNumberGenerator Randomizer = RandomNumberGenerator.Create();
811

12+
internal static readonly SecureRandom SecureRandom = new SecureRandom(new CryptoApiRandomGenerator(Randomizer));
13+
914
/// <summary>
1015
/// Generates a <see cref="byte"/> array of the specified length, and fills it with a
1116
/// cryptographically strong random sequence of values.

src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
using Renci.SshNet.Abstractions;
1+
using System;
2+
3+
using Org.BouncyCastle.Crypto.Agreement;
4+
using Org.BouncyCastle.Crypto.Generators;
5+
using Org.BouncyCastle.Crypto.Parameters;
6+
7+
using Renci.SshNet.Abstractions;
28
using Renci.SshNet.Common;
39
using Renci.SshNet.Messages.Transport;
4-
using Renci.SshNet.Security.Chaos.NaCl;
5-
using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;
610

711
namespace Renci.SshNet.Security
812
{
913
internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC
1014
{
11-
private byte[] _privateKey;
15+
private X25519Agreement _keyAgreement;
1216

1317
/// <summary>
1418
/// Gets algorithm name.
@@ -38,13 +42,13 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool
3842

3943
Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;
4044

41-
var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
42-
basepoint[0] = 9;
45+
var g = new X25519KeyPairGenerator();
46+
g.Init(new X25519KeyGenerationParameters(CryptoAbstraction.SecureRandom));
4347

44-
_privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes);
45-
46-
_clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
47-
MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);
48+
var aKeyPair = g.GenerateKeyPair();
49+
_keyAgreement = new X25519Agreement();
50+
_keyAgreement.Init(aKeyPair.Private);
51+
_clientExchangeValue = ((X25519PublicKeyParameters)aKeyPair.Public).GetEncoded();
4852

4953
SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
5054
}
@@ -96,9 +100,11 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b
96100
_hostKey = hostKey;
97101
_signature = signature;
98102

99-
var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
100-
MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);
101-
SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse();
103+
var publicKey = new X25519PublicKeyParameters(serverExchangeValue);
104+
105+
var k1 = new byte[_keyAgreement.AgreementSize];
106+
_keyAgreement.CalculateAgreement(publicKey, k1, 0);
107+
SharedKey = k1.ToBigInteger2().ToByteArray().Reverse();
102108
}
103109
}
104110
}

src/Renci.SshNet/Security/KeyExchangeECDH.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using Org.BouncyCastle.Crypto.Generators;
66
using Org.BouncyCastle.Crypto.Parameters;
77
using Org.BouncyCastle.Math.EC;
8-
using Org.BouncyCastle.Security;
98

9+
using Renci.SshNet.Abstractions;
1010
using Renci.SshNet.Common;
1111
using Renci.SshNet.Messages.Transport;
1212

@@ -41,7 +41,7 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool
4141
CurveParameter.GetSeed());
4242

4343
var g = new ECKeyPairGenerator();
44-
g.Init(new ECKeyGenerationParameters(_domainParameters, new SecureRandom()));
44+
g.Init(new ECKeyGenerationParameters(_domainParameters, CryptoAbstraction.SecureRandom));
4545

4646
var aKeyPair = g.GenerateKeyPair();
4747
_keyAgreement = new ECDHCBasicAgreement();

0 commit comments

Comments
 (0)