Get a correct SHA256 of a PublicKey as bytes

3

I’m new in code develop and I’m studying it by myself (books, tutorials, official help of sites…) since a year VB.NET. A lot of information I read is in C# that I rewrite in VB.NET. I’ve started four months ago to read and write some code about SHA256, Aes, ECDsa… and there are some things those I understand with time and practice, but there are other things that I can’t understand (or find) until read a lot of information. Well in this case, I think I can understand but I don’t know how write the code or understand how SHA256 works. I’m following these instructions:

ripemd160(sha256(publickey)) - Where am I going wrong? << I think I have the same problem.

I’ll try to be specific and write all necessary code for other people that it could be for their interest. Thank you for advance for all help, links, information that you can give me to follow the right path. Well, this is my situation: I’ve created a Public key (x coord and y coord) and a private key by ECDsa with SecP256k1 curve. This is the code:

Private Sub GetKeys()
Using myECDsa As New System.Security.Cryptography.ECDsaCng(vCurve)
myECDsa.HashAlgorithm = CngAlgorithm.Sha256
Dim PrivateKey() As Byte = myECDsa.Key.Export(CngKeyBlobFormat.EccPrivateBlob)
Dim PublicKey() As Byte = myECDsa.Key.Export(CngKeyBlobFormat.EccPublicBlob)

Console.WriteLine(Convert.ToBase64String(PrivateKey))
Console.WriteLine(Convert.ToBase64String(PublicKey))
End Using
End Sub


*vCurve is a var that contains the string “SecP256k1”

Output maybe this:

Private Key: RUNEViAAAADvJ2dk9gUnYF2XDIr5dNITLUXnXJRgXD8A3WHeDe6YkBBTJAlNizJCp5rMG0163U2JfNWEnBKEE7AjU2guVar63+jTifUg8/UrjTfoLkoIgdk8VLnTz1HYDxEvR2GtE70=


I can convert to string and clean data if I write this code into Using

'Private Key
Dim StrPrivateKey As String = String.Empty
For Each bt As Byte In PrivateKey
StrPrivateKey &= bt.ToString("X2")
Next
'Public Key
Dim StrPublicKey As String = String.Empty
For Each bt As Byte In PublicKey
StrPublicKey &= bt.ToString("X2")
Next
Dim StrDigits As String = StrPrivateKey.Substring(0, 16)
'Clean data
StrPrivateKey = StrPrivateKey.Substring(StrPublicKey.Length)
StrPublicKey = StrPublicKey.Substring(16)
Dim StrXCoord As String = StrPublicKey.Substring(0, 64)
Dim StrYCoord As String = StrPublicKey.Substring(64)


Output is:

Private Key: 6624B7D42BA98F09B4782B755DEE4A050A3E5F15D1DFB152E5A0571ABD045797
Digits: 4543445620000000
YCoord: C34F2FAA9533FEFD80E6EAA20ED0BD2D7A30F2696A08570B053159FA7068CE90


First Question: I saw that every Private/Public key has a similar number or 8 bytes. In this example is: 4543445620000000

What is this number? Is it a version of something?

Second Question: I’ve found a little information about how to get a SHA256 of Public Key. If I get the SHA256 of this example, the result is:

Public Key: 04C400BED535B984BADCB6DA96D4167709314085B6E5405C7CE1A3D2CF76FA991DC34F2FAA9533FEFD80E6EAA20ED0BD2D7A30F2696A08570B053159FA7068CE90
SHA256: f7beda57bd9e0c9838dd4e1336aaa363c2bfa88eca25407b472a620fcaa1626f


Sha256 is correct if I take Public Key as a string (yes, I write “04” at the start and I know that is not a byte). But I’ve read that Public Key must be in bytes, and this is the part where I lost the way. I have PublicKey() as byte, but I don’t know how work with it to get a SHA256. All sha256 tutorials and help about it, hash a single string or files, and as you can see, I need some information that I don’t know how to search.

Thanks a lot.

'------ Edit to write how I'm using SHA256 code. A lot of info I'm reading to learn is form https://docs.microsoft.com

Public Function FxSHA256(ByVal textHashed As String) As String
If textHashed.Length <= 0 Then
MsgBox("No text to hash.")
Return 0
Exit Function
End If
Dim hash As String = String.Empty
Using mySHA256 As SHA256 = SHA256.Create()
hash = ModuleConvert.GetHASH(mySHA256, textHashed)
End Using
myHash256 = hash
Return hash
End Function


In other module I have this:

'HashAlgorythm
Public Function GetHASH(ByVal hashAlgorithm As HashAlgorithm, ByVal textHashed As String) As String
Dim data As Byte() = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(textHashed))
Dim sBuilder As New StringBuilder()
For i As Integer = 0 To data.Length - 1
sBuilder.Append(data(i).ToString("x2"))
Next
Return sBuilder.ToString()
End Function


To second question, can you use sha256.ComputeHash as in Dim hash As Byte() = sha256.ComputeHash(bytes) in https://codeshare.co.uk/blog/sha-256-and-sha-512-hash-examples/?. (Yes, 0x04 is a byte and you should add it to beginning before hashing it, as you did in the last code snippet)

– MCCCS – 2019-10-25T18:13:33.867

Thanks. Yes, I read this link a few days ago. But works like my code. Now I will edit my Post to write what I'm using for get SHA256 – UnnamedString – 2019-10-26T13:07:36.347

@mcccs, sorry, I want to say that I wrote "04" as a string, and not add as a byte. I know that I need to add a byte in front of Public Key, but in this example I write as string. – UnnamedString – 2019-10-26T13:22:15.853

0

Well, I was lost in hashing bytes. Finally this web helped me to understand what happened: https://jackdye.co.uk/generating-a-bitcoin-address-in-c/

In my post I was hashing STRINGS, and this is why SHA256 never will works well. We can display on screen these values as strings, but when we have to do SHA256 or RIPEMD160 we need bytes (a lot of people have or had this problem to understand how to add bytes and hashing them as bytes, not as strings. It's a problem of understanding). To convert Strings to bytes I use this function:

Public Function HexToByteArray(ByVal HexString As String) As Byte()
Dim ByteArray((HexString.Length / 2) - 1) As Byte
If HexString.Length Mod 2 <> 0 Then
MsgBox("Invalid Hex string.")
Else
For i As Integer = 0 To ByteArray.Length - 1
ReDim Preserve ByteArray(i)
ByteArray(i) = Byte.Parse(HexString.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture)
Next
End If
Return ByteArray
End Function


Ok let's start: Work with strings and convert to byte():

When get the public key as string add a byte:

Dim myString as String = "04" & "C400BED535B984BADCB6DA96D4167709314085B6E5405C7CE1A3D2CF76FA991DC34F2FAA9533FEFD80E6EAA20ED0BD2D7A30F2696A08570B053159FA7068CE90"


Yes, this still a String and we are adding a string "04", but we will convert in a byte. Now Hashing it as a byte: This is the function for SHA256 for bytes

Public Function FxSHA256(ByVal ByteArray() As Byte) As Byte()
If ByteArray.Length <= 0 Then
MsgBox("No Byte Array to Hash.")
Return ByteArray
Exit Function
End If
Using NewSHA256 As SHA256 = SHA256.Create()
Return NewSHA256.ComputeHash(ByteArray)
End Using
End Function


And this is the SHA256 function for strings (wrong function to get the correct SHA256 in this example)

Public Function FxSHA256(ByVal textHashed As String) As String
If textHashed.Length <= 0 Then
MsgBox("No text to hash.")
Return 0
Exit Function
End If
Dim hash As String = String.Empty
Using mySHA256 As SHA256 = SHA256.Create()
hash = ModuleConvert.GetHASH(mySHA256, textHashed)
End Using
myHash256 = hash
Return hash
End Function


And now, you can understand why I get the correct SHA256 and why I was lost, wrong and confused.

To Hash correctly the string in bytes:

FxSHA256(HexToByteArray(myString))


And if you want to display on screen, you can do that:

For Each bt As Byte In FxSHA256(HexToByteArray(myString))
Console.Write(bt.ToString("x2"))
Next


The same for RIPEMD160.