From 71e2909dece446ae3f3c445414d6819ff8932644 Mon Sep 17 00:00:00 2001 From: Scott Xu Date: Wed, 24 Jul 2024 03:40:09 +0800 Subject: [PATCH] Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl (#1447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Curve25519 KEX is now based on BouncyCastle instead of Chaos.NaCl * Abstract SecureRandom --------- Co-authored-by: Wojciech Nagórski --- .../Abstractions/CryptoAbstraction.cs | 5 +++ .../Security/KeyExchangeECCurve25519.cs | 32 +++++++++++-------- src/Renci.SshNet/Security/KeyExchangeECDH.cs | 4 +-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs index 46f4b429d..0081e8860 100644 --- a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs @@ -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)); + /// /// Generates a array of the specified length, and fills it with a /// cryptographically strong random sequence of values. diff --git a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs index 987665afe..551fb948d 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs @@ -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; /// /// Gets algorithm name. @@ -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)); } @@ -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(); } } } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH.cs b/src/Renci.SshNet/Security/KeyExchangeECDH.cs index 88a76b81d..acf958048 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH.cs @@ -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; @@ -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();