在 C++ 中對塊頭進行雙重散列時使用的實際工作實現程式碼是什麼?
我需要根據我認為到目前為止被描述為十六進製過濾的 sha256 實現……或類似的東西成功地生成一個雜湊值。我來過這裡、這裡、這裡、這里和這裡……在許多其他地方。
範例案例:
使用“abc”作為輸入字元串, 勾選**“Hex”複選框的**AnyHash.com 會生成一個雜湊 - 。當作為輸入輸入時,它會產生雜湊 - 。
15f27c6b8828e62cd3d09e8b4de5230844facfc88f1b9c34129cab7706f2f561
15f27c6b8828e62cd3d09e.......
42a5aa8cd08811f43428c42f76279a5a92e12b3e3f7080b87804a05135773487
根據dave_thompson_085的評論,我一直在努力讓它發揮作用。使用中的 sha256 實現是由Zedwood提供的,下面是我為重新創建由AnyHash.com生成的雜湊輸出而進行的徒勞的努力。
// ----------------------- --------------------------- // // ----------------------- --------------------------- // // ----------------------- --------------------------- // // COMMENT BY DAVE_THOMPSON_085 // That code is okay except the silly std::string wrapper is useless for bitcoin. Do something like : // unsigned char hdr[80], hash[32]; // SHA256 ctx = SHA256(); /* fill in hdr */ // ctx.init(); // ctx.update(hdr,80); // ctx.final(hash); // ctx.init(); // ctx.update(hash,32); // ctx.final(hash); /* (reverse and) use results in hash, possibly converted to hex or whatever you need */ // ----------------------- --------------------------- // // ----------------------- --------------------------- // // ----------------------- --------------------------- // std::string sha256(std::string input) { string kk; // header_data is "160" in size because midstate optimization is not implemented unsigned char header_data[160], hash[32]; char hash2[32], hash3[32]; char buf[2*32+1]; buf[2*32] = 0; // input = GetBinaryStringFromHexString(input); // convert input data to binary format init(); update((unsigned char*)input.c_str(), input.length()); final(hash); // Iterate and store values from hash[] to hash2[] for (int i = 0; i < 32; i++) hash2[i] = hash[i]; // kk = final2(hash); // MODIFIED FUNCTION THAT RETURNS A STRING // //kk = char_ToString(hash2); // Converts char array to string variable kk = GetBinaryStringFromHexString(char_ToString(hash2)); // convert data to binary format input = kk; // Store data in kk to input init(); update((unsigned char*)input.c_str(), input.length()); final((unsigned char *)hash3); // Modified as char* to unsigned char* conversion is not allowed for (int i = 0; i < 32; i++) sprintf(buf+i*2, "%02x", hash3[i]); // ORIGINAL : sprintf(buf+i*2, "%02x", digest[i]) return std::string(buf); // Return buf as string instead of char } int main(int argc, char const *argv[]) { std::string data = "abc"; std::cout << "sha256(data) : " << sha256(data) << "\n"; std::cout << "sha256(sha256(data)) : " << sha256(sha256(data)) << "\n"; return 0; } // Input : abc // Expecting first hash output from sha256 ( with hex conversion ) to be : // 15f27c6b8828e62cd3d09e8b4de5230844facfc88f1b9c34129cab7706f2f561 - single sha // And second output to be : // 42a5aa8cd08811f43428c42f76279a5a92e12b3e3f7080b87804a05135773487 - double sha // As generated byanyhash.com
有時最難實現的總是顯而易見的實現。- 在我看來。
**勾選了“Hex”**的相同雜湊生成器成功生成了比特幣區塊鏈中存在的第100000 塊的正確雜湊。區塊 100,000 由 AnyHash.com 散列
塊頭**
0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710
**我嘗試從比特幣原始碼中獲取程式碼**
hahahahahahahahahahahaha
…….**需要我多說嗎?包含如此多的標頭和超出所需的依賴項,想想它就是一場噩夢。所以,如果有人知道如何真正使這段程式碼工作……請協助其他程序員……
天知道比特幣讓大多數程序員看起來像個新手。仍然是一項偉大的技術!
以下是使用的其他功能(如果它有問題)提前謝謝!
sing std::hex; string GetBinaryStringFromHexString(string hexData); // std::string char_ToString(char data[]); std::string char_ToString(char data[]) { std::string stringData = ""; //declare string variable // int size = sizeof(data)/sizeof(*data); int size = strlen(data); //get amount of characters in char array for (int i = 0; i < size; i++) // for elements in char array stringData = data; // store elements in string variable "stringData" return stringData; // return stringData } string GetBinaryStringFromHexString(string hexData) { string binaryResult = ""; for (int i = 0; i < hexData.length(); ++i) { switch (hexData[i]) { case '0': binaryResult.append("0000"); break; case '1': binaryResult.append("0001"); break; case '2': binaryResult.append("0010"); break; case '3': binaryResult.append("0011"); break; case '4': binaryResult.append("0100"); break; case '5': binaryResult.append("0101"); break; case '6': binaryResult.append("0110"); break; case '7': binaryResult.append("0111"); break; case '8': binaryResult.append("1000"); break; case '9': binaryResult.append("1001"); break; case 'a': binaryResult.append("1010"); break; case 'b': binaryResult.append("1011"); break; case 'c': binaryResult.append("1100"); break; case 'd': binaryResult.append("1101"); break; case 'e': binaryResult.append("1110"); break; case 'f': binaryResult.append("1111"); break; } } return binaryResult; }
請注意,我正在分析您的程式碼,就好像我按原樣編譯它一樣。這意味著任何被註釋掉的東西都會被忽略。
第一個主要問題是這一行:
kk = GetBinaryStringFromHexString(char_ToString(hash2)); // convert data to binary format
較早的
final(hash);
將生成一個 char 數組,其中填充了 SHA256 雜湊作為二進制數據。因此,無需將其轉換為 std::string 並隨後嘗試將其轉換為二進製字元串。此行是不必要的,hash
可以直接作為下一行的輸入提供update()
。解決這個問題應該可以讓您找到abc
.這段程式碼的第二個主要問題是它
GetBinaryStringFromHexString
沒有做你認為它正在做的事情。它將十六進製字元串轉換為二進製字元串。這與將十六進製字元串轉換為該十六進製表示的二進制數據不同。您在該函式中實際得到的是一個更長的字元串,其數據是 0 和 1 的 ascii 字元,而不是十六進製字元串本身表示的數據。這個StackOverflow 答案提供了一個可以使用的十六進製字元串解析函式。修復此問題應該允許您找到以十六進製字元串形式提供的塊頭的雙 SHA256。幾個小問題:
- 無需複製
hash
到hash2
. 您也可以直接將其作為參數提供給第二個update
。- 沒有必要有
hash2
或hash3
。您每次都可以使用hash
,它將被新的雜湊覆蓋。final
- 該功能
char_ToString
不是必需的。除此之外,您的程式碼不需要它,std::string
還有一個可以採用 a及其長度的建構子。char *
您的最終程式碼將類似於:
std::string sha256(std::string input) { string kk; // header_data is "160" in size because midstate optimization is not implemented unsigned char header_data[160], hash[32]; char buf[2*32+1]; buf[2*32] = 0; input = ParseHex(input); init(); update((unsigned char*)input.c_str(), input.length()); final(hash); init(); update(hash, 32); final(hash); for (int i = 0; i < 32; i++) sprintf(buf+i*2, "%02x", hash[i]); // ORIGINAL : sprintf(buf+i*2, "%02x", digest[i]) return std::string(buf); // Return buf as string instead of char } std::string ParseHex(const std::string& s) { assert(s.size() % 2 == 0); static const std::size_t symbol_count = 256; static const unsigned char hex_to_bin[symbol_count] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 - 0x07 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 - 0x0F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x17 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 - 0x1F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x27 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 - 0x2F 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 - 0x3F 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x40 - 0x47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 - 0x5F 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, // 0x60 - 0x67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 - 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 - 0x8F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 - 0x9F 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 - 0xA7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 - 0xAF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 - 0xB7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 - 0xBF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 - 0xC7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 - 0xCF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 - 0xD7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 - 0xDF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 - 0xE7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 - 0xEF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 - 0xF7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0xF8 - 0xFF }; std::string out; auto& itr = s.begin(); while (itr != s.end()) { unsigned char b = static_cast<unsigned char>(hex_to_bin[*(itr++)] << 4); b |= static_cast<unsigned char>(hex_to_bin[*(itr++)] ); out.push_back(b); } return out; }