23 Commits

Author SHA1 Message Date
Copilot 41053cb80f Replace Assert.IsTrue with CollectionAssert.AreEqual for collection comparisons (#1730)
* Initial plan

* Refactor collection assertions to use CollectionAssert.AreEqual

Replace Assert.IsTrue(xxx.IsEqualTo(yyy)) and Assert.IsTrue(xxx.SequenceEqual(yyy))
with CollectionAssert.AreEqual(expected, actual) across 55 test files

Co-authored-by: Rob-Hague <5132141+Rob-Hague@users.noreply.github.com>

* Fix argument order in CollectionAssert.AreEqual and remove unnecessary using directives

- Fixed argument order in KeyExchangeDhGroupExchangeReplyTest.cs (expected first, actual second)
- Fixed argument order in KeyExchangeInitMessageTest.cs (expected first, actual second)
- Removed unnecessary 'using System.Linq' directives from all affected test files

Co-authored-by: Rob-Hague <5132141+Rob-Hague@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Rob-Hague <5132141+Rob-Hague@users.noreply.github.com>
Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2026-06-26 17:44:36 +02:00
dependabot[bot] f5e6ce710c Bump the dependencies group with 11 updates (#1808)
* Bump the dependencies group with 11 updates

Bumps coverlet.collector from 6.0.4 to 10.0.1
Bumps coverlet.msbuild from 6.0.4 to 10.0.1
Bumps GitHubActionsTestLogger from 3.0.1 to 3.0.4
Bumps Meziantou.Analyzer from 3.0.18 to 3.0.114
Bumps Microsoft.Bcl.Cryptography from 10.0.3 to 10.0.9
Bumps Microsoft.Extensions.Logging.Console from 10.0.3 to 10.0.9
Bumps MSTest from 4.1.0 to 4.2.3
Bumps PolySharp from 1.15.0 to 1.16.0
Bumps SonarAnalyzer.CSharp from 10.20.0.135146 to 10.27.0.140913
Bumps System.Formats.Asn1 from 10.0.3 to 10.0.9
Bumps Testcontainers from 4.10.0 to 4.12.0

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Robert Hague <rh@johnstreetcapital.com>
2026-06-26 17:20:18 +02:00
Rob Hague 8ed8d38fa8 Encrypt packets in-place (#1787)
Support in-place encryption in the cipher types, then use it on the plaintext packets
instead of allocating a new array each time. Removes 2 of 4 bytes allocated for each
byte uploaded over SFTP.

For AES-CTR, supporting in-place encryption in this case means adding a persistent buffer
for the keystream and encrypting in chunks. The performance difference is ~1-2% i.e.
marginal versus one-shotting it. The variance is similar also for different choices of
buffer size (here 4096 is used).
2026-05-05 12:57:13 +02:00
mus65 4e02502bdf Add .NET 10 target and make use of C#14 extension members (#1672)
* Add .NET 10 target

* fix IDE0031

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0031

* fix ca5399

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca5399

* fix ca1515

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1515

* fix ca2002

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2002

* fix ca1508

new false positives.

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1508

* fix ca2000

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2000

* fix ca2025

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2025

* fix ca1849

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1849

* fix Reverse() overloads

because of https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/csharp-overload-resolution

* supress CA2002

* Use extension members for ThrowHelpers

* use extension members for CryptoAbstractions

* use extension member for DateTime.UnixEpoch

* use extension members for string.Join etc

* use extension members for Convert.To/FromHexString

* disable CA1508

* Update .NET 10 RC2

* Workaround Build Regression in .NET 10 RC2

https://github.com/dotnet/sdk/issues/51265

* suppress new warnings introduced by merge

* Update to .NET 10 final release

* Revert "Workaround Build Regression in .NET 10 RC2"

This is fixed in the final release.

This reverts commit 5a59ac9aa8.

* fix new warnings with MSTest 4 + .NET 10

* use same Randomizer instance

* disable CA2000

* reduce CA1849 suppressions

and disable duplicate S6966

* disable preview analyzers

reverts 6c3c06d95a
2025-11-15 12:21:49 +01:00
mus65 933613e31c Update to MSTest 4 (#1721)
* Update to MSTest 4

* fix TestMethodForPlatformAttribute

replace Execute with ExecuteAsync and fix MSTEST0057

https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0057 (link currently dead)

* fix compilation error

* fix MSTEST0037

https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0037

* fix MSTEST0052

https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0052

* fix MSTEST0045

Fixing this properly would require the tests to respect
testContext.CancellationToken. I'm not sure this is worth fixing
or how to even do it for the sync methods.

https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0045

* fix MSTEST0001

I assume that parallelization would break a lot of stuff.

https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0001

* Workaround for new Sonar warnings because of MSTest4

* revert analyzer fixes in OrderedDictionaryTest

* use custom sync console logger for MSTest

to work around https://github.com/microsoft/testfx/issues/6457

* remove redundant args

---------

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2025-11-14 22:09:13 +01:00
dependabot[bot] 03ae6bfa0f Bump dependencies (#1682)
* Bump the dependencies group with 4 updates

Bumps BouncyCastle.Cryptography from 2.6.1 to 2.6.2
Bumps Meziantou.Analyzer from 2.0.205 to 2.0.210
Bumps MSTest from 3.9.3 to 3.10.0
Bumps SonarAnalyzer.CSharp from 10.13.0.120203 to 10.15.0.120848

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2025-08-02 17:57:09 +02:00
Rob Hague dab8a11738 Use BouncyCastle for Diffie-Hellman key exchange (#1654)
Removes another vestige of hand-rolled crypto, and makes the classes public +
configurable for if/when we remove certain algorithms.
2025-08-02 11:08:56 +02:00
mus65 d1213cf751 remove Reverse extension to avoid source-breaking change with .NET 10 (#1606)
* remove Reverse extension to avoid source-breaking change with .NET 10

* revert to ifdef in some places

to avoid extra array copy on lower targets
2025-03-01 17:01:23 +01:00
Rob Hague 60f3cd803e Drop DSA (#1558)
DSA is removed at compile time from OpenSSH 9.8 and higher.
That means we can no longer test it in our integration tests. It seems like a
good time to remove it. From the OpenSSH release notes:

    DSA, as specified in the SSHv2 protocol, is inherently weak - being
    limited to a 160 bit private key and use of the SHA1 digest. Its
    estimated security level is only 80 bits symmetric equivalent.

    OpenSSH has disabled DSA keys by default since 2015 but has retained
    run-time optional support for them. DSA was the only mandatory-to-
    implement algorithm in the SSHv2 RFCs, mostly because alternative
    algorithms were encumbered by patents when the SSHv2 protocol was
    specified.

    This has not been the case for decades at this point and better
    algorithms are well supported by all actively-maintained SSH
    implementations. We do not consider the costs of maintaining DSA
    in OpenSSH to be justified and hope that removing it from OpenSSH
    can accelerate its wider deprecation in supporting cryptography
    libraries.
2025-01-03 11:12:21 +01:00
Scott Xu 14c652cb45 Use System.Security.Cryptography for TripleDesCipher (#1546)
* Use System.Security.Cryptography in DesCipher and TripleDesCipher; Fall back to use BouncyCastle if BCL doesn't support

* Drop DesCipher; Replace PKCS7Padding with BouncyCastle's implementation.

* Restore `CbcCipherMode`

* Restore AesCipherMode; Use BlockImpl instead of BouncyCastleImpl for 3DES-CFB on lower targets.

* Restore the xml doc comment
2024-12-27 13:37:02 +01:00
Scott Xu 29997aebe1 Add padding when encrypt and remove padding when decrypt (#1545)
* Tighten private key checking to reveal padding issue

* `Encrypt` should take into account padding for length of `inputBuffer` passed to `EncryptBlock` if padding is specified, no matter input is divisible or not.

* `Decrypt` should take into account unpadding for the final output if padding is specified.

* `Decrypt` should take into account *manual* padding for length of `inputBuffer` passed to `DecryptBlock` and unpadding for the final output if padding is not specified and mode is CFB or OFB.

* `Encrypt` should take into account *manual* padding for length of `inputBuffer` passed to `EncryptBlock` and unpadding for the final output if padding is not specified and mode is CFB or OFB.

* Rectify DES cipher tests. There's no padding in the data.

* Borrow `PadCount` method from BouncyCastle

* Manually pad input in CTR mode as well. Update AesCipherTest.

Co-Authored-By: Rob Hague <5132141+Rob-Hague@users.noreply.github.com>

* Manually pad/unpad for Aes CFB/OFB mode

* Update test/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/AesCipherTest.Gen.cs.txt

Co-authored-by: Rob Hague <rob.hague00@gmail.com>

* Re-generate AES cipher tests

---------

Co-authored-by: Rob Hague <5132141+Rob-Hague@users.noreply.github.com>
Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2024-12-22 16:21:02 +01:00
Rob Hague 3e12c96317 Add support for OpenSSH certificates (#1498)
Co-authored-by: cedricMicrovision <cedric.legoff@microvision.fr>
2024-10-19 14:36:41 +02:00
Rob Hague d06dfa5e4d Use System.Numerics.BigInteger (#1469)
Instead of the point-in-time copy
2024-09-05 13:51:57 +02:00
mus65 3dda5c92ce another .NET 9 SDK Build fix (#1475)
see 1b71e8fea4 and
 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1872
2024-08-24 12:50:00 +02:00
Rob Hague fe65570ebc Use System.Security.Cryptography for DSA (#1458)
* Use System.Security.Cryptography for DSA

This is the analogue of the RSA change #1373 for DSA. This has a couple of caveats:

- The BCL supports only FIPS 186-compliant keys, that is, public (P, Q) lengths
  of (512 <= P <= 1024, 160) for FIPS 186-1/186-2; and (2048, 256), (3072, 256)
  for FIPS 186-3/186-4. The latter also specifies (2048, 224) but due to a quirk
  in the Windows API, the BCL does not support Q values of length 224[^1].
- OpenSSH, based on the SSH spec, only supports (supported) Q values of length 160,
  but appears to also work in non-FIPS-compliant cases such as in our integration
  tests with a (2048, 160) host key. That test now fails and I changed that host key
  to (1024, 160).

This basically means that (1024, 160) is the largest DSA key size supported by both
SSH.NET and OpenSSH. However, given that OpenSSH deprecated DSA in 2015[^2], and the
alternative that I have been considering is just to delete support for DSA in the
library, this change seems reasonable to me. I don't think we can justify keeping the
current handwritten code around.

I think we may still consider dropping DSA from the library, I just had this branch
laying around and figured I'd finish it off.

[^1]: https://github.com/dotnet/runtime/blob/fadd8313653f71abd0068c8bf914be88edb2c8d3/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs#L259-L265
[^2]: https://www.openssh.com/txt/release-7.0

* Appease mono

* test experiment

* Revert "Appease mono"

This reverts commit 881eefe5e8.
2024-08-11 07:48:58 +02:00
Rob Hague 8ea108af1c Drop legacy algorithms part 1 (#1442)
This drops some of the algorithms long-considered legacy/insecure.

The idea is both to improve the theoretical security of the library by not offering
these algorithms, and to improve the practical security of the library by not having
hand-written, barely tested crypto code.

The overarching goal is for the library to have minimal exposure to crypto
implementation, relying firstly on the .NET base libraries, and secondly on
third-party providers, such as BouncyCastle.

This change covers deleting the cipher algorithms arcfour, blowfish, twofish, cast.
It covers deleting the MD5-based and truncated HMAC algorithms.

These were all disabled in OpenSSH server (sshd) in 2014[^1]:

> sshd(8): The default set of ciphers and MACs has been altered to
> remove unsafe algorithms. In particular, CBC ciphers and arcfour*
> are disabled by default.
>
> The full set of algorithms remains available if configured
> explicitly via the Ciphers and MACs sshd_config options.

and in the client in 2016[^2]:

> This release disables a number of legacy cryptographic algorithms
> by default in ssh:
>
>  * Several ciphers blowfish-cbc, cast128-cbc, all arcfour variants
>    and the rijndael-cbc aliases for AES.
>
>  * MD5-based and truncated HMAC algorithms.
>
> These algorithms are already disabled by default in sshd.

This change also drops PKCS5Padding, which is a line-for-line copy of PKCS7Padding,
and StreamCipher, which is now unused (and useless anyway).

[^1]: https://www.openssh.com/txt/release-6.7
[^2]: https://www.openssh.com/txt/release-7.2

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
2024-07-17 08:20:10 +02:00
mus65 1b71e8fea4 fix build with .NET 9.0 SDK (#1427)
* .NET 9: fix CA1872

see https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1872

* .NET 9: fix CA2022

see https://github.com/dotnet/roslyn-analyzers/pull/7208

Most of these could be safely ignored because of the following assert.
As far as I can see, The SftpFileStream.Read() implementation guarentees
that the specified number of bytes is read anyway.

---------

Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2024-06-16 11:35:20 +02:00
mus65 c0a353a4de Cleanup formatting and style and enforce it in CI (#1380)
* Preparation to enforce formatting and style in CI

- enabled IDE0055 to enforce formatting on build
- disabled SA1137 and SA1025 because they are already
  covered by IDE0055
- disabled SA1021 because it conflicts with csharp_space_after_cast

* Cleanup formatting and style on codebase

This commit has no manual changes, it is the result
of running "dotnet format whitespace" and "dotnet format style"

* new formatting fixes after merge

* appveyor: set git autocrlf

as suggested by sharwell to hopefully fix Windows CI.

* use autocrlf input

to hopefully fix Linux tests

* fix formatting

* use autocrlf input for Linux only

* set csharp_space_after_cast to false

* Revert SA1021 suppression

---------

Co-authored-by: Robert Hague <rh@johnstreetcapital.com>
2024-05-17 22:34:27 +02:00
Rob Hague f9908a22b5 Use System.Security.Cryptography for RSA (#1373)
* Use BCL for RSA

* Restore benchmark (with quirks for old code)

* Fixup benchmark (remove compatibility with old code)

* cosmetic tweaks

* Add a regression test for #1388
2024-05-10 11:35:21 +02:00
Rob Hague 24838e6173 Make keys immutable (#1264)
This makes it easier to reason about Key instances in e.g.
DigitalSignature implementations, because we know that the
Key is initialised with its data and will not change.

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
2023-12-21 23:12:15 +01:00
Pedro Fonseca 4ce18d305e Use hardware-accelerated AES CryptoServiceProvider (#865)
* Add FEATURE_AES_CSP to use hardware-accelerated AesCryptoServiceProvider
Reduces CPU usage dramatically, allowing more performance on slower machines

* Restructure, move most of the feature code to AesCipher.cs
Fix padding for non-AES blockciphers
Fix IV exception for non-AES blockciphers

* Fix the AES Padding
It looks like the legacy code doesn't correctly remove padding, so this code needs to do the same.

* fix rebase issues
restructure AES CSP code into its own class

* Minor fixes

* Rework based on suggestions

* Move all changes to AesCypher.cs, as per Rob-Hague suggestion
Remove FEATURE_AES_CSP conditional
Fix OFB CipherMode

* update AesCipherTest.cs generator

* Fix continuous session encrypt/decrypt
(preserve IV between calls when Padding is None)

* Reduce CTR memory usage in Net 6+
Small performance increase in CTR buffer mode
Cosmetic changes

* Factor out the implementations and re-add the existing constructor

* remove ctor; revert tests; remove unused _iv member

* Reorder Encryption cipher preference list

* Remove redundant AES tests
Add tests for stream cipher state preservation

* Refactor ArrayXOR()

* Add test for IV overflow

* Performance bump for AES CTR (thanks @robhague)

* fix merge conflict

* Move AesCipherMode enum to its own file

---------

Co-authored-by: Pedro Fonseca <pfonseca@qti.qualcomm.com>
Co-authored-by: Rob Hague <rob.hague00@gmail.com>
2023-11-28 12:59:06 +01:00
Rob Hague 826222f6fe Increase test coverage for AesCipher (#1232)
* Increase test coverage for AesCipher

The tests were generated by a script which is also added for posterity.
The script works by running "openssl enc [...]" (via WSL) to generate the
expected encrypted values, and also verifies those values against the .NET
BCL implementation as an extra validation (it uncovered a difference in
CFB mode between the two relating to the feedback size).

* Fix OfbCipherMode

It was an exact copy of CfbCipherMode
2023-11-05 09:45:30 +01:00
Wojciech Nagórski f1297dec75 Move test projects (#1212)
* Move test projects to test folder.
Move global.json to root of repo.
Update solution items in solution.

* Move test projects to test folder.
Move global.json to root of repo.
Update solution items in solution.
Update appveyor configuration/

* Attempt to have appveyor use the correct .NET SDK.

* Update .NET SDK to version 7.0.402.

* Move Data folder below Renci.SshNet.Tests.

* Make csinst less chatty.

* Move Data folder directly below test folder as it's used by multiple test projects.

* Remove CS1591 nowarn from concrete test projects as this is already defined in the Directory.Build.props that is in the test folder.

* Fix integration test after moving test projects

---------

Co-authored-by: drieseng <gert.driesen@telenet.be>
2023-10-14 22:16:11 +02:00