A fine-tuned implementation of the SHA256 hashing algorithm.
Dependents: EntropySource Wallet_v1
Diff: SHA256.cpp
- Revision:
- 3:f19b10394f9c
- Parent:
- 2:1991439ea6b8
- Child:
- 6:c0ed1bf37651
--- a/SHA256.cpp Mon Jun 20 09:45:02 2011 +0000 +++ b/SHA256.cpp Mon Jun 20 11:00:20 2011 +0000 @@ -6,11 +6,8 @@ #include "SHA256.h" -inline unsigned int byte_swap(unsigned int x) +inline unsigned int reverse_bytes(unsigned int x) { - // unsigned int result; - // asm("REV %0, %1" : "=r"(result) : "r"(x)); - // return result return __rev(x); } @@ -35,51 +32,49 @@ void SHA256::append(const char* data, int size) { - /* - unsigned int* dataw = reinterpret_cast<unsigned int*>(data); + int index = length % 64; + length += size; + const char* end = data + size; - while(length & 0x3) { - if(data == end) { - length += size; - return; - } - buffer[3 + (length & (~0x3)) - (length & 0x3)] = *data; - ++length; - ++data; + // Word align data + char* bytes = reinterpret_cast<char*>(w + (index / 4)); + switch(index % 4) + { + // Remember to reverse! (little endian!) + case 1: bytes[2] = *data++; ++index; + case 2: bytes[1] = *data++; ++index; + case 3: bytes[0] = *data++; ++index; + case 0: break; } - if(length % 64 == 0) { - process_chunk(); + if(data > end) { + // We have overshot reading data + // but w and length are correct + return; } - // Process words - int num_words = (end - data) / 4; - int index = (length % 64) / 4; - unsigned int* data_words = reinterpret_cast<unsigned int*>(data); - while(num_words--) - { - if(index == 16) { - process_chunk(); - } + // Index is now word alligned + index /= 4; + if(index == 16) { + process_chunk(); + index = 0; } - */ - const char* end = data + size; - char* buffer = reinterpret_cast<char*>(w); - - int index = length % 64; - while(data != end) { - int word_index = index / 4; - int byte_index = index % 4; - buffer[4 * word_index + 3 - byte_index] = *data; - ++index; - ++data; - if(index == 64) { + // Process whole words + int num_words = (end - data) / 4; + const unsigned int* data_words = reinterpret_cast<const unsigned int*>(data); + const unsigned int* data_words_end = data_words + num_words; + while(data_words != data_words_end) + { + w[index++] = reverse_bytes(*data_words++); + if(index == 16) { process_chunk(); index = 0; } } - length += size; + // Process trailing data bytes + // Again, we won't worry about overshooting data + w[index] = reverse_bytes(*data_words); } void SHA256::finalize() @@ -93,7 +88,7 @@ // Set all other bits to zero w[last_block] &= ~(bit_in_block - 1); - for(int i = last_block + 1; i < 15; ++i) + for(int i = last_block + 1; i < 16; ++i) w[i] = 0; // Make room for the length if necessary @@ -110,7 +105,7 @@ // Convert the result to big endian for(int i = 0; i < 8; ++i) - hash[i] = byte_swap(hash[i]); + hash[i] = reverse_bytes(hash[i]); } #define s0(x) (rotate_right(x, 7) ^ rotate_right(x, 18) ^ (x >> 3)) @@ -214,4 +209,13 @@ hash[7] += h; } - +std::string SHA256::hexString() +{ + const char* hex = "0123456789abcdef"; + std::string hexstr(64, '0'); + for(int i = 0; i < 32; ++i) { + hexstr[2 * i + 0] = hex[digest()[i] >> 4]; + hexstr[2 * i + 1] = hex[digest()[i] & 0xf]; + } + return hexstr; +}