Quellcode durchsuchen

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 <wojtpl2@gmail.com>
Scott Xu vor 1 Jahr
Ursprung
Commit
71e2909dec

+ 5 - 0
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));
+
         /// <summary>
         /// Generates a <see cref="byte"/> array of the specified length, and fills it with a
         /// cryptographically strong random sequence of values.

+ 19 - 13
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;
 
         /// <summary>
         /// Gets algorithm name.
@@ -38,13 +42,13 @@ namespace Renci.SshNet.Security
 
             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 @@ namespace Renci.SshNet.Security
             _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();
         }
     }
 }

+ 2 - 2
src/Renci.SshNet/Security/KeyExchangeECDH.cs

@@ -5,8 +5,8 @@ using Org.BouncyCastle.Crypto.Agreement;
 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 @@ namespace Renci.SshNet.Security
                                                       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();