Bitcoin Forum
May 12, 2024, 08:50:18 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Why does Bitcoin's SHA256 implementation work differently?  (Read 793 times)
minerino123 (OP)
Newbie
*
Offline Offline

Activity: 5
Merit: 0


View Profile
June 22, 2017, 04:09:17 PM
 #1

Hi, I am new here, so if this is the wrong forum, please let me know where this post is better placed.

I was trying to write my own miner, but simply don't understand what the Hash() function in hash.h is doing.
This is my code:
Code:
// allocate 80 bytes of 0x00s
unsigned char* memory = (unsigned char*)malloc(80);
int* result = (unsigned int*)malloc(32);
memory,0,80);
memory,0,32);

seems to be doing hashes under the SHA-256 name
hash = Hash(memory, memory+80);
hash:%s\n",hash.GetHex().c_str());
//14508459...0e57e74b

However when I try to do this with _any_ other SHA256 implementation I always get a different result (I tried three, which gave me the same result). Here is my Java code:
Code:
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(ByteBuffer.allocate(80).array());
for(byte c : digest) {
System.out.format("%x", c);
}
//5b6fb58e61fa475939767d68a446f97f1bff2c0e5935a3ea8bb51e6515783d8

I thought maybe I have to double hash, but this leaves me with this:
Code:
MessageDigest md2 = MessageDigest.getInstance("SHA-256");
byte[] digest2 = md2.digest(md2.digest(ByteBuffer.allocate(80).array()));
for(byte c : digest2) {
System.out.format("%x", c);
}
//4be757e8f70eb93640c8468274ba759745a7aa2b7d25ab1e421b259845014

So the hash I get from the Bitcoin implementation differs from any other SHA256 implementation for some reason... what am I missing? Am I using the algorithm wrong? Is it initialized differently (other implementation don't give me a possibility to parametrize the function)? Does it simply work differently (not according to the standard)?

Any help would be appreciated
1715503818
Hero Member
*
Offline Offline

Posts: 1715503818

View Profile Personal Message (Offline)

Ignore
1715503818
Reply with quote  #2

1715503818
Report to moderator
1715503818
Hero Member
*
Offline Offline

Posts: 1715503818

View Profile Personal Message (Offline)

Ignore
1715503818
Reply with quote  #2

1715503818
Report to moderator
According to NIST and ECRYPT II, the cryptographic algorithms used in Bitcoin are expected to be strong until at least 2030. (After that, it will not be too difficult to transition to different algorithms.)
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715503818
Hero Member
*
Offline Offline

Posts: 1715503818

View Profile Personal Message (Offline)

Ignore
1715503818
Reply with quote  #2

1715503818
Report to moderator
1715503818
Hero Member
*
Offline Offline

Posts: 1715503818

View Profile Personal Message (Offline)

Ignore
1715503818
Reply with quote  #2

1715503818
Report to moderator
1715503818
Hero Member
*
Offline Offline

Posts: 1715503818

View Profile Personal Message (Offline)

Ignore
1715503818
Reply with quote  #2

1715503818
Report to moderator
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3388
Merit: 6635


Just writing some code


View Profile WWW
June 22, 2017, 05:08:18 PM
 #2

The hashes that Bitcoin uses are double SHA256 hashes. The hashes are also usually in Little Endian byte order. So your second attempt with the double hash is actually correct, but with the wrong byte order. You need to byte swap your result to be in the right ordering.

minerino123 (OP)
Newbie
*
Offline Offline

Activity: 5
Merit: 0


View Profile
June 22, 2017, 09:35:01 PM
Last edit: June 22, 2017, 09:49:20 PM by minerino123
 #3

Thanks for your reply, I still don't understand the problem though. The array consists of 80 bytes all being of value 0x00. This should be the same regardless of byte order, shouldn't it?

EDIT: I don't know really why, but I tested the byte order just to be sure... as expected it doesn't make a difference for the byte array in question.
achow101
Moderator
Legendary
*
expert
Offline Offline

Activity: 3388
Merit: 6635


Just writing some code


View Profile WWW
June 22, 2017, 09:56:49 PM
 #4

Thanks for your reply, I still don't understand the problem though. The array consists of 80 bytes all being of value 0x00. This should be the same regardless of byte order, shouldn't it?

EDIT: I don't know really why, but I tested the byte order just to be sure... as expected it doesn't make a difference for the byte array in question.
It has nothing to do with what you initialized the array with nor with anything that you passed into the function. The endianness has to do with the output of the hash function. The output is different because Bitcoin uses little endian byte order for basically everything, so the output of the hash function will be in little endian byte order. However most other SHA256 implementations will output in big endian byte order so you will need to reverse the hash from other implementations in order to get the little endian byte order that Bitcoin uses.

physicist
Donator
Jr. Member
*
Offline Offline

Activity: 55
Merit: 3


the internet never sleeps


View Profile
June 23, 2017, 03:22:36 AM
 #5

Bitcoin uses little endian byte order. This is not what you are doing.

signature campaigns annoy me.
DannyHamilton
Legendary
*
Offline Offline

Activity: 3388
Merit: 4653



View Profile
June 23, 2017, 03:24:36 AM
 #6

- snip -
This is my code:
Code:
- snip -
//14508459...57e74b

Here, let me color code that for you.  Perhaps it will be easier to see what achow101 is saying...
14508459...57e74b

- snip -
I thought maybe I have to double hash, but this leaves me with this:
Code:
- snip -
//4be757e8f70eb93640c8468274ba759745a7aa2b7d25ab1e421b259845014

Take a look at the matching colors, see if you can spot what has happened...
4be757e8f70eb93640c8468274ba759745a7aa2b7d25ab1e421b259845014
Coding Enthusiast
Legendary
*
Offline Offline

Activity: 1039
Merit: 2783


Bitcoin and C♯ Enthusiast


View Profile WWW
June 23, 2017, 04:14:35 AM
Merited by ABCbits (1)
 #7

Bitcoin uses little endian byte order. This is not what you are doing.

Not always! There are cases which use Big-endian.

Projects List+Suggestion box
Donate: 1Q9s or bc1q
|
|
|
FinderOuter(0.19.1)Ann-git
Denovo(0.7.0)Ann-git
Bitcoin.Net(0.26.0)Ann-git
|
|
|
BitcoinTransactionTool(0.11.0)Ann-git
WatchOnlyBitcoinWallet(3.2.1)Ann-git
SharpPusher(0.12.0)Ann-git
minerino123 (OP)
Newbie
*
Offline Offline

Activity: 5
Merit: 0


View Profile
June 23, 2017, 09:42:47 AM
Last edit: June 23, 2017, 10:07:30 AM by minerino123
 #8

@achow101: Thanks for clarifying... I think I looked at too many bits yesterday. This helps a lot!

@DannyHamilton: Thanks as well for putting in the effort to color it and everything. However you did fake your comment a little bit:
You wrote:
Quote
- snip -
//14508459...57e74b
I wrote:
Quote
//14508459...057e74b
See the additional zero there? That kind of bothers me still... Another implementation contains the zeros as well, so I think there is a problem with my Java implementation... I'll investigate...

EDIT: Simple problem... my Java code was swallowing leading zeros...
Bad code:
Code:
System.out.format("%x", c);
Good code:
Code:
System.out.format("%02x", c);

Thanks again to all here for helping me with this problem!

EDIT2: So just for completness sake in case someone googles this... this Java function seems to produce the same thing as Bitcoin's Hash(...) function:
Code:
static byte[] btcSha256d(byte[] memory) throws NoSuchAlgorithmException{
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] result = md.digest(md.digest(memory));
for(int i=0;i<result.length/2;i++){
byte temp = result[i];
result[i]=result[result.length-i-1];
result[result.length-i-1]=temp;
}
return result;
}
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!