Author

Topic: Calculating SHA256 of a hex value? (Read 233 times)

legendary
Activity: 3402
Merit: 10424
June 08, 2021, 08:25:16 AM
#13
He could also just pass it through a hex-to-ascii converter first.
But that makes no sense. Why would you change the encoding of a string first before decoding it? You know internally from hex to ASCII it has to be converted to byte[] then to ASCII!
Also ASCII is a 7-bit encoding so you will lose bits and your final byte[] may not be what the initial hex represented.
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
June 08, 2021, 05:11:32 AM
#12
Should I change it to ASCII? Because it returns me the correct hash with UTF8.
Why would you? Your string is not using UT8 or ASCII or Unicode or ... It is using hexadecimal encoding and System.Text.Encoding doesn't have a Hex/Base16 encoder class so you can't use it at all.

He could also just pass it through a hex-to-ascii converter first.
legendary
Activity: 3402
Merit: 10424
June 06, 2021, 11:35:13 PM
#11
Should I change it to ASCII? Because it returns me the correct hash with UTF8.
Why would you? Your string is not using UT8 or ASCII or Unicode or ... It is using hexadecimal encoding and System.Text.Encoding doesn't have a Hex/Base16 encoder class so you can't use it at all.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
June 06, 2021, 03:28:29 PM
#10
Simply call the .ToArray() method on the IEnumerable and you'll get the array!!
Thanks!

I'll let you figure out your mistake in code below:
Should I change it to ASCII? Because it returns me the correct hash with UTF8.
legendary
Activity: 3402
Merit: 10424
June 06, 2021, 01:37:37 PM
#9
SHA256 takes a bytes array, not a byte. I'm not sure what exactly does that line do, but Visual Studio returns me that you can't convert from 'System.Collections.Generic.IEnumerable' to 'byte[]'.
Simply call the .ToArray() method on the IEnumerable and you'll get the array!!

IEnumerable objects are simply arrays that don't yet exist so they don't take up any memory but the code knows how to produce each element so you can "enumerate" them. Calling .ToArray() would do that and you'll get the whole array inside your memory.

I'll let you figure out your mistake in code below:
Quote
byte[] sourceBytes = Encoding.UTF8.GetBytes(compPubKeyHex);
legendary
Activity: 2982
Merit: 2681
Top Crypto Casino
June 06, 2021, 01:33:53 PM
#8
...
Hashing "fffff" as a text is the same as hashing "6666666666" as a hex, because ASCII code for 'f' is 0x66.
So should I firstly convert my hex to text and then to bytes?

If you first convert the hex to text and hash it with UTF8 encoding then the result will be the same as:

And this when I hash it as a hex value:
Code:
b4fabc7e6e75fa4b523cc55f51aa54ab1aa4309c92cc44fcf623ddef756f5391

We can verify with this tool the hash of fffff as hex: https://emn178.github.io/online-tools/sha256.html This is the string that you are looking for if the goal is to hash a Hex string.

fffff as Hex = b4fabc7e6e75fa4b523cc55f51aa54ab1aa4309c92cc44fcf623ddef756f5391
fffff as Text = 99834619b3c160248b69c7f42ba868f945a0ea04cd31cf2f60dc4bc8f7d13b8a

So, here the focus should be about what kind of input you have, since it's a Hex number the right hash is the one starting with b4fab.... This is important because if you want to repeat the process in another part of the code or in some dependencies like SQL, the process to follow was to sha256 a Hex input. And if you hash it as Text and as Hex in different parts of the code it will bring different results and that will break the main principle of the hash "Always you will get the same hash from the same string if they are in the same encoding".
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
June 06, 2021, 08:58:21 AM
#7
Code:
Enumerable.Range(0, hex.Length/2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16));
SHA256 takes a bytes array, not a byte. I'm not sure what exactly does that line do, but Visual Studio returns me that you can't convert from 'System.Collections.Generic.IEnumerable' to 'byte[]'.

It must have something to do with your line here:

Code:
byte[] sourceBytes = Encoding.UTF8.GetBytes(compPubKeyHex);

I'm suspecting your GetBytes() is returning Bytes[] not bytes[] (note the case; bytes is a built-in type, the other is a class). Though I'm not sure if the Bytes[] type is equivalent to that System.Collections.Generic.IEnumerable you're getting errors about, there's a Stack Overflow answer that converts from that IEnumerable to bytes[]:

Code:
byte[] result = r.SelectMany(i => i).ToArray();
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
June 06, 2021, 08:27:19 AM
#6
Simply convert your hex to bytes then use those bytes in SHA256.
But, I do convert my hex to bytes first and then I perform SHA256:
Code:
SHA256 sha256Hash = SHA256.Create();
byte[] sourceBytes = Encoding.UTF8.GetBytes(compPubKeyHex);
byte[] hashBytes = sha256Hash.ComputeHash(sourceBytes);
string hash = BitConverter.ToString(hashBytes).Replace("-", String.Empty);

Code:
Enumerable.Range(0, hex.Length/2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16));
SHA256 takes a bytes array, not a byte. I'm not sure what exactly does that line do, but Visual Studio returns me that you can't convert from 'System.Collections.Generic.IEnumerable' to 'byte[]'.

Hashing "fffff" as a text is the same as hashing "6666666666" as a hex, because ASCII code for 'f' is 0x66.
So should I firstly convert my hex to text and then to bytes?
legendary
Activity: 3402
Merit: 10424
June 05, 2021, 10:51:05 PM
#5
The problem is that I haven't found a way to do that in C#, but only as a text. (using SHA256.Create().ComputeHash(bytes))
It is a very simple matter of an additional step. You simply convert your hex to bytes then use those bytes in SHA256. Converting hex to bytes is very easy too, here is a one line code using LINQ
Code:
Enumerable.Range(0, hex.Length/2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16));
Usually libraries have some sort of encoder that can convert between different encodings and byte[].
hero member
Activity: 789
Merit: 1909
June 05, 2021, 05:08:59 PM
#4
Hashing "fffff" as a text is the same as hashing "6666666666" as a hex, because ASCII code for 'f' is 0x66.
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
June 05, 2021, 05:05:54 PM
#3
When you feed it fffff as a text string, it uses (usually) UTF-8 to convert them to bits.

Almost all programmatic SHA libraries will take the input at face value and hash bits instead of text and strings. Some don't even let you input strings and text, having a strict type-checking requirement of bytes input.

In Bitcoin, we generate the SHA256 of the public key as a hex and not as a text. The problem is that I haven't found a way to do that in C#, but only as a text. (using SHA256.Create().ComputeHash(bytes))

Hex is the wrong term to use here, you should be hashing in terms of bytes, which is what this code snippet does btw. Are you sure you're not converting hexadecimal characters into bytes and then hashing those in your code?

Crypto-related code should never intermingle hashing with character sets because these have to be decoded to bytes, and they have their own attack vector of vulnerabilities, which is compounded by the fact that different operating systems have different default character sets. (Windows for example does not use UTF-8 by default AFAIK)
legendary
Activity: 2268
Merit: 18503
June 05, 2021, 03:31:28 PM
#2
What difference does it read when I choose to hash it as a hex and what as a text?
SHA256 works on bits. When you feed it fffff as hex, it reads each of those characters as 1111. When you feed it fffff as a text string, it uses (usually) UTF-8 to convert them to bits, and each of those characters becomes 01100110. This results in two completely different inputs, and therefore, two completely different outputs.
legendary
Activity: 1344
Merit: 6415
Farewell, Leo
June 05, 2021, 02:32:01 PM
#1
I want to calculate the SHA256 hash of a hex value in one of my C# projects, but I haven't figured out how. First of all, is this the correct formulation of that phrase? Do I hash a hex value? Why does it differ from hashing a text recognized string?

For example, this string:
Code:
fffff

Gives me the following result when I hash it as a text:
Code:
99834619b3c160248b69c7f42ba868f945a0ea04cd31cf2f60dc4bc8f7d13b8a

And this when I hash it as a hex value:
Code:
b4fabc7e6e75fa4b523cc55f51aa54ab1aa4309c92cc44fcf623ddef756f5391

Doesn't SHA256 break the given pre-image into bits and then start its functions? What difference does it read when I choose to hash it as a hex and what as a text?

In Bitcoin, we generate the SHA256 of the public key as a hex and not as a text. The problem is that I haven't found a way to do that in C#, but only as a text. (using SHA256.Create().ComputeHash(bytes))
Jump to: