.NET equivalent for php's sha1(sha1("string",true)) [duplicate] - c#

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())
{
}
}

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)));
}

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);

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)));
}
}

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.

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

I'll throw my hat in here:
(as part of a static class, as this snippet is two extensions)
//hex encoding of the hash, in uppercase.
public static string Sha1Hash (this string str)
{
byte[] data = UTF8Encoding.UTF8.GetBytes (str);
data = data.Sha1Hash ();
return BitConverter.ToString (data).Replace ("-", "");
}
// Do the actual hashing
public static byte[] Sha1Hash (this byte[] data)
{
using (SHA1Managed sha1 = new SHA1Managed ()) {
return sha1.ComputeHash (data);
}

Related

How to convert hash function result to string representation properly? [duplicate]

I have some string and I want to hash it with the SHA-256 hash function using C#. I want something like this:
string hashString = sha256_hash("samplestring");
Is there something built into the framework to do this?
The implementation could be like that
public static String sha256_hash(String value) {
StringBuilder Sb = new StringBuilder();
using (SHA256 hash = SHA256Managed.Create()) {
Encoding enc = Encoding.UTF8;
Byte[] result = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in result)
Sb.Append(b.ToString("x2"));
}
return Sb.ToString();
}
Edit: Linq implementation is more concise, but, probably, less readable:
public static String sha256_hash(String value) {
using (SHA256 hash = SHA256Managed.Create()) {
return String.Concat(hash
.ComputeHash(Encoding.UTF8.GetBytes(value))
.Select(item => item.ToString("x2")));
}
}
Edit 2: .NET Core , .NET5, .NET6 ...
public static String sha256_hash(string value)
{
StringBuilder Sb = new StringBuilder();
using (var hash = SHA256.Create())
{
Encoding enc = Encoding.UTF8;
byte[] result = hash.ComputeHash(enc.GetBytes(value));
foreach (byte b in result)
Sb.Append(b.ToString("x2"));
}
return Sb.ToString();
}
From .NET 5 onwards, you can use the new Convert.ToHexString method to convert the hash byte array into a (hex) string without having to use a StringBuilder or .ToString("X0"), etc.:
public static string HashWithSHA256(string value)
{
using var hash = SHA256.Create();
var byteArray = hash.ComputeHash(Encoding.UTF8.GetBytes(value));
return Convert.ToHexString(byteArray);
}
I was looking for an in-line solution, and was able to compile the below from Dmitry's answer:
public static String sha256_hash(string value)
{
return (System.Security.Cryptography.SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes(value))
.Select(item => item.ToString("x2")));
}

c# Base64 Encoding Decoding wrong result

I need to create a hash-signature in c#.
The pseudo-code example that i need to implement in my c# code:
Signatur(Request) = new String(encodeBase64URLCompatible(HMAC-SHA-256(getBytes(Z, "UTF-8"), decodeBase64URLCompatible(getBytes(S, "UTF-8")))), "UTF-8")
Z: apiSecret
S: stringToSign
The coding for expectedSignatur and apiSecret is Base64 URL Encoding [RFC 4648 Section 5]
My problem is that I always get the wrong result.
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
private static byte[] HmacSha256(string data, string key)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
}
}
static void Main(string[] args)
{
var apiSecret = "JrXRHCnUegQJAYSJ5J6OvEuOUOpy2q2-MHPoH_IECRY=";
var stringToSign = "f3fea5f3-60af-496f-ac3e-dbb10924e87a:20160201094942:e81d298b-60dd-4f46-9ec9-1dbc72f5b5df:Qg5f0Q3ly1Cwh5M9zcw57jwHI_HPoKbjdHLurXGpPg0yazdC6OWPpwnYi22bnB6S";
var expectedSignatur = "ps9MooGiTeTXIkPkUWbHG4rlF3wuTJuZ9qcMe-Y41xE=";
apiSecret = apiSecret.Replace('-', '+').Replace('_', '/').PadRight(apiSecret.Length + (4 - apiSecret.Length % 4) % 4, '=');
var secretBase64Decoded = Base64Decode(apiSecret);
var hmac = Convert.ToBase64String(HmacSha256(secretBase64Decoded, stringToSign));
var signatur = hmac.Replace('+', '-').Replace('/', '_');
Console.WriteLine($"signatur: {signatur}");
Console.WriteLine($"expected: {expectedSignatur}");
Console.WriteLine(signatur.Equals(expectedSignatur));
Console.ReadLine();
}
You're assuming that your key was originally text encoded with UTF-8 - but it looks like it wasn't. You should keep logically binary data as binary data - you don't need your Base64Encode and Base64Decode methods at all. Instead, your HmacSha256 method should take a byte[] as a key, and you can just use Convert.FromBase64String to get at those bytes from the base64-encoded secret:
using System;
using System.Text;
using System.Security.Cryptography;
class Test
{
private static byte[] HmacSha256(byte[] key, string data)
{
using (var hmac = new HMACSHA256(key))
{
return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
}
}
static void Main(string[] args)
{
var apiSecret = "JrXRHCnUegQJAYSJ5J6OvEuOUOpy2q2-MHPoH_IECRY=";
var stringToSign = "f3fea5f3-60af-496f-ac3e-dbb10924e87a:20160201094942:e81d298b-60dd-4f46-9ec9-1dbc72f5b5df:Qg5f0Q3ly1Cwh5M9zcw57jwHI_HPoKbjdHLurXGpPg0yazdC6OWPpwnYi22bnB6S";
var expectedSignatur = "ps9MooGiTeTXIkPkUWbHG4rlF3wuTJuZ9qcMe-Y41xE=";
apiSecret = apiSecret.Replace('-', '+').Replace('_', '/').PadRight(apiSecret.Length + (4 - apiSecret.Length % 4) % 4, '=');
var secretBase64Decoded = Convert.FromBase64String(apiSecret);
var hmac = Convert.ToBase64String(HmacSha256(secretBase64Decoded, stringToSign));
var signatur = hmac.Replace('+', '-').Replace('/', '_');
Console.WriteLine($"signatur: {signatur}");
Console.WriteLine($"expected: {expectedSignatur}");
Console.WriteLine(signatur.Equals(expectedSignatur));
}
}
Personally I'd change your HmacSha256 method to:
private static byte[] ComputeHmacSha256Hash(byte[] key, byte[] data)
{
using (var hmac = new HMACSHA256(key))
{
return hmac.ComputeHash(data);
}
}
so that it's more general purpose, maybe adding another method to compute the hash after encoding as UTF-8 for convenience. That way you can sign any data, not just strings.

C# code php equivalent md5 hash

I have this C# code:
public static string Encript(string strData)
{
string hashValue = HashData(strData);
string hexHashData = ConvertStringToHex(hashValue);
return hexHashData;
}
public static string HashData(string textToBeEncripted)
{
//Convert the string to a byte array
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
//Compute the MD5 hash algorithm
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
return System.Text.Encoding.Unicode.GetString(byteHashValue);
}
public static string ConvertStringToHex(string asciiString)
{
string hex = "";
foreach (char c in asciiString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint) System.Convert.ToUInt32(tmp.ToString()));
}
return hex;
}
Here you can see an online version.As you can see for the string "test" I get the output "5c82e9e41c7599f790ef1d774b7e6bf"
And this is what I tried on php side
$a = "test";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a);
echo $a;
But the value of the php code is "c8059e2ec7419f590e79d7f1b774bfe6".Why is not working?
Edit:Looks like the C# code is incorrect and needs to be replaced
The correct MD5 hash for 'test' is '098f6bcd4621d373cade4e832627b4f6' in PHP.
I tested it with this code in C#
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
It will generate the same hash as PHP will, without the 'convert encoding' method you are using.
I believe converting the encoding is what is giving you a different answer, try it without
$a = mb_convert_encoding($a, "UTF-16LE");
The problem is that you are converting the result incorrectly in your C# code. If you put a breakpoint in the code after you call ComputeHash, and examine the value of byteHashValue, you'll see that it's c8059e2e....
Or, just add this code to your ComputeHash method:
Console.WriteLine(BitConverter.ToString(byteHashValue));
I would suggest rewriting your code to be:
public static string Encript(string strData)
{
string hashValue = HashData(strData);
return hashValue;
}
public static string HashData(string textToBeEncripted)
{
//Convert the string to a byte array
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
//Compute the MD5 hash algorithm
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
return BitConverter.ToString(byteHashValue).Replace("-", "");
}
Oh, and a side note: the word is "Encrypt," not "Encript."
The problem in your case is not the encoding, but your conversion to string on the C# side. As long as you use the same encoding everywhere, it should work as expected. But note, that most of the online hashers use ASCII encoding, whereas you use System.Text.Encoding.Unicode which is UTF-16, thus the results will differ from the online encoders.
The code below will give the same result as your PHP snippet (ie c8059e2ec7419f590e79d7f1b774bfe6)
public static void Main(string[] args)
{
string a = "test";
string en = HashData(a);
Console.WriteLine(en);
}
public static string HashData(string textToBeEncripted)
{
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (var b in byteHashValue)
s.Append(b.ToString("x2"));
return s.ToString();
}
If you use System.Text.Encoding.ASCII instead, you will get 098f6bcd4621d373cade4e832627b4f6 as suggested in other answers. But then you'll have to use ASCII encoding in your PHP code as well.
This is because with UTF16 every character is represented by two bytes, and not only by one. Thus the byteDataToHash will have twice the size ([116, 0, 101, 0, 115, 0, 116, 0] vs [116, 101, 115, 116] in your case). And a different bytevector of course leads to a different hashvalue. But as said above, as long as all included components use the same encoding, it does not really matter which one you use.

Hashing with SHA1 Algorithm in C#

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())
{
}
}
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)));
}
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);
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)));
}
}
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.
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
I'll throw my hat in here:
(as part of a static class, as this snippet is two extensions)
//hex encoding of the hash, in uppercase.
public static string Sha1Hash (this string str)
{
byte[] data = UTF8Encoding.UTF8.GetBytes (str);
data = data.Sha1Hash ();
return BitConverter.ToString (data).Replace ("-", "");
}
// Do the actual hashing
public static byte[] Sha1Hash (this byte[] data)
{
using (SHA1Managed sha1 = new SHA1Managed ()) {
return sha1.ComputeHash (data);
}

C# SHA-2 (512) Base64 encoded hash

Looking for a way to do the following in C# from a string.
public static String sha512Hex(byte[] data)
Calculates the SHA-512 digest and returns the value as a hex string.
Parameters:
data - Data to digest
Returns:
SHA-512 digest as a hex string
private static string GetSHA512(string text)
{
UnicodeEncoding UE = new UnicodeEncoding();
byte[] hashValue;
byte[] message = UE.GetBytes(text);
SHA512Managed hashString = new SHA512Managed();
string encodedData = Convert.ToBase64String(message);
string hex = "";
hashValue = hashString.ComputeHash(UE.GetBytes(encodedData));
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
return hex;
}
Would System.Security.Cryptography.SHA512 be what you need?
var alg = SHA512.Create();
alg.ComputeHash(Encoding.UTF8.GetBytes("test"));
BitConverter.ToString(alg.Hash).Dump();
Executed in LINQPad produces:
EE-26-B0-DD-4A-F7-E7-49-AA-1A-8E-E3-C1-0A-E9-92-3F-61-89-80-77-2E-47-3F-88-19-A5-D4-94-0E-0D-B2-7A-C1-85-F8-A0-E1-D5-F8-4F-88-BC-88-7F-D6-7B-14-37-32-C3-04-CC-5F-A9-AD-8E-6F-57-F5-00-28-A8-FF
To create the method from your question:
public static string sha512Hex(byte[] data)
{
using (var alg = SHA512.Create())
{
alg.ComputeHash(data);
return BitConverter.ToString(alg.Hash);
}
}
Got this to work. Taken from here and modified a bit.
public static string CreateSHAHash(string Phrase)
{
SHA512Managed HashTool = new SHA512Managed();
Byte[] PhraseAsByte = System.Text.Encoding.UTF8.GetBytes(string.Concat(Phrase));
Byte[] EncryptedBytes = HashTool.ComputeHash(PhraseAsByte);
HashTool.Clear();
return Convert.ToBase64String(EncryptedBytes);
}
Better memory management:
public static string SHA512Hash(string value)
{
byte[] encryptedBytes;
using (var hashTool = new SHA512Managed())
{
encryptedBytes = hashTool.ComputeHash(System.Text.Encoding.UTF8.GetBytes(string.Concat(value)));
hashTool.Clear();
}
return Convert.ToBase64String(encryptedBytes);
}

Categories