A fine-tuned implementation of the SHA256 hashing algorithm.

Dependents:   EntropySource Wallet_v1

Committer:
Remco
Date:
Mon Jun 20 11:11:10 2011 +0000
Revision:
5:246096ab9e56
Parent:
4:81678751d669
Child:
6:c0ed1bf37651

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Remco 0:772b6de3a841 1 // Author: Remco Bloemen
Remco 0:772b6de3a841 2 // Based on:
Remco 0:772b6de3a841 3 // http://en.wikipedia.org/wiki/SHA-2
Remco 0:772b6de3a841 4 // http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf
Remco 3:f19b10394f9c 5 // OpenSSL optimizations
Remco 0:772b6de3a841 6
Remco 3:f19b10394f9c 7 #pragma once
Remco 0:772b6de3a841 8 #include <string.h>
Remco 0:772b6de3a841 9 #include <string>
Remco 0:772b6de3a841 10
Remco 3:f19b10394f9c 11 /// Class to quickly compute SHA-256 hashes
Remco 3:f19b10394f9c 12 ///
Remco 3:f19b10394f9c 13 /// This class has been heavily optimized for speed
Remco 3:f19b10394f9c 14 /// at a slight expense of code size.
Remco 5:246096ab9e56 15 ///
Remco 5:246096ab9e56 16 /// Example usage:
Remco 5:246096ab9e56 17 /// @code
Remco 5:246096ab9e56 18 /// SHA256 hash;
Remco 5:246096ab9e56 19 /// hash.append("The quick brown fox jumps over the lazy dog.");
Remco 5:246096ab9e56 20 /// hash.finalize();
Remco 5:246096ab9e56 21 /// std::cout << "Digest: " << hash.hexString() << std::endl;
Remco 5:246096ab9e56 22 /// @endcode
Remco 0:772b6de3a841 23 class SHA256 {
Remco 0:772b6de3a841 24 public:
Remco 5:246096ab9e56 25
Remco 3:f19b10394f9c 26 //// Create a new instance, ready for appending
Remco 0:772b6de3a841 27 SHA256() { reset(); }
Remco 3:f19b10394f9c 28
Remco 3:f19b10394f9c 29 /// Reset this instance so you can calculate a new hash
Remco 0:772b6de3a841 30 void reset();
Remco 3:f19b10394f9c 31
Remco 3:f19b10394f9c 32 /// Append data to the hash
Remco 3:f19b10394f9c 33 ///
Remco 3:f19b10394f9c 34 /// Note: due to word-allignment optimizations
Remco 3:f19b10394f9c 35 /// the function may read up to three bytes beyond
Remco 3:f19b10394f9c 36 /// the end of data.
Remco 3:f19b10394f9c 37 ///
Remco 5:246096ab9e56 38 /// @param data the bytes to be added.
Remco 5:246096ab9e56 39 /// @param size the number of bytes to read from data, but see the note.
Remco 0:772b6de3a841 40 void append(const char* data, int size);
Remco 3:f19b10394f9c 41
Remco 4:81678751d669 42 /// Append a single byte
Remco 4:81678751d669 43 ///
Remco 3:f19b10394f9c 44 /// Avoid this function if performance is important.
Remco 4:81678751d669 45 ///
Remco 5:246096ab9e56 46 /// @param c the character to be appended.
Remco 3:f19b10394f9c 47 void append(char c) { append(&c, 1); }
Remco 3:f19b10394f9c 48
Remco 3:f19b10394f9c 49 /// Append a zero terminated string
Remco 4:81678751d669 50 ///
Remco 3:f19b10394f9c 51 /// The terminating zero itself is not appended.
Remco 4:81678751d669 52 ///
Remco 5:246096ab9e56 53 /// @param str the zero terminated string to be appended.
Remco 0:772b6de3a841 54 void append(const char* str) { append(str, strlen(str)); }
Remco 3:f19b10394f9c 55
Remco 3:f19b10394f9c 56 /// Append a std::string
Remco 4:81678751d669 57 ///
Remco 4:81678751d669 58 /// @param str The std::string to be appended.
Remco 0:772b6de3a841 59 void append(const std::string& str) { append(str.data(), str.length()); }
Remco 3:f19b10394f9c 60
Remco 3:f19b10394f9c 61 /// Append the required padding and compute the final digest
Remco 4:81678751d669 62 ///
Remco 4:81678751d669 63 /// Always call this function first before requesting the digest.
Remco 3:f19b10394f9c 64 ///
Remco 3:f19b10394f9c 65 /// After finalization you must call reset() before you can append again.
Remco 4:81678751d669 66 ///
Remco 3:f19b10394f9c 67 /// However, you can do this:
Remco 4:81678751d669 68 /// @code
Remco 5:246096ab9e56 69 /// SHA256 A, AB;
Remco 5:246096ab9e56 70 /// A.append("First part");
Remco 5:246096ab9e56 71 /// AB = A;
Remco 5:246096ab9e56 72 /// A.finalize();
Remco 5:246096ab9e56 73 /// do_something(A.digest());
Remco 5:246096ab9e56 74 /// AB.append("Second part");
Remco 5:246096ab9e56 75 /// AB.finalize();
Remco 5:246096ab9e56 76 /// do_something(AB.digest());
Remco 4:81678751d669 77 /// @endcode
Remco 0:772b6de3a841 78 void finalize();
Remco 3:f19b10394f9c 79
Remco 3:f19b10394f9c 80 /// Returns a pointer to the 32 bytes of the digest
Remco 4:81678751d669 81 ///
Remco 4:81678751d669 82 /// @returns a pointer to a non-zero-terminated block of
Remco 4:81678751d669 83 /// 32 bytes containting the digest.
Remco 0:772b6de3a841 84 const char* digest() { return reinterpret_cast<char*>(hash); }
Remco 3:f19b10394f9c 85
Remco 3:f19b10394f9c 86 /// Return the digest as a binary std::string
Remco 3:f19b10394f9c 87 ///
Remco 3:f19b10394f9c 88 /// Avoid this function if performance is important,
Remco 3:f19b10394f9c 89 /// the std::string constructor will make a copy of the
Remco 3:f19b10394f9c 90 /// digest internally, doing a malloc and memcpy.
Remco 4:81678751d669 91 ///
Remco 4:81678751d669 92 /// @returns a std::string containing the digest as raw binary bits.
Remco 3:f19b10394f9c 93 std::string binString() { return std::string(digest(), 32); }
Remco 3:f19b10394f9c 94
Remco 3:f19b10394f9c 95 /// Return the digest as a hexadecimal std::string
Remco 3:f19b10394f9c 96 ///
Remco 3:f19b10394f9c 97 /// In addition to the note for binaryString, this function
Remco 3:f19b10394f9c 98 /// also does conversion.
Remco 4:81678751d669 99 ///
Remco 4:81678751d669 100 /// @returns a std::string containing the digest in hexadecimal ascii.
Remco 3:f19b10394f9c 101 std::string hexString();
Remco 3:f19b10394f9c 102
Remco 0:772b6de3a841 103 private:
Remco 0:772b6de3a841 104 void process_chunk();
Remco 0:772b6de3a841 105 int length;
Remco 0:772b6de3a841 106 unsigned int hash[8];
Remco 2:1991439ea6b8 107 unsigned int w[16];
Remco 0:772b6de3a841 108 };
Remco 0:772b6de3a841 109