dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.54k stars 4.54k forks source link

Add Bcrypt password hashing #98823

Open yhojann-cl opened 6 months ago

yhojann-cl commented 6 months ago

Is there an existing issue for this?

Is your feature request related to a problem? Please describe the problem.

Secure hashing password using a good standard and compatibility with other technologies and databases, like as org.springframework.security.crypto.bcrypt for Java.

Describe the solution you'd like

Add a native component for Bcrypt hashing, by example to the system.security.cryptography component.

Additional context

No response

danmoseley commented 6 months ago

Should this be in dotnet/runtime?

danmoseley commented 6 months ago

@vcsjones ?

bartonjs commented 6 months ago

Since the request seems to be for the algorithm primitive, vs hooking it up to something like the ASP.NET membership identity provider (if that still exists?); it'd be an issue for dotnet/runtime, yes.

We've had a couple of issues mention it in the past https://github.com/dotnet/runtime/issues/39922, https://github.com/dotnet/runtime/issues/15936; but it hasn't ever reached critical mass for implementation. BCrypt is a hash algorithm, and so it would come under our "we don't implement cryptographic algorithms, but instead defer to an OS implementation" policy. Windows doesn't have/expose it (last I checked), and so it'd probably have a static IsSupported that would only return true on the platforms where we use OpenSSL (I'm not sure about macOS/iOS/Android).

So, it's not "no", but it's also not "yes".

Since we don't have an active issue for it, we could transfer this one over and see how much support it garners...

bartonjs commented 6 months ago

and so it'd probably have a static IsSupported that would only return true on the platforms where we use OpenSSL

Actually, I seem to have misremembered OpenSSL's support for BCrypt... they don't, and won't: https://github.com/openssl/openssl/issues/5323.

Since it's a cryptographic algorithm, and it doesn't appear in the libraries we depend on, it's a "no" from the runtime perspective (until/unless things change).

yhojann-cl commented 5 months ago

I understand that a component dedicated to WEB technology developments does not include functionalities that are not exclusive for the use of WEB solutions, but in practice a WEB site always requires encryption components that are specific and recommended for technologies and standards that are used in WEB sites, as defined here:

For example, a WEB framework should have native cryptographic mechanisms for session management via JWT, by example, System.IdentityModel.Tokens.Jwt should be part of the aspnet or .net 8 component instead of system core, the same for bcrypt and password hashing.

I think this can be derived from two questions:

Depending on each answer, you would have to ask yourself, for example, why the JWT management component (System.IdentityModel.Tokens.Jwt) is located in the .net and not in Aspnet.

In any case, whatever the case, Bcrypt should be an encryption method that can be brought to .net without the need for third-party components, thus avoiding poor implementation and security problems.

I understand that .net uses System.Security.Cryptography along with Rfc2898DeriveBytes to simulate a Bcrypt hash, but it is not really Bcrypt, but rather PBKDF2. It may be very secure but Bcrypt is by default the algorithm with the best compatibility between different technologies, especially when working in microservices where a data is not from a language but from a project as a whole, in this case .net is far behind in Compatibility issues for large atomic projects.

For this reason I believe that, whether in .net or aspnet, this encryption method should exist.

ghost commented 4 months ago

Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones See info in area-owners.md if you want to be subscribed.

Issue Details
### Is there an existing issue for this? - [X] I have searched the existing issues ### Is your feature request related to a problem? Please describe the problem. Secure hashing password using a good standard and compatibility with other technologies and databases, like as `org.springframework.security.crypto.bcrypt` for Java. ### Describe the solution you'd like Add a native component for Bcrypt hashing, by example to the `system.security.cryptography` component. ### Additional context _No response_
Author: yhojann-cl
Assignees: -
Labels: `area-System.Security`, `untriaged`
Milestone: -
bartonjs commented 3 months ago

As described prior to the issue transfer: neither Windows nor OpenSSL provide an implementation of the BCrypt algorithm. BCrypt may be functionally available on Linux via calling crypt(3), but it's not guaranteed, only works for null-terminated string inputs, and may have length limitations... so it's not ideal to depend on for a generalized API (though maybe the 72-character input is a limitation of the algorithm itself?). Even if we did want to depend on it, our usual rule is that we don't do cryptographic algorithms unless we have them on both Windows and Linux; and there's no answer on Windows.

vcsjones commented 3 months ago

crypt(3) is not suitable.

ugh maybe the 72-character input is a limitation of the algorithm itself?

It's a 72-byte limit, but yes the algorithm does not support more than "hashing" 72 bytes.

there's no answer on Windows.

I do not believe there is a suitable answer on Linux, either. A number of Linux distributions do not support it.

bgermann commented 1 month ago

Windows exports bcrypt and the right OpenSSL issue to watch is https://github.com/openssl/openssl/issues/16447 (the previously referenced one asks for bcrypt-pbkdf).

vcsjones commented 1 month ago

Windows exports bcrypt

That is unfortunately a name collision. bcrypt is the name of Windows’ CNG primitives library. BCrypt-the-library in Win32 does not actually implement bcrypt-the-hash.

yhojann-cl commented 3 weeks ago

As described prior to the issue transfer: neither Windows nor OpenSSL provide an implementation of the BCrypt algorithm. BCrypt may be functionally available on Linux via calling crypt(3), but it's not guaranteed, only works for null-terminated string inputs, and may have length limitations... so it's not ideal to depend on for a generalized API (though maybe the 72-character input is a limitation of the algorithm itself?). Even if we did want to depend on it, our usual rule is that we don't do cryptographic algorithms unless we have them on both Windows and Linux; and there's no answer on Windows.

I think that .net should be agnostic to the Windows core, firstly due to its portability on other systems being multiplatform, if .net always depended on what Windows does that means that the speed of .NET in technological innovation would depend on Windows and on Most of the time it is always delayed, causing problems like this, the same would happen the other way around, if Windows implements something new that Linux does not yet have, such as the management of the RDP protocol.

I understand that .NET has strict work policies and I am not going to argue with it, but I think it would be a better idea to create your own implementation within .NET without the need to resort to external libraries since it would also be affected by third-party vulnerabilities, or at least for implementations where there is no consensus between different systems, as is the case with Bcrypt.

The idea of ​​using a cross-platform development framework is that it is system agnostic, not integrated into the system, like Java, NodeJS, Ruby ​​or Python. In some cases Openssl is responsible for managing some algorithms at a lower level but not in all of them.

If we have to wait for the implementation of Bcrypt in Windows we will probably have to wait many years and probably at that time another algorithm will replace it, something similar to the implementation of ssh-keygen in Windows natively, when in linux decided to implement it the use of default ecdsa keys to replace rsa that windows is recently implementing.

bgermann commented 3 weeks ago

If you just want a cryptographic primitive to be available that can be used as a password hash and is available on the mentioned crypto frameworks, I suggest to go with PBKDF2.