Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. #859

Closed
alvaromolinaGL opened this issue Aug 13, 2021 · 20 comments
Labels
Milestone

Comments

@alvaromolinaGL
Copy link

Hi, I am using the library to send some files through an sftp, I am connecting to the site via the SftpClient class:

var client = new SftpClient(host, port, username, password);

client.Connect();
client.UploadFile(zipFile, outPath);
client.Disconnect();

This code is running in an azure function, it was working fine but it stopped working back in May and its now throwing this message:

Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.)

Any ideas??

Thanks.

@IgorMilavec
Copy link
Collaborator

Can you provide the call stack of the exception?

@dd-morphi
Copy link

Hi,
Recently I've hit an issue with the same error message but in a different scenario.
My code is connecting to devices through SSH. One of those devices is an older Linux.
When connecting to it on Windows with .net5 it throws the exception:

System.PlatformNotSupportedException: Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.)
   at System.Security.Cryptography.HMAC.HashFinal()
   at Renci.SshNet.Security.Cryptography.HMACSHA1.HashFinal()
   at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize()
   at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer)
   at Renci.SshNet.Session.SendMessage(Message message)
   at Renci.SshNet.Session.Connect()
   at Renci.SshNet.BaseClient.CreateAndConnectSession()
   at Renci.SshNet.BaseClient.Connect()

I was trying to debug your library and discovered that the issue is on this device because it returns the only hash algorithm hmac-sha1-96. It looks that your library on netstandard2.0 has an issue with this. When tried with framework it works.

I reproduced the issue with Ubuntu by adding the line MACs hmac-sha1-96 to /etc/ssh/sshd_config and restarting the sshd service.

The easiest workaround for it is removing FEATURE_HMAC_SHA1 from the list of DefineConstants and then rebuilding it. It uses then SshNet.Security.Cryptography which works correctly in this scenario.


I was looking also at your implementation of Renci.SshNet.Security.Cryptography.HMACSHA1 and the strange thing is that on netstandard2.0 it sees HMAC as the base implementation of HashFinal not HMACSHA1
image
When analyzing the .net implementation it looks that this error message is only thrown on the usage of HMAC methods.
I copied Renci.SshNet.Security.Cryptography.HMACSHA1 code to .net5.0 program and it works correctly.

I hope it helps somehow to fix it

@alvaromolinaGL
Copy link
Author

That is exactly the error message I am seeing, it's throwing it when trying to connect to the sftp.

at System.Security.Cryptography.HMAC.HashFinal()
at Renci.SshNet.Security.Cryptography.HMACMD5.HashFinal()
at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize()
at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer)
at Renci.SshNet.Session.SendMessage(Message message)
at Renci.SshNet.Session.Connect()
at Renci.SshNet.BaseClient.CreateAndConnectSession()
at Renci.SshNet.BaseClient.Connect()

How can I. change the DefineConstants?

@dd-morphi
Copy link

I have changed it like here dd-morphi@9d3387e?branch=9d3387e1d6b406c215a160d2bc0f0bb338c39f6f for netstandard2.0
Then I rebuild the library and in csproj instead of

  <ItemGroup>
    <PackageReference Include="SSH.NET" Version="2020.0.1" />
  </ItemGroup>

I put

  <ItemGroup>
    <PackageReference Include="SshNet.Security.Cryptography" Version="1.3.0" />
    <Reference Include="Renci.SshNet">
      <HintPath>..\Renci.SshNet.dll</HintPath>
    </Reference>
  </ItemGroup>

with reference to compiled library

@IgorMilavec
Copy link
Collaborator

This seems to be the problem mentioned in dotnet/runtime#22929.
@dd-morphi do I understand correctly that the issue is fixed in SshNet.Security.Cryptography and you could fix the error by backporting this class to SshNet?
@drieseng can you please help determine the appropriate course of action: should the changes be backported to SshNet or should crypto functionality be completely removed from SshNet in favor of using the SshNet.Security.Cryptography?

@dd-morphi
Copy link

@IgorMilavec backporting to SshNet.Security.Cryptography helps, but SSH.NET uses System.Security.Cryptography.HMACSHA1 in two places:

  1. for "hmac-sha1" where it creates new System.Security.Cryptography.HMACSHA1(key)
  2. for "hmac-sha1-96" where it derives from public class HMACSHA1 : System.Security.Cryptography.HMACSHA1

The first works correctly always, the second fails with this strange error message on .net5.0. (it looks like base keyword instead of parents HMACSHA1.HashFinal() method finds grand parents method HMAC.HashFinal())

@Ronn1e-D
Copy link

Ronn1e-D commented Sep 8, 2021

Same here! Using on Azure Function v3 (netcoreapp3.1), but with a specific SFTP server. I'm connecting with 3 different SFTP servers, 2 work flawlessly and 1 is failing with this exact error.

System.PlatformNotSupportedException: Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.) at System.Security.Cryptography.HMAC.HashFinal() at Renci.SshNet.Security.Cryptography.HMACSHA1.HashFinal() at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize() at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer) at Renci.SshNet.Session.SendMessage(Message message) at Renci.SshNet.Session.Connect() at Renci.SshNet.BaseClient.CreateAndConnectSession() at Renci.SshNet.BaseClient.Connect() at D365.AzureFunctions.Handlers.SFTPHandler.UploadFile(Stream fileStream,String filename,String remoteFilePath)

Hoping for a permanent solution :) I really don't want to switch to another package.

@Ronn1e-D
Copy link

I can confirm that the solution provided by @dd-morphi works. Thanks for that :)

@malhotrar
Copy link

malhotrar commented Oct 6, 2021

Hitting the same issue running .net5 on windows. What is the recommended course of action here? I'm not super thrilled about having to package a custom version here similar to @dd-morphi, as I use this in an enterprise ETL tool.

@drieseng - is there a timeline for a resolution?

@lawhorkl
Copy link

I tried @dd-morphi 's solution and its worked for us. I'd be willing to put a PR up if it would be merged in relatively soon.

Haven't had a release for a little while as well.

@Aethon
Copy link

Aethon commented Jul 26, 2022

It was good to find this discussion here, since we could not get past connecting with our client's SFTP server. We started down the path of this workaround, but were deeply unsatisfied with maintaining our own copy of the assembly. I poked a little and found an easier workaround that uses the published package:

        var info = new ConnectionInfo(
            "host.com",
            22,
            "user1",
            new PasswordAuthenticationMethod("user1", "secret_password")
        );
        info.HmacAlgorithms["hmac-sha1"] =
            new HashInfo(160, k => new SshNet.Security.Cryptography.HMACSHA1(k));
        info.HmacAlgorithms["hmac-sha1-96"] =
            new HashInfo(160, k => new SshNet.Security.Cryptography.HMACSHA1(k, 96));
        info.HmacAlgorithms["hmac-md5"] =
            new HashInfo(128, k => new SshNet.Security.Cryptography.HMACMD5(k));
        info.HmacAlgorithms["hmac-md5-96"] =
            new HashInfo(128, key => new SshNet.Security.Cryptography.HMACMD5(key, 96));

In our case, we only had to override the MD5 macs, but as many (or all) of the crypto algorithms can be fixed up via the connection info. Super nicely designed.

HTH someone else until the bug is fixed in a release, and thanks to the maintainers of this sweet library.

@menees
Copy link
Contributor

menees commented Jun 6, 2023

Thanks, @Aethon! Your workaround was very helpful! I looked at the default HmacAlgorithms set by ConnectionInfo.cs, and I extended your example code to override them all with concrete implementations instead of using the CryptoAbstraction defaults.

var info = new ConnectionInfo(
	"host.com",
	22,
	"user1",
	new PasswordAuthenticationMethod("user1", "secret_password")
);
IDictionary<string, HashInfo> hmacAlgorithms = info.HmacAlgorithms;
hmacAlgorithms["hmac-md5"] = new HashInfo(128, key => new SshNet.Security.Cryptography.HMACMD5(key));
hmacAlgorithms["hmac-md5-96"] = new HashInfo(128, key => new SshNet.Security.Cryptography.HMACMD5(key, 96));
hmacAlgorithms["hmac-sha1"] = new HashInfo(160, key => new SshNet.Security.Cryptography.HMACSHA1(key));
hmacAlgorithms["hmac-sha1-96"] = new HashInfo(160, key => new SshNet.Security.Cryptography.HMACSHA1(key, 96));
hmacAlgorithms["hmac-sha2-256"] = new HashInfo(256, key => new SshNet.Security.Cryptography.HMACSHA256(key));
hmacAlgorithms["hmac-sha2-256-96"] = new HashInfo(256, key => new SshNet.Security.Cryptography.HMACSHA256(key, 96));
hmacAlgorithms["hmac-sha2-512"] = new HashInfo(512, key => new SshNet.Security.Cryptography.HMACSHA512(key));
hmacAlgorithms["hmac-sha2-512-96"] = new HashInfo(512, key => new SshNet.Security.Cryptography.HMACSHA512(key, 96));
hmacAlgorithms["hmac-ripemd160"] = new HashInfo(160, key => new SshNet.Security.Cryptography.HMACRIPEMD160(key));
hmacAlgorithms["hmac-ripemd160@openssh.com"] = new HashInfo(160, key => new SshNet.Security.Cryptography.HMACRIPEMD160(key));

@Rob-Hague
Copy link
Collaborator

Rob-Hague commented Aug 31, 2023

This only repros on .NET Core targets using the .NET Standard 2.0 version of the library, which as of the latest package 2020.0.2, is all of them. It is (inadvertently) fixed in the develop branch.

The reason is that Renci.SshNet.Security.Cryptography.HMACSHA1 subclasses System.Security.Cryptography.HMACSHA1 and overrides HashFinal, calling the base method here:

protected override byte[] HashFinal()
{
var hash = base.HashFinal();
return hash.Take(HashSize / 8);
}

I can only really explain with pictures, but when targeting netstandard2.0, base.HashFinal is pointing to HMAC.HashFinal (edit: this was already explained above):

image

which on .NET Core is just:

https://github.com/dotnet/runtime/blob/4aadfea70082ae23e6c54a449268341e9429434e/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HMAC.cs#L67-L68

throwing (with a misleading exception message?):

System.PlatformNotSupportedException
  HResult=0x80131539
  Message=Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.)
  Source=System.Security.Cryptography.Primitives
  StackTrace:
   at System.Security.Cryptography.HMAC.HashFinal()
   at Renci.SshNet.Security.Cryptography.HMACSHA1.HashFinal() in SSH.NET\src\Renci.SshNet\Security\Cryptography\HMACSHA1.cs:line 54
   at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize()
   at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer)
   at Renci.SshNet.Tests.Classes.ExpectActionTest.Sss() in SSH.NET\src\Renci.SshNet.Tests\Classes\ExpectActionTest.cs:line 48

Whereas when actually targeting .NET Core it is pointing to HMACSHA1.HashFinal:

image

Right now the develop branch has a target for net6.0 and so the problem doesn't occur.

It actually also has a target for netstandard2.1 meaning the problem also does not occur for apps targeting net5.0 (or earlier):

image

@Zero-Xiong
Copy link

is the issue permanent solved? I still face the issue on 2020.0.2

@Rob-Hague
Copy link
Collaborator

Yes on the develop branch and the next (imminent) release

@WojciechNagorski WojciechNagorski added this to the 2023.0.0 milestone Oct 11, 2023
@WojciechNagorski
Copy link
Collaborator

Version 2023.0.0 has been published https://www.nuget.org/packages/SSH.NET/2023.0.0

@Eduard-Nuco
Copy link

Hi, using the latest version in our webapp, 2023.0.0, and getting an issue similar to this one. Below is the error and stack trace.

Error: System.ArgumentException: Could not create HashAlgorithm from SHA1. (Parameter 'hashAlgorithmName')

Stack Trace: at Renci.SshNet.Security.Cryptography.RsaDigitalSignature..ctor(RsaKey rsaKey, HashAlgorithmName hashAlgorithmName)
at Renci.SshNet.ConnectionInfo.<>c.<.ctor>b__132_26(Byte[] data)
at Renci.SshNet.Security.KeyExchange.ValidateExchangeHash(Byte[] encodedKey, Byte[] encodedSignature)
at Renci.SshNet.Security.KeyExchangeEC.ValidateExchangeHash()
at Renci.SshNet.Security.KeyExchange.Finish()
at Renci.SshNet.Security.KeyExchangeECDH.Finish()
at Renci.SshNet.Security.KeyExchangeECDH.Session_KeyExchangeEcdhReplyMessageReceived(Object sender, MessageEventArgs`1 e)
at Renci.SshNet.Messages.Transport.KeyExchangeEcdhReplyMessage.Process(Session session)
at Renci.SshNet.Session.MessageListener()
--- End of stack trace from previous location ---
at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle)
at Renci.SshNet.Session.Connect()
at Renci.SshNet.BaseClient.CreateAndConnectSession()
at Renci.SshNet.BaseClient.Connect()

@Rob-Hague
Copy link
Collaborator

Rob-Hague commented Oct 16, 2023

@Eduard-Nuco what OS and .NET version are you using?

edit: also, is this a published application, or could trimming be otherwise involved?

@Eduard-Nuco
Copy link

@Rob-Hague I'm developing on Windows 11, the project is using .NET 7. It's in release configuration with deployment mode as self-contained and target runtime is win-x86. The app is hosted on our local server running Windows 10.

I disabled trimming and am not getting the error anymore. I didn't consider this an issue previously, so thank you for the input.

@Rob-Hague
Copy link
Collaborator

Thanks for the info. I have opened #1216 to fix the trimming issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests