A fine-tuned implementation of the SHA256 hashing algorithm.

Dependents:   EntropySource Wallet_v1

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;
+}