13

I need to import a bunch of user accounts Moodle into a system written in c#.

Moodle uses password_hash() function to create hashes of passwords. I need to be able to verify these passwords in c#.

In other words I looking for a c# implementation of PHP's password verify function ( http://www.php.net/manual/en/function.password-verify.php ).

I've googled a bit but couldn't really find anything close, so I am asking in hopes of avoiding reinventing the wheel :-)

Thanks!

Filip
  • 681
  • 7
  • 19

2 Answers2

19

Got it!

First install CryptSharp via NuGet Package. (Use the 2.0 "official" package), and by the way, BCrypt.net didn't work for me.

Then:

using CryptSharp;
bool matches = Crypter.CheckPassword("password goes here", "hash goes here");

Note that hash should start with something like: "$2y$..."

Works like a charm! :-)

Dwza
  • 6,494
  • 6
  • 41
  • 73
Filip
  • 681
  • 7
  • 19
  • Can you please provide a link for this useful .NET BCrypt implementation? – Anti-weakpasswords Mar 25 '14 at 02:33
  • http://www.zer7.com/software/cryptsharp is the one I used. It is also easy to install via NuGet Package Manager. – Filip Mar 25 '14 at 10:21
  • Man I was really hoping this was going to do the trick for me. I was trying this and I always get false back. Did some searching and found your post so wondering why it is not working. The has starts with "$2y$". I pulled version 2.1.0 off NuGet. what am I missing? – ToddB Aug 08 '15 at 19:20
  • 1
    This isn't quite identical. [Martin Steel's BCrypt.NET fork](https://github.com/martinsteel/Bcrypt.NET) compares bcrypt hashes in constant time, CryptSharp doesn't [yet](https://github.com/ChrisMcKee/cryptsharp/pull/5). – Scott Arciszewski Mar 01 '16 at 05:32
  • just used CryptSharpOfficial of the same link @Filip provided, v2.10 still and it still works. – Chad Oct 30 '19 at 19:39
  • BCrypt.net didn't work for me << this comment just make me glad that not only me having difficulties to hash between php and c# – aswzen Jan 04 '20 at 19:06
  • So, using `CryptSharp`, I would be able to compare a string with a password hashed with `password_hash`? – Momoro Feb 08 '20 at 19:56
  • CryptSharp hasn't been updated since 2014 – bstras21 Sep 02 '21 at 14:46
-4

Well i know you don't want to write a code for it, .Net has a built in Cryptography library that computes the hash and encrypts it. You have to use it by importing Security.Cryptography. You can compare the result with the one saved in your DB. Here's the code.

class Program
{
    static int SaltValueSize = 8;
    static void Main(string[] args)
    {
        string pass = "Password";
        string result = ComputeHash(pass, new MD5CryptoServiceProvider());
        Console.WriteLine("Original: " + pass + "\nEncrypted: " + result);
        Console.WriteLine("Is user valid: " + IsUserValid("UserName", pass));
        Console.WriteLine("With Salt, Original: " + pass + "\nEcrypted: " + System.Text.Encoding.Default.GetString(ComputePasswordHash(pass, salted)));
        Console.ReadLine();

    }
    private static byte[] ComputePasswordHash(string password, int salt)
    {
        byte[] saltBytes = new byte[4];
        saltBytes[0] = (byte)(salt >> 24);
        saltBytes[1] = (byte)(salt >> 16);
        saltBytes[2] = (byte)(salt >> 8);
        saltBytes[3] = (byte)(salt);

        byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(password);

        byte[] preHashed = new byte[saltBytes.Length + passwordBytes.Length];
        System.Buffer.BlockCopy(passwordBytes, 0, preHashed, 0, passwordBytes.Length);
        System.Buffer.BlockCopy(saltBytes, 0, preHashed, passwordBytes.Length, saltBytes.Length);

        SHA1 sha1 = SHA1.Create();
        return sha1.ComputeHash(preHashed);
    }


    public static string ComputeHash(string input, HashAlgorithm algorithm)
    {
        Byte[] inputBytes = Encoding.UTF8.GetBytes(input);

        Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);

        return BitConverter.ToString(hashedBytes);
    }

    public static bool IsUserValid(string userName, string password)
    {
        bool isValid;
        string result = VerifyPassword(password);
        // isValid = Your database call in a form of Inverted statement which you
        //can check if the user with the hashed password exists or Not
        return isValid;
    }

    public static string VerifyPassword(string password)
    {
        return ComputeHash(password, new MD5CryptoServiceProvider());
    }


}
AEH
  • 36
  • 5
  • Hi Ahmad! Thanks for trying to help, but you solution will not work. "$2y$" means Blowfish based hashing which MD5CryptoServiceProvider cannot handle. – Filip Mar 24 '14 at 17:50
  • 1
    This is quite bad password hashing. You forgot the salt, and MD5 is far too fast. – CodesInChaos Mar 24 '14 at 19:04
  • This was just a simple way, Filip didn't say anything about salt, i was merely showing him that .Net has a built in library for this. – AEH Mar 24 '14 at 20:10
  • I have added one method with salt – AEH Mar 24 '14 at 20:15
  • 3
    Please do not use MD5 for passwords. Please do not use a single pass (or even a handful of passes) of any given hash function for passwords. Please do read [How to securely hash passwords?](http://security.stackexchange.com/q/211/39623), particularly including Thomas Porrin's comprehensive answer (the short form: use BCrypt, SCrypt, or PBKDF2). [RFC2898DeriveBytes](http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx) is stock .NET (SHA-1), and [Jither wrote SHA-2 PBKDF2 code](https://github.com/Anti-weakpasswords/PBKDF2-CSharp-DeriveBytes-custom-A) – Anti-weakpasswords Mar 25 '14 at 02:32