Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
901fd5a
Use BCL ECDiffieHellman for KeyExchange (.NET 8.0 onward only)
scott-xu Apr 6, 2024
f78488c
Merge branch 'develop' into ecdh-bcl
scott-xu Apr 6, 2024
4b8be40
Add back an empty line
scott-xu Apr 6, 2024
8e6d079
Merge branch 'ecdh-bcl' of https://github.com/scott-xu/SSH.NET into e…
scott-xu Apr 6, 2024
61e44a4
Remove the BouncyCastle dependency when target .NET 8.0 onward.
scott-xu Apr 7, 2024
767e692
Merge branch 'develop' into ecdh-bcl
scott-xu Apr 7, 2024
4628a73
Run KeyExchangeAlgorithmTests for .NET 6.0
scott-xu Apr 9, 2024
23c4ac2
Merge branch 'ecdh-bcl' of https://github.com/scott-xu/SSH.NET into e…
scott-xu Apr 9, 2024
23a1dd3
Build Renci.SshNet.IntegrationTests.csproj for net6.0
scott-xu Apr 9, 2024
182f586
Update filter
scott-xu Apr 9, 2024
fed031b
Merge branch 'develop' into ecdh-bcl
scott-xu Apr 18, 2024
cfd950f
Merge branch 'develop' into ecdh-bcl
scott-xu Apr 25, 2024
8392edb
Merge branch 'develop' into ecdh-bcl
scott-xu May 4, 2024
8b42e59
Merge branch 'develop' of https://github.com/scott-xu/SSH.NET into ec…
scott-xu May 23, 2024
b35ffdf
Merge branch 'ecdh-bcl' of https://github.com/scott-xu/SSH.NET into e…
scott-xu May 23, 2024
4b73a96
Merge branch 'develop' into ecdh-bcl
scott-xu Jun 9, 2024
5502918
Add back BouncyCastle as fallback
scott-xu Jun 12, 2024
f76ffeb
Merge branch 'develop' into ecdh-bcl
scott-xu Jun 13, 2024
a1b00e3
Add back the missing `SendMessage`
scott-xu Jun 13, 2024
6ed28ae
Merge branch 'ecdh-bcl' of https://github.com/scott-xu/SSH.NET into e…
scott-xu Jun 13, 2024
d754e93
Merge branch 'develop' into ecdh-bcl
scott-xu Jun 16, 2024
08c9594
Merge branch 'develop' of https://github.com/scott-xu/SSH.NET into ec…
scott-xu Jul 17, 2024
4495c57
Merge branch 'ecdh-bcl' of https://github.com/scott-xu/SSH.NET into e…
scott-xu Jul 17, 2024
bd093c7
Merge branch 'develop' into ecdh-bcl
scott-xu Jul 23, 2024
57bf19d
Merge branch 'develop' into ecdh-bcl
WojciechNagorski Jul 25, 2024
13dd7e1
Run ECDH KEX integration tests under .NET48
scott-xu Jul 25, 2024
9fa0c14
Merge branch 'develop' into ecdh-bcl
scott-xu Jul 25, 2024
344b744
Merge branch 'develop' into ecdh-bcl
scott-xu Jul 27, 2024
385e087
Use SshNamedCurves instead of SecNamedCurves for BouncyCastle.
scott-xu Jul 28, 2024
387e6da
typo
scott-xu Jul 28, 2024
73c9446
Fix build
scott-xu Jul 29, 2024
db0a98e
Use System.Security.Cryptography namespace if NET8_0_OR_GREATER;
scott-xu Jul 29, 2024
2441f77
Separate BCL and BouncyCastle implementation
scott-xu Jul 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ for:
- sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_unit_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_unit_test_net_8_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
- sh: echo "Run integration tests"
- sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_8_coverage.xml test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
- sh: dotnet test -f net48 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_48_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_48_coverage.xml --filter "Name=ChaCha20Poly1305|Name~Zlib" test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj
- sh: dotnet test -f net48 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_48_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_48_coverage.xml --filter "Name=ChaCha20Poly1305|Name~Ecdh|Name~Zlib" test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj

-
matrix:
Expand Down
79 changes: 67 additions & 12 deletions src/Renci.SshNet/Security/KeyExchangeECDH.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;

using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Math.EC;

using Renci.SshNet.Abstractions;
Expand All @@ -14,16 +14,19 @@ namespace Renci.SshNet.Security
{
internal abstract class KeyExchangeECDH : KeyExchangeEC
{
#if NET8_0_OR_GREATER
private System.Security.Cryptography.ECDiffieHellman _clientECDH;
#endif
private ECDHCBasicAgreement _keyAgreement;
private ECDomainParameters _domainParameters;

/// <summary>
/// Gets the parameter of the curve.
/// Gets the name of the curve.
/// </summary>
/// <value>
/// The parameter of the curve.
/// The name of the curve.
/// </value>
protected abstract X9ECParameters CurveParameter { get; }

private ECDHCBasicAgreement _keyAgreement;
private ECDomainParameters _domainParameters;
protected abstract string CurveName { get; }

/// <inheritdoc/>
public override void Start(Session session, KeyExchangeInitMessage message, bool sendClientInitMessage)
Expand All @@ -34,11 +37,30 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool

Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived;

_domainParameters = new ECDomainParameters(CurveParameter.Curve,
CurveParameter.G,
CurveParameter.N,
CurveParameter.H,
CurveParameter.GetSeed());
#if NET8_0_OR_GREATER
if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(10))
{
_clientECDH = System.Security.Cryptography.ECDiffieHellman.Create();
_clientECDH.GenerateKey(System.Security.Cryptography.ECCurve.CreateFromFriendlyName(CurveName));

var q = _clientECDH.PublicKey.ExportParameters().Q;

_clientExchangeValue = new byte[1 + q.X.Length + q.Y.Length];
_clientExchangeValue[0] = 0x04;
Buffer.BlockCopy(q.X, 0, _clientExchangeValue, 1, q.X.Length);
Buffer.BlockCopy(q.Y, 0, _clientExchangeValue, q.X.Length + 1, q.Y.Length);

SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue));

return;
}
#endif
var curveParameter = SshNamedCurves.GetByName(CurveName);
_domainParameters = new ECDomainParameters(curveParameter.Curve,
curveParameter.G,
curveParameter.N,
curveParameter.H,
curveParameter.GetSeed());

var g = new ECKeyPairGenerator();
g.Init(new ECKeyGenerationParameters(_domainParameters, CryptoAbstraction.SecureRandom));
Expand Down Expand Up @@ -92,12 +114,45 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b
var y = new byte[cordSize];
Buffer.BlockCopy(serverExchangeValue, cordSize + 1, y, 0, y.Length);

#if NET8_0_OR_GREATER
if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(10))
{
using var serverECDH = System.Security.Cryptography.ECDiffieHellman.Create(
new System.Security.Cryptography.ECParameters
{
Curve = System.Security.Cryptography.ECCurve.CreateFromFriendlyName(CurveName),
Q =
{
X = x,
Y = y,
},
});

var k = _clientECDH.DeriveRawSecretAgreement(serverECDH.PublicKey);
SharedKey = k.ToBigInteger2().ToByteArray().Reverse();

return;
}
#endif
var c = (FpCurve)_domainParameters.Curve;
var q = c.CreatePoint(new Org.BouncyCastle.Math.BigInteger(1, x), new Org.BouncyCastle.Math.BigInteger(1, y));
var publicKey = new ECPublicKeyParameters("ECDH", q, _domainParameters);

var k1 = _keyAgreement.CalculateAgreement(publicKey);
SharedKey = k1.ToByteArray().ToBigInteger2().ToByteArray().Reverse();
}

#if NET8_0_OR_GREATER

/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_clientECDH?.Dispose();
}
}
#endif
}
}
14 changes: 4 additions & 10 deletions src/Renci.SshNet/Security/KeyExchangeECDH256.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;

using Renci.SshNet.Abstractions;
using Renci.SshNet.Abstractions;

namespace Renci.SshNet.Security
{
Expand All @@ -16,14 +13,11 @@ public override string Name
}

/// <summary>
/// Gets Curve Parameter.
/// Gets curve name.
/// </summary>
protected override X9ECParameters CurveParameter
protected override string CurveName
{
get
{
return SecNamedCurves.GetByName("secp256r1");
}
get { return "nistp256"; }
}

/// <summary>
Expand Down
14 changes: 4 additions & 10 deletions src/Renci.SshNet/Security/KeyExchangeECDH384.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;

using Renci.SshNet.Abstractions;
using Renci.SshNet.Abstractions;

namespace Renci.SshNet.Security
{
Expand All @@ -16,14 +13,11 @@ public override string Name
}

/// <summary>
/// Gets Curve Parameter.
/// Gets curve name.
/// </summary>
protected override X9ECParameters CurveParameter
protected override string CurveName
{
get
{
return SecNamedCurves.GetByName("secp384r1");
}
get { return "nistp384"; }
}

/// <summary>
Expand Down
14 changes: 4 additions & 10 deletions src/Renci.SshNet/Security/KeyExchangeECDH521.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;

using Renci.SshNet.Abstractions;
using Renci.SshNet.Abstractions;

namespace Renci.SshNet.Security
{
Expand All @@ -16,14 +13,11 @@ public override string Name
}

/// <summary>
/// Gets Curve Parameter.
/// Gets curve name.
/// </summary>
protected override X9ECParameters CurveParameter
protected override string CurveName
{
get
{
return SecNamedCurves.GetByName("secp521r1");
}
get { return "nistp384"; }
}

/// <summary>
Expand Down