alipha / csharp-argon2

C#/.NET binding for the Argon2 password hash
Other
36 stars 13 forks source link

libargon2.dll not found #2

Closed jwbats closed 8 years ago

jwbats commented 8 years ago

My solution contains one web project and multiple class libraries. I've set all my projects to x64.

The project runs successfully on either iis express 64 bits or iis local 64 bits.

When I hit this package's methods, I still get this error. What can I do to solve it?

alipha commented 8 years ago

jwbats,

I'm assuming you're using the Liphsoft.Crypto.Argon2 1.0.3 nuget package ( https://www.nuget.org/packages/Liphsoft.Crypto.Argon2/ )

When you deploy, the destination directory should contain a bin\ directory and inside it should be Liphsoft.Crypto.Argon2.dll and libargon2.dll. If Liphsoft.Crypto.Argon2.dll is there but libargon2.dll isn't, then for some reason my After Build step isn't executing correctly. What version of visual studio are you using? In your build output, do you see the message -- Liphsoft.CryptoArgon2.targets: Copying files from $(MSBuildThisFileDirectory)..\Argon2\x86\ to $(TargetDir) being displayed?

You could manually copy the libargon2.dll from YOUR_SOLUTION\packages\Liphsoft.Crypto.Argon2.1.0.3\Argon2\x64\libargon2.dll to the bin\ folder with the rest of the dlls, or add a build step yourself, just to get it working.

jwbats commented 8 years ago

The libargon2.dll file ends up in the debug directory of the class library that wants to execute your code.

I am getting the following:

An exception of type 'System.DllNotFoundException' occurred in Liphsoft.Crypto.Argon2.dll but was not handled in user code

Additional information: Unable to load DLL 'libargon2.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
pit123 commented 8 years ago

I'm having the same issue, even with the lastest update. The dll is in the Debug folder. The program runs, but when it reach the hast part it says:

An unhandled exception of type 'System.DllNotFoundException' occurred in Liphsoft.Crypto.Argon2.dll

Additional information: Unable to load DLL 'libargon2.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

alipha commented 8 years ago

What version of visual studio are you using? I tested on VS 2013 and 2015 and worked fine for me. Are you doing anything with custom build steps or build tools?

jwbats commented 8 years ago

I'm not using any custom build steps or build tools in VS2015. I've tried using it in my WebAPI2 project. It has been set to x64 per the instructions. This also causes VS2015 to no longer create Debug and Release folders for some reason. Rather, it places my build in the bin folder.

It still won't work for me, unfortunately. I'm disappointed that I'm basically forced to use a sub par hashing algo (sha512 in my case), because decent hashing algos aren't yet well enough supported in .NET. I would really like for this to work. If only there were a native implementation that installs under the latest .NET version. But with the extremely low number of downloads for the available Argon2 Nuget packages, I don't think anybody is going to maintain them.

Alipha, let's say I build a project with your Liphsoft Argon2 package and it doesn't work. Can I send it over so you can have a look at it to see what's the matter?

On Wed, Sep 21, 2016 at 9:13 PM, Kevin Spinar notifications@github.com wrote:

What version of visual studio are you using? I tested on VS 2013 and 2015 and worked fine for me. Are you doing anything with custom build steps or build tools?

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/alipha/csharp-argon2/issues/2#issuecomment-248713236, or mute the thread https://github.com/notifications/unsubscribe-auth/AL9zgP_LB5JvV7q0HVIk0JvEgOLXww1Dks5qsYH2gaJpZM4JuJE4 .

alipha commented 8 years ago

@jwbats, you said that libargon2.dll is in the Debug folder but then you said your build is in the bin folder--is the libargon2.dll not with the rest of the dlls from your build? If so, that is probably the problem. They should all be in the same folder. I think that might happen if your solution platform doesn't match your project platforms.

When you open up the configuration manager, make sure that the "Active solution platform" dropdown in the top right is set to x64 and that all the projects in the grid below have the Platform also set to x64. If there's a mismatch, then that could be the problem.

You may also try adding a new platform for x86 in the configuration manager. In the solution platform dropdown, you should be able to select and select x86 in the new window that pops up. Again, make sure that all the projects are also set to x86.

Honestly, I did most of my testing with console applications. I did some testing today with creating a Web API application. I ran into issues when setting the configuration to x64--the Visual Studio debugger doesn't appear to support x64, so then I had to set my project to use local IIS, and then I had issues with IIS not having permission to access the libargon2.dll, and it was just a mess. Using x86 instead was a lot smoother, so I would recommend trying that.

I hope that helps. Yeah, you can send me your code if you're still having problems and I can look at it.

jwbats commented 8 years ago

At first I was building for Any CPU, which creates a debug/release folder. But then I switched to x64, and everything ends up in the bin folder. The argon2 dll was in the same folder as the rest of my binaries. So that wasn't the problem.

I have now tried to use this nuget package in a console application just like you. It works right out of the box, when using the Any CPU build setting. Later on I will have a few more tries with a WebAPI project. I have run into the same issues as you have.

Did you know there is a setting called "Use the 64 bit version of IIS Express" in VS 2015? You can find it under "Projects and Solutions" -> "Web Projects".

I would really like to just run my application in 64 bit. It's going to be a program that targets a huge audience and I'm contemplating loading a huge amount of data in memory to serve requests quickly. Don't wanna run out of memory at 4GB.

Soon, I will have another shot at this to see if I can get argon2 working in my WebAPI project. I'll let you know how it works out.

By the way... this is the hash I got from my console app, using the default settings for "mypassword".

$argon2i$v=19$m=8192,t=3,p=1$qXWS7HplpNzq1QTZKhIoFw$Zbu0Z1SAWvCDwYJ0m36o4iFfPqu9jVyT/DHRy6pzCU0

Is this whole string the hash? I wasn't expecting it to contain readable information. Is it not a security risk to let people know upfront which hashing algo was used to create a hash?

On Wed, Sep 28, 2016 at 6:26 AM, Kevin Spinar notifications@github.com wrote:

@jwbats https://github.com/jwbats, you said that libargon2.dll is in the Debug folder but then you said your build is in the bin folder--is the libargon2.dll not with the rest of the dlls from your build? If so, that is probably the problem. They should all be in the same folder. I think that might happen if your solution platform doesn't match your project platforms.

When you open up the configuration manager, make sure that the "Active solution platform" dropdown in the top right is set to x64 and that all the projects in the grid below have the Platform also set to x64. If there's a mismatch, then that could be the problem.

You may also try adding a new platform for x86 in the configuration manager. In the solution platform dropdown, you should be able to select and select x86 in the new window that pops up. Again, make sure that all the projects are also set to x86.

Honestly, I did most of my testing with console applications. I did some testing today with creating a Web API application. I ran into issues when setting the configuration to x64--the Visual Studio debugger doesn't appear to support x64, so then I had to set my project to use local IIS, and then I had issues with IIS not having permission to access the libargon2.dll, and it was just a mess. Using x86 instead was a lot smoother, so I would recommend trying that.

I hope that helps. Yeah, you can send me your code if you're still having problems and I can look at it.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/alipha/csharp-argon2/issues/2#issuecomment-250068636, or mute the thread https://github.com/notifications/unsubscribe-auth/AL9zgOKFSlFK52IfiLt_z7q9tgvoqzsXks5quexzgaJpZM4JuJE4 .

jwbats commented 8 years ago

Solved the problem!

I am running a WebAPI project that references a Core project, which is a DLL.

The Core had the package installed and correctly received libargon2.dll. WebAPI did not have it installed and as such was unable to locate libargon2.dll in its own bin folder.

It did copy Liphsoft.Crypto.Argon2.dll in there, so I mistakenly thought it had everything it needed.

Speaking of bin folders (I mentioned this in my previous posts)... I just found out WebAPI projects need to have their output path set to 'bin' and not 'bin/Debug' or 'bin/x64/Debug'. And if you dare change it, there's gonna be trouble.

jwbats commented 8 years ago

I am reading the argon2 documentation and now have questions:

  1. Argon2 apparently supports salt lengths as an input parameter. Why does the liphsoft wrapper not? Would've been convenient if I didn't have to generate my own salts.
  2. The documentation recommends tweaking until you get 1ms hash times on recent hardware. My hardware is recent and I am getting 25ms hash times with the default settings: time=3, mem=8192, parallelism=1. Why have these default settings been chosen? The docs recommend time=2, mem=512, parallelism=2.
alipha commented 8 years ago

If you use PasswordHasher.Hash(string password), it will generate a secure, random 16-byte salt for you and encodes the salt into the hash output. So just use that. I'm not sure under what condition you would want a salt of a different length or generate your own salt, but if so, you'd do:

var hasher = new PasswordHasher();
var salt = PasswordHasher.GenerateSalt(32);
var hash = hasher.Hash(Encoding.UTF8.GetBytes("mypassword"), salt);

But really, just use hasher.Hash("mypassword").


That's not the official Argon2 documentation--that's the documentation for someone's port to Python. Argon2 was originally written in C and is here: https://github.com/P-H-C/phc-winner-argon2

I'm not sure why the author of that python port would recommend a target time under 1ms. That seems extremely low. You want the hash time to be as large as possible for your situation. Unless you're expecting a really high traffic website that needs to serve hundreds of logins a second (very little traffic on a site is actually someone logging in), then 1ms is too low and not nearly as secure as it probably could be. 25ms is probably appropriate for a site wanting to serve a couple dozen logins a second.

If instead of running Argon2 on a server, you were instead running Argon2 locally where you only need to hash one password at a time (perhaps as a key-derivation function to do password-based encryption), then really, I would crank up the time and memory parameters (and perhaps set parallelism to 4) so that it takes about a second to perform the hash. A single user won't care waiting a second after entering their password. It's only in a server environment where the server is having to perform several hashes at the same time because multiple people are logging in at the same time that you need lower parameters.


And I never answered your question about whether it's a security risk for all the parameters and salt to be encoded into the Argon2 hash. In cryptography, all these algorithms and systems are written with the principle that we need to assume the attacker knows everything except for the key (or password). If your server was hacked, then you have to assume that the hacker got everything--your database, configuration files, and application code. In which case, if you're not storing the Argon2 parameters in your database, they still have to be somewhere, either in config files or the application code and so the hacker will eventually find them.

Okay, yes, if the hacker only was only able to get the database and the parameters weren't in the database, then they would have more trouble cracking the passwords. But, let's say the hacker already has a username and password of his own in the database because he made an account with your site. Now he can figure out what the parameters are by trying different parameters with his own password until he reproduces his hash. Now he can start brute forcing other people's passwords since he knows what the parameters are. So this would be another situation where hiding them wouldn't really help.

Plus having the parameters built into the Argon2 hash output makes it a lot easier to change the parameters later. For instance, you might want to increase the parameters if you upgrade to new server hardware which can hash the passwords faster. Or, you might want decrease the parameters if you find that the amount of traffic you're seeing has grown a lot and your servers can't handle the traffic anymore. In either case, you can't update the hash parameters of the existing hashes all at once because you need the corresponding passwords, so instead you'd have to generate new hashes as people gradually log into the server. And so that means keeping track of which users are using which Argon2 parameters, and the whole thing is a lot easier if the parameters are right there with the hash.

But I will concede that a little obscurity can improve your security as long as you're not depending upon obscurity. However, there's a much easier and more effective way to add some obscurity and separate a piece of knowledge away from the database of passwords: add some global "pepper". "Password pepper" is an actual term that you can google if you want to read more about it, but the idea is that you have some application-wide value that you append to all your passwords:

string passwordPepper = ConfigurationManager.AppSettings["PasswordPepper"];
var hasher = new PasswordHasher();
var hash = hasher.Hash("mypassword" + passwordPepper);
// store hash in the database
// ...
if(hasher.Verify("mypassword" + passwordPepper))
// ...

You would want this password pepper to be at least 16 randomly-generated bytes and you could store it in your configuration file or even hard-code it into your source code. This accomplishes the same thing (and does it more effectively) as keeping the Argon2 parameters secret: the attacker needs the pepper or the password database is useless.

cosmin-ionita commented 8 years ago

For anyone that is facing the initial problem of this issue, here is my workaround:

  1. Install the Argon2 via NuGet
  2. Implement the logic that you want using hashing
  3. Clean & Rebuild the solution
  4. In the /bin folder of the project that uses the Liphsoft.Crypto.Argon2.dll you will find the problematic libargon.dll
  5. If you try to run the logic that does the hashing you will get an exception, telling you that the libargon.dll could not be found, which is actually the problem.

I've found out that WebAPI doesn't know by default how to load unmanaged dll files, you need to specify in the PATH the directory where unmanaged dll's are located.

Also, you need to give the IIS the right permissions to access that folder. In order to do that, make sure that you have checked the Internet Information Services feature in the Windows Features window. Then, go to Administative Tools -> Internet Information Services Manager -> Application Pools -> << Your Application Pool >>.

By default, there is one Application Pool named DefaultAppPool. Right click on it, Advanced Settings -> Identiy -> Edit.

Here is selected the built in account, named ApplicationPoolIdentity. You must select CustomAccount -> enter your account credentials (the account of the current machine that you are on).

There is one step left: go to Environment Variables -> Add to the PATH the path of the /bin directory where libargon.dll (the unmanaged dll) is located.

Now it should work flawlessly.

My Configuration:

-> Visual Studio 2015 V14.0.25123.00 Update 2 -> Windows 10 Pro 64-bit, Build 14393 -> IIS Version 10.0.14393.0

Another workaround: if you don't want to spend time configuring the IIS (although there are simple configurations) you can copy your unmanaged dll into C:\Windows\SysWOW64 without making any changes to the PATH or to the IIS. This should work too.

Thank you respectfully,

Cosmin Ionita

jwbats commented 8 years ago

@alipha Thanks for the clarifying feedback. I learned a lot from this. I wasn't aware that the PasswordHasher was capable of generating a salt for me.

However, I don't see how a pepper will obscure the resulting hash. You are using the pepper like I would use a manual salt ("mypassword" + pepper). The result of this is just a string that is hashed and yields a parametered argon2 hash string.

I am currently using UrlTokenEncode to encode my randomly generated bytes and whatnot. It's handy for sending account verification strings along in a URL.

Not sure if it would add significant time for a hacker to get to my passwords if I use this encoding on my argon2 hashes. And like you said, it's handy having the information there. A hacker would still have to invest significant amounts of time to crack'em one by one.

alipha commented 8 years ago

@jwbats With a salt, the salt is stored with the password hash so that you can have a unique salt per user. With a pepper, it's one random blob that's the same for all users that is hidden somewhere away from the database that hopefully an attacker won't be able to find.

jwbats commented 8 years ago

Now it all makes sense. I looked up some more info regarding the pepper. The approved answer in this thread makes it pretty clear. Thanks again!

johnstaveley commented 7 years ago

I get "System.DllNotFoundException: Unable to load DLL 'libargon2.dll': The specified module could not be found" when running tests using this on my TeamCIty build server.

Is there any other way of solving this other than sticking the dll in the path? I thought .Net checked the local directory first (which is where libargon2.dll can be found). There must be a way of allowing a solution to see an unmanaged dll. I have in the same directory as the build and tests which are being run but apparently TeamCity still can't see them. Sticking libargon2.dll into the path seems a rather nasty hack. I've read somewhere that the dll is copied to a temporary folder location first which is why I get the Unable to load DLL error above, putting it in the path would fix that but it is not the underlying problem as libargon2.dll can be found everywhere the NuGet package (I'm using 1.0.5) dlls are being used.

jwbats commented 7 years ago

Having no compiler errors isn't good enough. The package must be installed in all projects that make use of it. If you require the dll yet elsewhere, then you'll have to find a way to get it there.

On Thu, Dec 15, 2016 at 11:45 AM, John Staveley notifications@github.com wrote:

I get "System.DllNotFoundException: Unable to load DLL 'libargon2.dll': The specified module could not be found" when running tests using this on my TeamCIty build server.

Is there any other way of solving this other than sticking the dll in the path? I thought .Net checked the local directory first (which is where libargon2.dll can be found). There must be a way of allowing a solution to see an unmanaged dll. I have in the same directory as the build and tests which are being run but apparently TeamCity still can't see them. Sticking libargon2.dll into the path seems a rather nasty hack. I've read somewhere that the dll is copied to a temporary folder location first which is why I get the Unable to load DLL error above, putting it in the path would fix that but it is not the underlying problem as libargon2.dll can be found everywhere the NuGet package (I'm using 1.0.5) dlls are being used.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/alipha/csharp-argon2/issues/2#issuecomment-267297306, or mute the thread https://github.com/notifications/unsubscribe-auth/AL9zgBi0t2EYsRU5bPdwccSiukf4LdiDks5rIRpDgaJpZM4JuJE4 .

johnstaveley commented 7 years ago

It is installed in the test project which runs fine locally but fails on the CI server. Despite the fact the libargon2.dll being present in the same directory as the test code which is being executed

jwbats commented 7 years ago

You're sure the CI build isn't trying to get its dll files from somewhere else?

On Thu, Dec 15, 2016 at 11:58 AM, John Staveley notifications@github.com wrote:

It is installed in the test project which runs fine locally but fails on the CI server. Despite the fact the libargon2.dll being present in the same directory as the test code which is being executed

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/alipha/csharp-argon2/issues/2#issuecomment-267299923, or mute the thread https://github.com/notifications/unsubscribe-auth/AL9zgH0Eo2ztxZtDD1FlJlH4rx6y4tMwks5rIR1XgaJpZM4JuJE4 .

johnstaveley commented 7 years ago
The articles I've read on it seem to suggest that even though the
  dll is local because it is unmanaged the managed .Net code can't
  'see' it, hence the 'add it to the path, everything miraculously
  works' solution.
The dlls don't exist anywhere else on the build server as far as
  I am aware, you build them Just in time for the purpose for which
  you want them, in this case running tests.

On 15/12/2016 12:00, jwbats wrote:

You're sure the CI build isn't trying to get its dll
  files from somewhere
  else?

  On Thu, Dec 15, 2016 at 11:58 AM, John Staveley
  <notifications@github.com>
  wrote:

  > It is installed in the test project which runs fine locally
  but fails on
  > the CI server. Despite the fact the libargon2.dll being
  present in the same
  > directory as the test code which is being executed
  >
  > —
  > You are receiving this because you were mentioned.
  > Reply to this email directly, view it on GitHub
  >

https://github.com/alipha/csharp-argon2/issues/2#issuecomment-267299923,

or mute the thread

https://github.com/notifications/unsubscribe-auth/AL9zgH0Eo2ztxZtDD1FlJlH4rx6y4tMwks5rIR1XgaJpZM4JuJE4 .

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

  {"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/alipha/csharp-argon2","title":"alipha/csharp-argon2","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/alipha/csharp-argon2"}},"updates":{"snippets":[{"icon":"PERSON","message":"@jwbats in #2: You're sure the CI build isn't trying to get its dll files from somewhere\nelse?\n\nOn Thu, Dec 15, 2016 at 11:58 AM, John Staveley \u003cnotifications@github.com\u003e\nwrote:\n\n\u003e It is installed in the test project which runs fine locally but fails on\n\u003e the CI server. Despite the fact the libargon2.dll being present in the same\n\u003e directory as the test code which is being executed\n\u003e\n\u003e —\n\u003e You are receiving this because you were mentioned.\n\u003e Reply to this email directly, view it on GitHub\n\u003e \u003chttps://github.com/alipha/csharp-argon2/issues/2#issuecomment-267299923\u003e,\n\u003e or mute the thread\n\u003e \u003chttps://github.com/notifications/unsubscribe-auth/AL9zgH0Eo2ztxZtDD1FlJlH4rx6y4tMwks5rIR1XgaJpZM4JuJE4\u003e\n\u003e .\n\u003e\n"}],"action":{"name":"View Issue","url":"https://github.com/alipha/csharp-argon2/issues/2#issuecomment-267311394"}}}

-- 

John Staveley CITP MBCS MPhil MEng DipM ACGI Mobile +44 (0) 788 066 4824 LinkedIn https://www.linkedin.com/in/johnstaveley Web http://www.staveley.org Skype GembaKaizen

kunalkakkad commented 7 years ago

@cosmin-ionita I am facing the issue over 3rd party hosting server where I am having shared hosting. So how can I handle the same?