Skip to content

Commit

Permalink
Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl (#1447
Browse files Browse the repository at this point in the history
)

* Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl

* Abstract SecureRandom

---------

Co-authored-by: Wojciech Nagórski <[email protected]>
  • Loading branch information
scott-xu and WojciechNagorski authored Jul 23, 2024
1 parent 4cc1278 commit 71e2909
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/Renci.SshNet/Abstractions/CryptoAbstraction.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
using System.Security.Cryptography;

using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Security;

namespace Renci.SshNet.Abstractions
{
internal static class CryptoAbstraction
{
private static readonly RandomNumberGenerator Randomizer = RandomNumberGenerator.Create();

internal static readonly SecureRandom SecureRandom = new SecureRandom(new CryptoApiRandomGenerator(Randomizer));

/// <summary>
/// Generates a <see cref="byte"/> array of the specified length, and fills it with a
/// cryptographically strong random sequence of values.
Expand Down
32 changes: 19 additions & 13 deletions src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using Renci.SshNet.Abstractions;
using System;

using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;

using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
using Renci.SshNet.Security.Chaos.NaCl;
using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;

namespace Renci.SshNet.Security
{
internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC
{
private byte[] _privateKey;
private X25519Agreement _keyAgreement;

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

Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;

var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
basepoint[0] = 9;
var g = new X25519KeyPairGenerator();
g.Init(new X25519KeyGenerationParameters(CryptoAbstraction.SecureRandom));

_privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes);

_clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0);
var aKeyPair = g.GenerateKeyPair();
_keyAgreement = new X25519Agreement();
_keyAgreement.Init(aKeyPair.Private);
_clientExchangeValue = ((X25519PublicKeyParameters)aKeyPair.Public).GetEncoded();

SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));
}
Expand Down Expand Up @@ -96,9 +100,11 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b
_hostKey = hostKey;
_signature = signature;

var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes];
MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0);
SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse();
var publicKey = new X25519PublicKeyParameters(serverExchangeValue);

var k1 = new byte[_keyAgreement.AgreementSize];
_keyAgreement.CalculateAgreement(publicKey, k1, 0);
SharedKey = k1.ToBigInteger2().ToByteArray().Reverse();
}
}
}
4 changes: 2 additions & 2 deletions src/Renci.SshNet/Security/KeyExchangeECDH.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;

using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;

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

var g = new ECKeyPairGenerator();
g.Init(new ECKeyGenerationParameters(_domainParameters, new SecureRandom()));
g.Init(new ECKeyGenerationParameters(_domainParameters, CryptoAbstraction.SecureRandom));

var aKeyPair = g.GenerateKeyPair();
_keyAgreement = new ECDHCBasicAgreement();
Expand Down

0 comments on commit 71e2909

Please sign in to comment.