diff --git a/README.md b/README.md index 22b665b..e33057c 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,48 @@ # [hmac_sha256](https://github.com/h5p9sl/hmac_sha256) -A SHA256 HMAC implementation in C/C++ +*A SHA256 HMAC implementation in C/C++* ## Usage Example (C++) ```cpp -#include "hmac_sha256.h" +#include "../hmac_sha256.h" #include #include #include #include +#include +#include -#define SHA256_HASHLEN 32 +#define SHA256_HASH_SIZE 32 int main() { - // This is what the hmac_sha256 value should output - const std::string testvector = "b0344c61d8db38535ca8afceafbf12b881dc20c9833da726e9376c2e32cff7"; - const std::string str_data = "Hi There"; + const std::string str_data = "Hello World!"; + const std::string str_key = "super-secret-key"; + std::stringstream ss_result; - std::vector key, data, out; - std::stringstream result; - - // Allocate memory using C++ std::vector - key.resize(20, 0x0b); - data.resize(str_data.length(), 0); - out.resize(SHA256_HASHLEN, 0); - - // Fill `data` with `str_data`'s bytes - data.assign(str_data.cbegin(), str_data.cend()); + // Allocate memory for the HMAC + std::vector out(SHA256_HASH_SIZE); // Call hmac-sha256 function hmac_sha256( - key.data(), key.size(), - data.data(), data.size(), + str_key.data(), str_key.size(), + str_data.data(), str_data.size(), out.data(), out.size() ); // Convert `out` to string with std::hex - for (size_t i = 0; i < out.size(); i++) { - result << std::hex << (int)out[i]; - } - std::cout << result.str() << std::endl; - std::cout << testvector << std::endl; - - // Compare result - if (testvector.compare(result.str()) == 0) { - std::cout << "Test passed!" << std::endl; - } else { - std::cout << "Test failed." << std::endl; + for (uint8_t x : out) { + ss_result << std::hex << std::setfill('0') << std::setw(2) << (int)x; } + // Print out the result + std::cout << "Message: " << str_data << std::endl; + std::cout << "HMAC: " << ss_result.str() << std::endl; + + // This assertion fails if something went wrong + assert( + ss_result.str() == + "4b393abced1c497f8048860ba1ede46a23f1ff5209b18e9c428bddfbb690aad8" + ); return 0; } ``` diff --git a/examples/simple_example.cpp b/examples/simple_example.cpp new file mode 100644 index 0000000..231e5e8 --- /dev/null +++ b/examples/simple_example.cpp @@ -0,0 +1,42 @@ +#include "../hmac_sha256.h" + +#include +#include +#include +#include +#include +#include + +#define SHA256_HASH_SIZE 32 + +int main() { + const std::string str_data = "Hello World!"; + const std::string str_key = "super-secret-key"; + std::stringstream ss_result; + + // Allocate memory for the HMAC + std::vector out(SHA256_HASH_SIZE); + + // Call hmac-sha256 function + hmac_sha256( + str_key.data(), str_key.size(), + str_data.data(), str_data.size(), + out.data(), out.size() + ); + + // Convert `out` to string with std::hex + for (uint8_t x : out) { + ss_result << std::hex << std::setfill('0') << std::setw(2) << (int)x; + } + + // Print out the result + std::cout << "Message: " << str_data << std::endl; + std::cout << "HMAC: " << ss_result.str() << std::endl; + + // This assertion fails if something went wrong + assert( + ss_result.str() == + "4b393abced1c497f8048860ba1ede46a23f1ff5209b18e9c428bddfbb690aad8" + ); + return 0; +} diff --git a/examples/tests.cpp b/examples/tests.cpp new file mode 100644 index 0000000..3f3cd5a --- /dev/null +++ b/examples/tests.cpp @@ -0,0 +1,58 @@ +#include "../hmac_sha256.h" + +#include +#include +#include +#include +#include +#include +#include + +#define SHA256_HASH_SIZE 32 + +typedef std::vector> TestData_t; + +void do_tests(const TestData_t& test_vectors) { + // Perform tests + for (auto tvec : test_vectors) { + std::stringstream ss_result; + std::vector out(SHA256_HASH_SIZE); + hmac_sha256( + std::get<0>(tvec).data(), std::get<0>(tvec).size(), + std::get<1>(tvec).data(), std::get<1>(tvec).size(), + out.data(), out.size() + ); + for (uint8_t i : out) { ss_result << std::hex << std::setfill('0') << std::setw(2) << (int)i; } + if (std::get<2>(tvec) != ss_result.str()) { + std::cout << "TEST FAILED: \n\t" << ss_result.str() << " != \n\t" << std::get<2>(tvec) << std::endl; + } else { + std::cout << "Test successful" << std::endl; + } + } +} + +int main() { + const TestData_t test_vectors = { + // Key Data HMAC + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "Hi There", + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", + }, { + "Jefe", + "what do ya want for nothing?", + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", + }, { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", + }, { + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", + }, + }; + do_tests(test_vectors); + return 0; +} + diff --git a/hmac_sha256.c b/hmac_sha256.c index e97fd52..568e9e7 100644 --- a/hmac_sha256.c +++ b/hmac_sha256.c @@ -1,27 +1,28 @@ /* - hmac_sha256.c - Originally written by https://github.com/h5p9sl -*/ + hmac_sha256.c + Originally written by https://github.com/h5p9sl + */ #include "hmac_sha256.h" -#include "WjCryptLib_Sha256.h" +#include "sha256.h" #include #include #define SIZEOFARRAY(x) sizeof(x) / sizeof(x[0]) +#define SHA256_BLOCK_SIZE 64 /* LOCAL FUNCTIONS */ -void sha256(const uint8_t* data, const unsigned datalen, uint8_t* out); -void appendAndHash(const uint8_t* dest, const unsigned destlen, const uint8_t* src, const unsigned srclen, uint8_t* out, const unsigned outlen -); + +// wrapper for sha256 digest functions +void sha256(const void *data, const unsigned datalen, void *out); +// concatonate src & dest then sha2 digest them +void concat_and_hash(const void *dest, const unsigned destlen, const void *src, + const unsigned srclen, void *out, const unsigned outlen); // Declared in hmac_sha256.h -void hmac_sha256( - const uint8_t* key, const unsigned keylen, - const uint8_t* data, const unsigned datalen, - uint8_t* out, const unsigned outlen) -{ +void hmac_sha256(const void *key, const unsigned keylen, const void *data, + const unsigned datalen, void *out, const unsigned outlen) { uint8_t k[SHA256_BLOCK_SIZE]; // block-sized key derived from 'key' parameter uint8_t k_ipad[SHA256_BLOCK_SIZE]; uint8_t k_opad[SHA256_BLOCK_SIZE]; @@ -32,7 +33,8 @@ void hmac_sha256( // Fill 'k' with zero bytes memset(k, 0, SIZEOFARRAY(k)); if (keylen > SHA256_BLOCK_SIZE) { - // If the key is larger than the hash algorithm's block size, we must digest it first. + // If the key is larger than the hash algorithm's block size, we must + // digest it first. sha256(key, keylen, k); } else { memcpy(k, key, keylen); @@ -48,8 +50,10 @@ void hmac_sha256( // Perform HMAC algorithm H(K XOR opad, H(K XOR ipad, text)) // https://tools.ietf.org/html/rfc2104 - appendAndHash(k_ipad, SIZEOFARRAY(k_ipad), data, datalen, hash0, SIZEOFARRAY(hash0)); - appendAndHash(k_opad, SIZEOFARRAY(k_opad), hash0, SIZEOFARRAY(hash0), hash1, SIZEOFARRAY(hash1)); + concat_and_hash(k_ipad, SIZEOFARRAY(k_ipad), data, datalen, hash0, + SIZEOFARRAY(hash0)); + concat_and_hash(k_opad, SIZEOFARRAY(k_opad), hash0, SIZEOFARRAY(hash0), hash1, + SIZEOFARRAY(hash1)); // Copy the resulting hash the output buffer // Trunacate sha256 hash if needed @@ -57,11 +61,8 @@ void hmac_sha256( memcpy(out, hash1, sz); } -void appendAndHash( - const uint8_t* dest, const unsigned destlen, - const uint8_t* src, const unsigned srclen, - uint8_t* out, const unsigned outlen) -{ +void concat_and_hash(const void *dest, const unsigned destlen, const void *src, + const unsigned srclen, void *out, const unsigned outlen) { uint8_t buf[destlen + srclen]; uint8_t hash[SHA256_HASH_SIZE]; @@ -77,7 +78,7 @@ void appendAndHash( memcpy(out, hash, SHA256_HASH_SIZE); } -void sha256(const uint8_t* data, const unsigned datalen, uint8_t* out) { +void sha256(const void *data, const unsigned datalen, void *out) { Sha256Context ctx; SHA256_HASH hash; diff --git a/hmac_sha256.h b/hmac_sha256.h index e33e0b5..1c1e5f3 100644 --- a/hmac_sha256.h +++ b/hmac_sha256.h @@ -14,11 +14,11 @@ extern "C" { void hmac_sha256( // [in]: The key and it's length. Should be at least 32 bytes long for optimal security. - const uint8_t* key, const unsigned keylen, + const void* key, const unsigned keylen, // [in]: The data to hash along with the key. - const uint8_t* data, const unsigned datalen, + const void* data, const unsigned datalen, // [out]: The output hash. Should be 32 bytes long, but if it's less than 32 bytes, the function will truncate the resulting hash. - uint8_t* out, const unsigned outlen + void* out, const unsigned outlen ); #ifdef __cplusplus diff --git a/WjCryptLib_Sha256.c b/sha256.c similarity index 99% rename from WjCryptLib_Sha256.c rename to sha256.c index 559865e..fe2aeef 100644 --- a/WjCryptLib_Sha256.c +++ b/sha256.c @@ -12,7 +12,7 @@ // IMPORTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include "WjCryptLib_Sha256.h" +#include "sha256.h" #include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/WjCryptLib_Sha256.h b/sha256.h similarity index 98% rename from WjCryptLib_Sha256.h rename to sha256.h index cbee3d9..406ed86 100644 --- a/WjCryptLib_Sha256.h +++ b/sha256.h @@ -26,7 +26,6 @@ typedef struct } Sha256Context; #define SHA256_HASH_SIZE ( 256 / 8 ) -#define SHA256_BLOCK_SIZE ( 512 / 8 ) typedef struct {