Hashing with SHA1 Algorithm in C#

163,441

Solution 1

For those who want a "standard" text formatting of the hash, you can use something like the following:

static string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            // can be "x2" if you want lowercase
            sb.Append(b.ToString("X2"));
        }

        return sb.ToString();
    }
}

This will produce a hash like 0C2E99D0949684278C30B9369B82638E1CEAD415.

Or for a code golfed version:

static string Hash(string input)
{
    var hash = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input));
    return string.Concat(hash.Select(b => b.ToString("x2")));
}

For .Net 5 and above, the built-in Convert.ToHexString gives a nice solution with no compromises:

static string Hash(string input)
{
    using var sha1 = SHA1.Create();
    return Convert.ToHexString(sha1.ComputeHash(Encoding.UTF8.GetBytes(input)));
}

Solution 2

public string Hash(byte [] temp)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(temp);
        return Convert.ToBase64String(hash);
    }
}

EDIT:

You could also specify the encoding when converting the byte array to string as follows:

return System.Text.Encoding.UTF8.GetString(hash);

or

return System.Text.Encoding.Unicode.GetString(hash);

Solution 3

This is what I went with. For those of you who want to optimize, check out https://stackoverflow.com/a/624379/991863.

    public static string Hash(string stringToHash)
    {
        using (var sha1 = new SHA1Managed())
        {
            return BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(stringToHash)));
        }
    }

Solution 4

Fastest way is this :

    public static string GetHash(string input)
    {
        return string.Join("", (new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input))).Select(x => x.ToString("X2")).ToArray());
    }

For Small character output use x2 in replace of of X2

Solution 5

You can "compute the value for the specified byte array" using ComputeHash:

var hash = sha1.ComputeHash(temp);

If you want to analyse the result in string representation, then you will need to format the bytes using the {0:X2} format specifier.

Share:
163,441
Merve Kaya
Author by

Merve Kaya

Updated on July 08, 2022

Comments

  • Merve Kaya
    Merve Kaya almost 2 years

    I want to hash given byte[] array with using SHA1 Algorithm with the use of SHA1Managed.
    The byte[] hash will come from unit test.
    Expected hash is 0d71ee4472658cd5874c5578410a9d8611fc9aef (case sensitive).

    How can I achieve this?

    public string Hash(byte [] temp)
    {
        using (SHA1Managed sha1 = new SHA1Managed())
        {
    
        }
    }
    
  • Rich
    Rich about 11 years
    If they want a hex string then Base64 is probably the wrong choice.
  • John Gathogo
    John Gathogo about 11 years
    @Joey: Against the answer given by GrantThomas, the member indicated that they need to return a string
  • John Gathogo
    John Gathogo about 11 years
    @MerveKaya: Perhaps you should explain what you mean by "it didnt work". What does the incoming byte array represent? How did you determine "SHA1Managed"-hashing the incoming byte array should give you 0d71ee4472658cd5874c5578410a9d8611fc9aef as the output?
  • Merve Kaya
    Merve Kaya about 11 years
    Byte[] hash comes from unit test. In the question they wrote that expected hash is 0d71ee4472658cd5874c5578410a9d8611fc9aef. It comes from unit test
  • John Gathogo
    John Gathogo about 11 years
    @MerveKaya: See my update on how to use Encoding when converting the hash to a string
  • Merve Kaya
    Merve Kaya about 11 years
    No, unfortunately it failed again
  • sky-dev
    sky-dev over 8 years
    It bugs me that this solution doesn't dispose the SHA1Managed object, because it is marked as Disposable. This post could be handy when optimizing: stackoverflow.com/a/624379/991863
  • kshitij Sabale
    kshitij Sabale over 8 years
    @sky-dev, I usually agree with IDisposable, but a quick trip to the reference source shows that nothing interesting happens in .Dispose()
  • sky-dev
    sky-dev over 8 years
    Yeah, I looked at the Dispose implementation as well. It would just speed GarbageCollection a tad. It probably isn't a big deal in the grand scheme of things.
  • unenthusiasticuser
    unenthusiasticuser over 7 years
    @Mitch If it implements the IDisposable interface then what happens in the reference source shouldn't matter. Should they ever change it for any reason such that the .Dispose() call becomes important, your previously working code is now causing a problem. Relying on looking into the bowels of a framework to determine what you can get away with is a path to a maintenance nightmare. I highly suggest following the documentation and correctly handling disposable objects, it'll save you pain in the long term.
  • kshitij Sabale
    kshitij Sabale over 7 years
    @unenthusiastic use, Haha, thanks. I wasn't sure what the purpose of documentation was... (The code in my production applications is the one from the top, but the circumstances of the second make me comfortable enough that it would be equally supportable in all but the tightest loops. IDisposable is semi-optional when dealing with non-side-effecting classes.)
  • rickythefox
    rickythefox about 7 years
    SHA1Managed implements IDisposable, so you would probably want to dispose it when done with it to free up resources.
  • Sam
    Sam almost 6 years
    I had to use BitConverter.ToString(sha1.ComputeHash(bytes)).Replace("-", "") since I didn't want the dashes introduced by BitConverter. After that it worked like a charm! Thanks!
  • Vince
    Vince almost 6 years
    just because something is IDisposable doesn't mean you should call Dispose() on it. source: I've done server-side SharePoint development.
  • aloisdg
    aloisdg over 5 years
    For the second version, you can also replace the select + concat logic with aggregate: new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input)).Agg‌​regate(string.Empty, (x, y) => x + y.ToString("x2"))
  • ijt
    ijt almost 4 years
    What is the "X2" for?
  • kshitij Sabale
    kshitij Sabale almost 4 years
    @ijt, X2 tells it to use two hexadecimal digits per byte. x2 means lowercase, X2 is uppercase
  • Joey Adams
    Joey Adams almost 4 years
    If you need to support machines set to FIPS 140-2 compliance, replace SHA1Managed with SHA1CryptoServiceProvider instead (but keep the rest the same). But to future-proof your code, use a stronger hashing algorithm. Even if your use case is not security-sensitive, these methods can be disabled through system policy.
  • kshitij Sabale
    kshitij Sabale almost 4 years
    @JoeyAdams, sure. That is only needed for .Net 2 through .Net 4.7.2, though. .Net 4.8 make the change automatically for you (Managed cryptography classes do not throw a CryptographyException in FIPS mode)
  • Joey Adams
    Joey Adams almost 4 years
    @Mitch: Thanks for the refinement. Though this only applies if the application targets .NET 4.8, or if the app config uses UseLegacyFipsThrow=false as described in your link.
  • quetzalcoatl
    quetzalcoatl almost 3 years
    It's not the fastest way, it's merely packed into a single line.
  • alireza amini
    alireza amini almost 3 years
    @quetzalcoatl well, yeah :)