NotATether
Legendary
Offline
Activity: 1722
Merit: 7203
In memory of o_e_l_e_o
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
December 16, 2022, 07:34:52 AM Last edit: December 16, 2022, 08:27:08 AM by NotATether |
|
It's using OpenSSL by the way, but I have a standalone SHA256 class file (that is not AI-generated) that does an equivalent job if you want it.
Can you please share the code because I don't think I ever figure out how to include openssl library or any other third-party library in cpp projects. ![Cheesy](https://bitcointalk.org/Smileys/default/cheesy.gif) Certainly. // ////////////////////////////////////////////////////////// // sha256.h // Copyright (c) 2014,2015 Stephan Brumme. All rights reserved. // see http://create.stephan-brumme.com/disclaimer.html //
#pragma once
//#include "hash.h" #include <string>
// define fixed size integer types #ifdef _WIN32 // Windows typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #else // GCC #include <stdint.h> #endif
// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN #ifndef _WIN32 #include <endian.h> #endif
//#define SHA2_224_SEED_VECTOR
inline uint32_t SHA256_rotate(uint32_t a, uint32_t c) { return (a >> c) | (a << (32 - c)); }
inline uint32_t SHA256_swap(uint32_t x) { #if defined(__GNUC__) || defined(__clang__) return __builtin_bswap32(x); #endif #ifdef MSC_VER return _byteSHA256_swap_ulong(x); #endif
return (x >> 24) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 0x00FF0000) | (x << 24); }
// mix functions for processBlock() inline uint32_t SHA256_f1(uint32_t e, uint32_t f, uint32_t g) { uint32_t term1 = SHA256_rotate(e, 6) ^ SHA256_rotate(e, 11) ^ SHA256_rotate(e, 25); uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g))) return term1 + term2; }
inline uint32_t SHA256_f2(uint32_t a, uint32_t b, uint32_t c) { uint32_t term1 = SHA256_rotate(a, 2) ^ SHA256_rotate(a, 13) ^ SHA256_rotate(a, 22); uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c); return term1 + term2; }
/// compute SHA256 hash /** Usage: SHA256 sha256; std::string myHash = sha256("Hello World"); // std::string std::string myHash2 = sha256("How are you", 11); // arbitrary data, 11 bytes
// or in a streaming fashion:
SHA256 sha256; while (more data available) sha256.add(pointer to fresh data, number of new bytes); std::string myHash3 = sha256.getHash(); */ class SHA256 //: public Hash { public: /// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long enum { BlockSize = 512 / 8, HashBytes = 32 }; private: /// size of processed data in bytes uint64_t m_numBytes; /// valid bytes in m_buffer size_t m_bufferSize; /// bytes not processed yet uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 }; /// hash, stored as integers uint32_t m_hash[HashValues];
/// process 64 bytes void processBlock(const void* data) { // get last hash uint32_t a = m_hash[0]; uint32_t b = m_hash[1]; uint32_t c = m_hash[2]; uint32_t d = m_hash[3]; uint32_t e = m_hash[4]; uint32_t f = m_hash[5]; uint32_t g = m_hash[6]; uint32_t h = m_hash[7];
// data represented as 16x 32-bit words const uint32_t* input = (uint32_t*) data; // convert to big endian uint32_t words[64]; int i; for (i = 0; i < 16; i++) #if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN) words[i] = input[i]; #else words[i] = SHA256_swap(input[i]); #endif
uint32_t x,y; // temporaries
// first round x = h + SHA256_f1(e,f,g) + 0x428a2f98 + words[ 0]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0x71374491 + words[ 1]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x3956c25b + words[ 4]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0x59f111f1 + words[ 5]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x923f82a4 + words[ 6]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// secound round x = h + SHA256_f1(e,f,g) + 0xd807aa98 + words[ 8]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0x12835b01 + words[ 9]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0x243185be + words[10]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0x550c7dc3 + words[11]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x72be5d74 + words[12]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0x80deb1fe + words[13]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x9bdc06a7 + words[14]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0xc19bf174 + words[15]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 24 words for (; i < 24; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// third round x = h + SHA256_f1(e,f,g) + 0xe49b69c1 + words[16]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0xefbe4786 + words[17]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0x0fc19dc6 + words[18]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0x240ca1cc + words[19]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x2de92c6f + words[20]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0x4a7484aa + words[21]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x5cb0a9dc + words[22]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0x76f988da + words[23]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 32 words for (; i < 32; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// fourth round x = h + SHA256_f1(e,f,g) + 0x983e5152 + words[24]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0xa831c66d + words[25]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0xb00327c8 + words[26]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0xbf597fc7 + words[27]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0xc6e00bf3 + words[28]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0xd5a79147 + words[29]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x06ca6351 + words[30]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0x14292967 + words[31]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 40 words for (; i < 40; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// fifth round x = h + SHA256_f1(e,f,g) + 0x27b70a85 + words[32]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0x2e1b2138 + words[33]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0x4d2c6dfc + words[34]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0x53380d13 + words[35]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x650a7354 + words[36]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0x766a0abb + words[37]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x81c2c92e + words[38]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0x92722c85 + words[39]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 48 words for (; i < 48; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// sixth round x = h + SHA256_f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0xa81a664b + words[41]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0xc24b8b70 + words[42]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0xc76c51a3 + words[43]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0xd192e819 + words[44]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0xd6990624 + words[45]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0xf40e3585 + words[46]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0x106aa070 + words[47]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 56 words for (; i < 56; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// seventh round x = h + SHA256_f1(e,f,g) + 0x19a4c116 + words[48]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0x1e376c08 + words[49]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0x2748774c + words[50]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0x34b0bcb5 + words[51]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x391c0cb3 + words[52]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0x4ed8aa4a + words[53]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0x5b9cca4f + words[54]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0x682e6ff3 + words[55]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// extend to 64 words for (; i < 64; i++) words[i] = words[i-16] + (SHA256_rotate(words[i-15], 7) ^ SHA256_rotate(words[i-15], 18) ^ (words[i-15] >> 3)) + words[i-7] + (SHA256_rotate(words[i- 2], 17) ^ SHA256_rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
// eigth round x = h + SHA256_f1(e,f,g) + 0x748f82ee + words[56]; y = SHA256_f2(a,b,c); d += x; h = x + y; x = g + SHA256_f1(d,e,f) + 0x78a5636f + words[57]; y = SHA256_f2(h,a,b); c += x; g = x + y; x = f + SHA256_f1(c,d,e) + 0x84c87814 + words[58]; y = SHA256_f2(g,h,a); b += x; f = x + y; x = e + SHA256_f1(b,c,d) + 0x8cc70208 + words[59]; y = SHA256_f2(f,g,h); a += x; e = x + y; x = d + SHA256_f1(a,b,c) + 0x90befffa + words[60]; y = SHA256_f2(e,f,g); h += x; d = x + y; x = c + SHA256_f1(h,a,b) + 0xa4506ceb + words[61]; y = SHA256_f2(d,e,f); g += x; c = x + y; x = b + SHA256_f1(g,h,a) + 0xbef9a3f7 + words[62]; y = SHA256_f2(c,d,e); f += x; b = x + y; x = a + SHA256_f1(f,g,h) + 0xc67178f2 + words[63]; y = SHA256_f2(b,c,d); e += x; a = x + y;
// update hash m_hash[0] += a; m_hash[1] += b; m_hash[2] += c; m_hash[3] += d; m_hash[4] += e; m_hash[5] += f; m_hash[6] += g; m_hash[7] += h; } /// process everything left in the internal buffer void processBuffer() { // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
// - append "1" bit to message // - append "0" bits until message length in bit mod 512 is 448 // - append length as 64 bit integer
// number of bits size_t paddedLength = m_bufferSize * 8;
// plus one bit set to 1 (always appended) paddedLength++;
// number of bits must be (numBits % 512) = 448 size_t lower11Bits = paddedLength & 511; if (lower11Bits <= 448) paddedLength += 448 - lower11Bits; else paddedLength += 512 + 448 - lower11Bits; // convert from bits to bytes paddedLength /= 8;
// only needed if additional data flows over into a second block unsigned char extra[BlockSize];
// append a "1" bit, 128 => binary 10000000 if (m_bufferSize < BlockSize) m_buffer[m_bufferSize] = 128; else extra[0] = 128;
size_t i; for (i = m_bufferSize + 1; i < BlockSize; i++) m_buffer[i] = 0; for (; i < paddedLength; i++) extra[i - BlockSize] = 0;
// add message length in bits as 64 bit number uint64_t msgBits = 8 * (m_numBytes + m_bufferSize); // find right position unsigned char* addLength; if (paddedLength < BlockSize) addLength = m_buffer + paddedLength; else addLength = extra + paddedLength - BlockSize;
// must be big endian *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF); *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF); *addLength = (unsigned char)( msgBits & 0xFF);
// process blocks processBlock(m_buffer); // flowed over into a second block ? if (paddedLength > BlockSize) processBlock(extra); }
public:
/// same as reset() SHA256() { reset(); }
/// compute SHA256 of a memory block std::string operator()(const void* data, size_t numBytes) { reset(); add(data, numBytes); return getHash(); } /// compute SHA256 of a string, excluding final zero std::string operator()(const std::string& text) { reset(); add(text.c_str(), text.size()); return getHash(); }
/// add arbitrary number of bytes void add(const void* data, size_t numBytes) { const uint8_t* current = (const uint8_t*) data;
if (m_bufferSize > 0) { while (numBytes > 0 && m_bufferSize < BlockSize) { m_buffer[m_bufferSize++] = *current++; numBytes--; } }
// full buffer if (m_bufferSize == BlockSize) { processBlock(m_buffer); m_numBytes += BlockSize; m_bufferSize = 0; }
// no more data ? if (numBytes == 0) return;
// process full blocks while (numBytes >= BlockSize) { processBlock(current); current += BlockSize; m_numBytes += BlockSize; numBytes -= BlockSize; }
// keep remaining bytes in buffer while (numBytes > 0) { m_buffer[m_bufferSize++] = *current++; numBytes--; } }
/// return latest hash as 64 hex characters std::string getHash() { // compute hash (as raw bytes) unsigned char rawHash[HashBytes]; getHash(rawHash);
// convert to hex string std::string result; result.reserve(2 * HashBytes); for (int i = 0; i < HashBytes; i++) { static const char dec2hex[16+1] = "0123456789abcdef"; result += dec2hex[(rawHash[i] >> 4) & 15]; result += dec2hex[ rawHash[i] & 15]; }
return result; } /// return latest hash as bytes void getHash(unsigned char buffer[HashBytes]) { // save old hash if buffer is partially filled uint32_t oldHash[HashValues]; for (int i = 0; i < HashValues; i++) oldHash[i] = m_hash[i];
// process remaining bytes processBuffer();
unsigned char* current = buffer; for (int i = 0; i < HashValues; i++) { *current++ = (m_hash[i] >> 24) & 0xFF; *current++ = (m_hash[i] >> 16) & 0xFF; *current++ = (m_hash[i] >> 8) & 0xFF; *current++ = m_hash[i] & 0xFF;
// restore old hash m_hash[i] = oldHash[i]; } }
/// restart void reset() { m_numBytes = 0; m_bufferSize = 0;
// according to RFC 1321 // "These words were obtained by taking the first thirty-two bits of the // fractional parts of the square roots of the first eight prime numbers" m_hash[0] = 0x6a09e667; m_hash[1] = 0xbb67ae85; m_hash[2] = 0x3c6ef372; m_hash[3] = 0xa54ff53a; m_hash[4] = 0x510e527f; m_hash[5] = 0x9b05688c; m_hash[6] = 0x1f83d9ab; m_hash[7] = 0x5be0cd19;
#ifdef SHA2_224_SEED_VECTOR // if you want SHA2-224 instead then use these seeds // and throw away the last 32 bits of getHash m_hash[0] = 0xc1059ed8; m_hash[1] = 0x367cd507; m_hash[2] = 0x3070dd17; m_hash[3] = 0xf70e5939; m_hash[4] = 0xffc00b31; m_hash[5] = 0x68581511; m_hash[6] = 0x64f98fa7; m_hash[7] = 0xbefa4fa4; #endif } }; As the code mentions, I did not write this code, I just adapted it to a single header file. He has more open-source hashing functions, which you can download for free at https://create.stephan-brumme.com/hash-library/PS: Since most people will be dealing with binary data when converting the HASH160 to base58(check), I decided to ask chatGPT to make binary to hex conversions as well: #include <iostream> #include <string> #include <bitset> #include <sstream>
// Convert an 8-bit binary string to a hexadecimal string std::string binaryToHex(const std::string& binary) { std::bitset<8> bits(binary); int decimal = bits.to_ulong(); std::stringstream stream; stream << std::hex << decimal; return stream.str(); }
// Convert a hexadecimal string to an 8-bit binary string std::string hexToBinary(const std::string& hex) { int decimal = std::stoi(hex, nullptr, 16); std::bitset<8> bits(decimal); return bits.to_string(); }
Here's how you can use these functions: int main() { std::string binary = "00011011"; std::string hex = binaryToHex(binary); std::cout << "Hexadecimal: " << hex << std::endl;
std::string hex2 = "1B"; std::string binary2 = hexToBinary(hex2); std::cout << "Binary: " << binary2 << std::endl;
return 0; }
The output of this program will be: Hexadecimal: 1b Binary: 00011011
I am so glad I didn't waste $100 on Copilot, this is so much better and more useful (and free!).
Update: I installed openssl using this command: sudo apt-get install libssl-dev
But now I am seeing another error: /main.cpp:24: undefined reference to `SHA256' collect2: error: ld returned 1 exit status
How to make it work? Are you linking to both libssl and libcrypto? -lssl -lcrypto
|