56

I am trying to write a function to take a string and sha512 it like so?

public string SHA512(string input)
{
     string hash;

     ~magic~

     return hash;
}

What should the magic be?

James
  • 28,499
  • 18
  • 82
  • 110

11 Answers11

87

Your code is correct, but you should dispose of the SHA512Managed instance:

using (SHA512 shaM = new SHA512Managed())
{
   hash = shaM.ComputeHash(data);
}

512 bits are 64 bytes.

To convert a string to a byte array, you need to specify an encoding. UTF8 is okay if you want to create a hash code:

var data = Encoding.UTF8.GetBytes("text");    
using (...
AlG
  • 14,097
  • 4
  • 41
  • 53
Carsten Schütte
  • 4,138
  • 1
  • 19
  • 24
  • 16
    The number of examples that don't utilize dispose in any fashion whatsoever is astounding. Kudos for showing the idiomatic manner with `using`. – Jesse C. Slicer Jul 06 '12 at 18:36
  • 4
    Instead of `var data = Encoding.UTF8.GetByteCount(foo)`, use `var data = Encoding.UTF8.GetBytes(foo)`. – luiscubal Jul 06 '12 at 20:52
  • 1
    Why do you need the "using" clause? Won't the default C# garbage collection kick in and get rid of the shaM variable? Why is explicit garbage collection like this necessary? – alpsystems.com Nov 29 '15 at 10:44
  • 7
    Do not mix up carbage collection and freeing/disposing unused unmanaged objects. Using "using" makes sure that Dispose is called when the using block ends. This will release unmanaged resources - otherwise they will be released when the GC cleans up the object (and calls the finalizer internally). The class SHA512Managed is disposable, so I prefer to use using. For more information about the Dispose pattern, take a look at https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx – Carsten Schütte Dec 29 '15 at 15:27
  • In .NET 6 it throws warning `Warning SYSLIB0021 'SHA512Managed' is obsolete: 'Derived cryptographic types are obsolete. Use the Create method on the base type instead.'` How to use this in .NET 6 ? There is separate question in https://stackoverflow.com/questions/70109573/how-to-calculate-sha-512-hash-properly-in-net-6 – Andrus Nov 25 '21 at 10:36
40

This is from one of my projects:

public static string SHA512(string input)
{
    var bytes = System.Text.Encoding.UTF8.GetBytes(input);
    using (var hash = System.Security.Cryptography.SHA512.Create())
    {
        var hashedInputBytes = hash.ComputeHash(bytes);

        // Convert to text
        // StringBuilder Capacity is 128, because 512 bits / 8 bits in byte * 2 symbols for byte 
        var hashedInputStringBuilder = new System.Text.StringBuilder(128);
        foreach (var b in hashedInputBytes)
            hashedInputStringBuilder.Append(b.ToString("X2"));
        return hashedInputStringBuilder.ToString();
    }
}

Please, note:

  1. SHA512 object is disposed ('using' section), so we do not have any resource leaks.
  2. StringBuilder is used for efficient hex string building.
Nazar
  • 574
  • 5
  • 7
  • 8
    The StringBuilder code can be replaced by a single line   ‘var hash = BitConverter.ToString(hashedInputBytes).Replace("-", "");’ https://msdn.microsoft.com/en-us/library/system.bitconverter.tostring(v=vs.110).aspx – Michael Freidgeim Apr 13 '18 at 21:09
8

512/8 = 64, so 64 is indeed the correct size. Perhaps you want to convert it to hexadecimal after the SHA512 algorithm.

See also: How do you convert Byte Array to Hexadecimal String, and vice versa?

Community
  • 1
  • 1
luiscubal
  • 24,243
  • 9
  • 55
  • 82
  • Yes, you are absolutely right. I just used an online generator to compare against, which made hex. Thanks :) – James Jul 06 '12 at 18:33
  • The link does not convert a string to a byte array, it converts hex string to bytes. To convert a string to a byte array, use something like `Encoding.UTF8.GetByteCount("text")` – Carsten Schütte Jul 06 '12 at 18:38
  • @CarstenSchütte Well, UTF-8 is for text encoding, which is not related to this question. And either way, GetByteCount wouldn't convert the string to a byte array. It'd only get the *length* of the byte array. – luiscubal Jul 06 '12 at 18:51
  • @CarstenSchütte Oh, wait. I think I know what you meant. You're talking about obtaining the initial "data" variable, right? In that case, yes, UTF-8 is fine. Still, GetByteCount is still not the appropriate function. – luiscubal Jul 06 '12 at 20:51
  • @luiscubal: Sorry, GetByteCount was my fault (and copy/paste error). Of course you need to use GetBytes() to get the data. – Carsten Schütte Jan 18 '14 at 21:50
2

Instead of WinCrypt-API using System.Security.Cryptography, you can also use BouncyCastle:

public static byte[] SHA512(string text)
{
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes(text);

    Org.BouncyCastle.Crypto.Digests.Sha512Digest digester = new Org.BouncyCastle.Crypto.Digests.Sha512Digest();
    byte[] retValue = new byte[digester.GetDigestSize()];
    digester.BlockUpdate(bytes, 0, bytes.Length);
    digester.DoFinal(retValue, 0);
    return retValue;
}

If you need the HMAC-version (to add authentication to the hash)

public static byte[] HmacSha512(string text, string key)
{
    byte[] bytes = Encoding.UTF8.GetBytes(text);

    var hmac = new Org.BouncyCastle.Crypto.Macs.HMac(new Org.BouncyCastle.Crypto.Digests.Sha512Digest());
    hmac.Init(new Org.BouncyCastle.Crypto.Parameters.KeyParameter(System.Text.Encoding.UTF8.GetBytes(key)));

    byte[] result = new byte[hmac.GetMacSize()];
    hmac.BlockUpdate(bytes, 0, bytes.Length);
    hmac.DoFinal(result, 0);

    return result;
}
Stefan Steiger
  • 73,615
  • 63
  • 359
  • 429
2

You might try these lines:

public static string GenSHA512(string s, bool l = false)
{
    string r = "";

    try
    {
        byte[] d = Encoding.UTF8.GetBytes(s);

        using (SHA512 a = new SHA512Managed())
        {
            byte[] h = a.ComputeHash(d);
            r = BitConverter.ToString(h).Replace("-", "");
        }

        r = (l ? r.ToLowerInvariant() : r);
    }
    catch
    {

    }

    return r;
}
  1. It is disposed at the end
  2. It's safe
  3. Supports lower case
Faither
  • 698
  • 3
  • 14
  • 25
1

I'm not sure why you are expecting 128.

8 bits in a byte. 64 bytes. 8 * 64 = 512 bit hash.

Andrew T Finnell
  • 13,117
  • 2
  • 32
  • 48
1

From the MSDN Documentation:
The hash size for the SHA512Managed algorithm is 512 bits.

Joel Rondeau
  • 7,338
  • 2
  • 40
  • 53
1

You could use the System.Security.Cryptography.SHA512 class

MSDN on SHA512

Here is an example, straigt from the MSDN

byte[] data = new byte[DATA_SIZE];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(data);
Mare Infinitus
  • 7,826
  • 7
  • 57
  • 109
1

Keeping it simple:

using (SHA512 sha512 = new SHA512Managed())
{
    password = Encoding.UTF8.GetString(sha512.ComputeHash(Encoding.UTF8.GetBytes(password)));
}
alansiqueira27
  • 7,413
  • 15
  • 60
  • 104
0
UnicodeEncoding UE = new UnicodeEncoding();            
        byte[] message = UE.GetBytes(password);
        SHA512Managed hashString = new SHA512Managed();
        string hexNumber = "";
        byte[]  hashValue = hashString.ComputeHash(message);
        foreach (byte x in hashValue)
        {
            hexNumber += String.Format("{0:x2}", x);
        }
        string hashData = hexNumber;
Mahesh.P
  • 261
  • 3
  • 4
-1

I used the following

public static string ToSha512(this string inputString)
{
        if (string.IsNullOrWhiteSpace(inputString)) return string.Empty;
        using (SHA512 shaM = new SHA512Managed())
        {
            return Convert.ToBase64String(shaM.ComputeHash(Encoding.UTF8.GetBytes(inputString)));
        }
}
Mohammad Dayyan
  • 20,033
  • 39
  • 154
  • 219