From a3236c0f9d69fec8f053acd72a20b4d7cb237cd0 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Wed, 9 Oct 2024 11:24:36 +0530 Subject: [PATCH 01/12] feat: added ripemd160.cpp --- hashing/ripemd_160.cpp | 457 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 hashing/ripemd_160.cpp diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp new file mode 100644 index 00000000000..b7631e68bef --- /dev/null +++ b/hashing/ripemd_160.cpp @@ -0,0 +1,457 @@ +/** + * @file + * @author [Shree Harish S](https://github.com/ShreeHarish) + * @brief C++ implementation of the [RIPEMD-160 Hashing + * Algorithm](https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf) + * + * @details + * [RIPEMD-160](https://en.wikipedia.org/wiki/SHA-1) RIPEMD (RACE + * Integrity Primitives Evaluation Message Digest) is a cryptographic hash + * function designed to produce a 160-bit (20-byte) hash value from input data + * of arbitrary size. It was developed as a part of the RIPEMD family of hash + * functions in 1996 by a team of cryptographers including Ronald Rivest and + * others. RIPEMD-160 is used in some cryptocurrencies and blockchain + * technologies as part of their hashing mechanisms. + * + * Produces a fixed-size output of 160 bits (20 bytes), which is commonly + * represented as a 40-character hexadecimal string. + * + * RIPEMD-160 uses a Merkle-Damgård construction, meaning it processes the input + * data in blocks (512 bits) and produces a hash iteratively. It employs a total + * of 80 processing steps, split into two parallel paths that converge at the + * end. + * + */ + +#include /// For assert +#include /// For data types such as int32_t, uint32_t, etc +#include /// For functions like setw, setfill +#include /// For managing io +#include /// For bytes to hex string +#include /// For string data +#include /// To parallelize for efficiency +#include /// For dynamic arrays + +/** + * @namespace hashing + * @brief Hashing algorithms + */ +namespace hashing { +/** + * @class RIPEMD-160 + * @brief Implementation of relevant functions to perform RIPEMD160 hashing. + * This class expects a string to hash. + */ +class RIPEMD160 { + private: + /** + * @brief converts string data to vector of uint32_t (4 byte words) + * @details converts the string to 4 byte words in little endian format + * after adding padding and message length as specified in the algorithm + * @param data data to be converted + * @return vector of 4 byte words in little endian format + */ + std::vector string_to_word_data(std::string &data) { + std::vector word_data; + + // convert string data to 4 byte words in little endian format + for (uint64_t i = 0; i < (data.size() / 4) * 4; i += 4) { + word_data.push_back(static_cast(data[i]) | + (static_cast(data[i + 1]) << 8) | + (static_cast(data[i + 2]) << 16) | + (static_cast(data[i + 3]) << 24)); + } + + // add padding to data + int extra = data.size() % 4; + + if (extra == 0) { + word_data.push_back(0x00000080); + } + + else if (extra == 1) { + word_data.push_back(static_cast(data[data.size() - 1]) | + 0x00008000); + } + + else if (extra == 2) { + word_data.push_back( + static_cast(data[data.size() - 2]) | + (static_cast(data[data.size() - 1]) << 8) | + 0x00800000); + } + + else if (extra == 3) { + word_data.push_back( + static_cast(data[data.size() - 3]) | + (static_cast(data[data.size() - 2]) << 8) | + (static_cast(data[data.size() - 1]) << 16) | + 0x80000000); + } + + while (word_data.size() % 16 != 14) { + word_data.push_back(0x00000000); + } + + // add message length + word_data.push_back((static_cast(data.size()) << 3) & + 0xffffffff); + word_data.push_back((static_cast(data.size()) >> 29) & + 0xffffffff); + + return word_data; + } + + /** + * @brief implements f(j,x,y,z) + * @param j round number j / 16 + * @param x value x + * @param y value y + * @param z value z + * @return returns the function value + */ + uint32_t f(int j, uint32_t x, uint32_t y, uint32_t z) { + if (j == 0) { + return x ^ y ^ z; + } + + else if (j == 1) { + return (x & y) | (~x & z); + } + + else if (j == 2) { + return (x | ~y) ^ z; + } + + else if (j == 3) { + return (x & z) | (y & ~z); + } + + else { /// if (j == 4) + return x ^ (y | ~z); + } + } + + /** + * @brief implements K value for a given j + * @param j round number j / 16 + * @return appropriate K value + */ + uint32_t K(int j) { + if (j == 0) { + return static_cast(0x00000000); + } + + else if (j == 1) { + return static_cast(0x5A827999); + } + + else if (j == 2) { + return static_cast(0x6ED9EBA1); + } + + else if (j == 3) { + return static_cast(0x8F1BBCDC); + } + + else { /// if (j == 4) + return static_cast(0xA953FD4E); + } + } + + /** + * @brief implements K' value for a given j + * @param j round number j / 16 + * @return appropriate K' value + */ + uint32_t K_dash(int j) { + if (j == 0) { + return 0x50A28BE6; + } + + else if (j == 1) { + return 0x5C4DD124; + } + + else if (j == 2) { + return 0x6D703EF3; + } + + else if (j == 3) { + return 0x7A6D76E9; + } + + else { /// if (j == 4) + return 0x00000000; + } + } + + /** + * @brief implements r value for a given j + * @param j round number j + * @return appropriate r value + */ + int r(int j) { + static const int r_value[80] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; + + return r_value[j]; + } + + /** + * @brief implements r' value for a given j + * @param j round number j + * @return appropriate r' value + */ + int r_dash(int j) { + static const int r_dash_value[80] = { + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; + + return r_dash_value[j]; + } + + /** + * @brief implements s value for a given j + * @param j round number j + * @return appropriate s value + */ + int s(int j) { + static const int s_value[80] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; + + return s_value[j]; + } + + /** + * @brief implements s' value for a given j + * @param j round number j + * @return appropriate s' value + */ + int s_dash(int j) { + static const int s_dash_value[80] = { + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; + + return s_dash_value[j]; + } + + /** + * @brief cyclic left shift of uint32_t + * @param value value to be shifted + * @param shift number of bits to be shifted + * @return shifter value + */ + inline uint32_t cyclic_left_shift(uint32_t value, int shift) { + return (value << shift) | (value >> (32 - shift)); + } + + /** + * @brief computes the 80 rounds for current block + * @details hashing is performed on blocks of 512 bits and performed on two + * parallel path. this function performs one of the parallel path. + * @param A current value of A + * @param B current value of B + * @param C current value of C + * @param D current value of D + * @param E current value of E + * @param T current value of T. This is a temporary memory for computation + * @param current_block_data current 512 bits or 16 4-byte words that is + * being processed + * @return void + */ + void compute_for_block(int32_t *A, int32_t *B, int32_t *C, int32_t *D, + int32_t *E, int32_t *T, + const std::vector ¤t_block_data) { + for (int j = 0; j < 80; j++) { + *T = cyclic_left_shift(*A + f(j >> 4, *B, *C, *D) + + current_block_data[r(j)] + K(j >> 4), + s(j)) + + *E; + + *A = *E; + *E = *D; + *D = cyclic_left_shift(*C, 10); + *C = *B; + *B = *T; + } + } + + /** + * @brief computes the 80 rounds for current block + * @details hashing is performed on blocks of 512 bits and performed on two + * parallel path. this function performs the other parallel path. + * @param A current value of A_hash + * @param B current value of B_hash + * @param C current value of C_hash + * @param D current value of D_hash + * @param E current value of E_hash + * @param T current value of T_hash. This is a temporary memory for + * computation + * @param current_block_data current 512 bits or 16 4-byte words that is + * being processed + * @return void + */ + void compute_for_block_dash( + int32_t *A, int32_t *B, int32_t *C, int32_t *D, int32_t *E, int32_t *T, + const std::vector ¤t_block_data) { + for (int j = 0; j < 80; j++) { + *T = cyclic_left_shift(*A + f(4 - (j >> 4), *B, *C, *D) + + current_block_data[r_dash(j)] + + K_dash(j >> 4), + s_dash(j)) + + *E; + + *A = *E; + *E = *D; + *D = cyclic_left_shift(*C, 10); + *C = *B; + *B = *T; + } + } + + /** + * @brief converts from bytes in little endian format to string + * @param value value to be converted to string + * @return converted string value + */ + std::string uint32_t_to_string(uint32_t value) { + std::stringstream stream; + for (uint32_t i = 0; i < 4; ++i) { + stream << std::setfill('0') << std::setw(2) << std::hex + << ((value >> (i * 8)) & 0xff); + } + + return stream.str(); + } + + public: + /** + * @brief the hashing function that performs the RIPEMD-160 hashing + * @param data string data to be hashed + * @return hex of hash in string format + */ + std::string hash(std::string data) { + // convert string to 4-byte words including padding + std::vector word_data = string_to_word_data(data); + + // holds the current 512 bits of data to be processed + std::vector current_block_data; + + // initial state + int64_t h_0 = 0x67452301; + int64_t h_1 = 0xefcdab89; + int64_t h_2 = 0x98badcfe; + int64_t h_3 = 0x10325476; + int64_t h_4 = 0xc3d2e1f0; + + int32_t A = 0, B = 0, C = 0, D = 0, E = 0, T = 0; + int32_t A_dash = 0, B_dash = 0, C_dash = 0, D_dash = 0, E_dash = 0, + T_dash = 0; + + // for each 512 bits of data + for (uint64_t i = 0; i < word_data.size(); i += 16) { + current_block_data = std::vector( + word_data.begin() + i, word_data.begin() + i + 16); + + A = h_0; + B = h_1; + C = h_2; + D = h_3; + E = h_4; + + A_dash = h_0; + B_dash = h_1; + C_dash = h_2; + D_dash = h_3; + E_dash = h_4; + + // parallely process the 80 rounds + std::thread compute_for_block_thread(&compute_for_block, this, &A, + &B, &C, &D, &E, &T, + std::ref(current_block_data)); + std::thread compute_for_block_dash_thread( + &compute_for_block_dash, this, &A_dash, &B_dash, &C_dash, + &D_dash, &E_dash, &T_dash, std::ref(current_block_data)); + + compute_for_block_thread.join(); + compute_for_block_dash_thread.join(); + + // update the current state after 80 rounds + T = h_1 + C + D_dash; + h_1 = h_2 + D + E_dash; + h_2 = h_3 + E + A_dash; + h_3 = h_4 + A + B_dash; + h_4 = h_0 + B + C_dash; + h_0 = T; + } + + // convert the bytes in little endian format to hex in string format + std::string hash = ""; + hash = hash + uint32_t_to_string(h_0); + hash = hash + uint32_t_to_string(h_1); + hash = hash + uint32_t_to_string(h_2); + hash = hash + uint32_t_to_string(h_3); + hash = hash + uint32_t_to_string(h_4); + + return hash; + } +}; +} // namespace hashing + +/** + * @brief test example hashes + */ +static void check_me(std::string data, std::string expected_hash) { + hashing::RIPEMD160 obj; + + std::cout << "Hashing the data " + data + "\n"; + std::cout << "Obtained hash : " + obj.hash(data) + "\n"; + std::cout << "Expected hash : " + expected_hash + "\n"; + assert(obj.hash(data).compare(expected_hash) == 0); + std::cout + << "**********************************************************\n\n"; +} + +static void test() { + check_me("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"); + check_me("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); + check_me("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); + check_me("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"); + check_me("abcdefghijklmnopqrstuvwxyz", + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); + check_me("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "12a053384a9c0c88e405a06c27dcf49ada62eb2b"); + check_me( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0" + "123456789", + "b0e20b6e3116640286ed3a87a5713079b21f5189"); + check_me( + "12345678901234567890123456789012345678901234567890123" + "456789012345678901234567890", + "9b752e45573d4b39f4dbd3323cab82bf63326bfb"); +} + +/** + * @brief main function + * @return 0 on exit + */ +int main(int argc, char *argv[]) { + test(); + + return 0; +} \ No newline at end of file From 2747a0b3c07bd61a2cf5ae8fce3d1a92bf86051b Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Wed, 9 Oct 2024 19:57:54 +0530 Subject: [PATCH 02/12] Updated changes recommended in the previous pull request --- hashing/ripemd_160.cpp | 137 +++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 80 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index b7631e68bef..bde6d9877b9 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -1,6 +1,5 @@ /** * @file - * @author [Shree Harish S](https://github.com/ShreeHarish) * @brief C++ implementation of the [RIPEMD-160 Hashing * Algorithm](https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf) * @@ -21,10 +20,11 @@ * of 80 processing steps, split into two parallel paths that converge at the * end. * + * @author [Shree Harish S](https://github.com/ShreeHarish) */ #include /// For assert -#include /// For data types such as int32_t, uint32_t, etc +#include /// For data types such as std::int32_t, std::uint32_t, etc #include /// For functions like setw, setfill #include /// For managing io #include /// For bytes to hex string @@ -65,28 +65,30 @@ class RIPEMD160 { // add padding to data int extra = data.size() % 4; - if (extra == 0) { - word_data.push_back(0x00000080); - } - - else if (extra == 1) { - word_data.push_back(static_cast(data[data.size() - 1]) | - 0x00008000); - } - - else if (extra == 2) { - word_data.push_back( - static_cast(data[data.size() - 2]) | - (static_cast(data[data.size() - 1]) << 8) | - 0x00800000); - } - - else if (extra == 3) { - word_data.push_back( - static_cast(data[data.size() - 3]) | - (static_cast(data[data.size() - 2]) << 8) | - (static_cast(data[data.size() - 1]) << 16) | - 0x80000000); + switch (extra) { + case 0: + word_data.push_back(0x00000080); + break; + + case 1: + word_data.push_back( + static_cast(data[data.size() - 1]) | 0x00008000); + break; + + case 2: + word_data.push_back( + static_cast(data[data.size() - 2]) | + (static_cast(data[data.size() - 1]) << 8) | + 0x00800000); + break; + + case 3: + word_data.push_back( + static_cast(data[data.size() - 3]) | + (static_cast(data[data.size() - 2]) << 8) | + (static_cast(data[data.size() - 1]) << 16) | + 0x80000000); + break; } while (word_data.size() % 16 != 14) { @@ -105,30 +107,21 @@ class RIPEMD160 { /** * @brief implements f(j,x,y,z) * @param j round number j / 16 - * @param x value x - * @param y value y - * @param z value z + * @param B,C,D the state values * @return returns the function value */ - uint32_t f(int j, uint32_t x, uint32_t y, uint32_t z) { - if (j == 0) { - return x ^ y ^ z; - } - - else if (j == 1) { - return (x & y) | (~x & z); - } - - else if (j == 2) { - return (x | ~y) ^ z; - } - - else if (j == 3) { - return (x & z) | (y & ~z); - } - - else { /// if (j == 4) - return x ^ (y | ~z); + uint32_t f(int j, uint32_t B, uint32_t C, uint32_t D) { + switch(j) { + case 0: + return B ^ C ^ D; + case 1: + return (B & C) | (~B & D); + case 2: + return (B | ~C) ^ D; + case 3: + return (B & D) | (C & ~D); + case 4: + return B ^ (C | ~D); } } @@ -138,23 +131,15 @@ class RIPEMD160 { * @return appropriate K value */ uint32_t K(int j) { - if (j == 0) { - return static_cast(0x00000000); - } - - else if (j == 1) { + switch(j) { + case 0: return static_cast(0x00000000); + case 1: return static_cast(0x5A827999); - } - - else if (j == 2) { + case 2: return static_cast(0x6ED9EBA1); - } - - else if (j == 3) { + case 3: return static_cast(0x8F1BBCDC); - } - - else { /// if (j == 4) + case 4: return static_cast(0xA953FD4E); } } @@ -165,24 +150,17 @@ class RIPEMD160 { * @return appropriate K' value */ uint32_t K_dash(int j) { - if (j == 0) { - return 0x50A28BE6; - } - - else if (j == 1) { - return 0x5C4DD124; - } - - else if (j == 2) { - return 0x6D703EF3; - } - - else if (j == 3) { - return 0x7A6D76E9; - } - - else { /// if (j == 4) - return 0x00000000; + switch(j){ + case 0: + return 0x50A28BE6; + case 1: + return 0x5C4DD124; + case 2: + return 0x6D703EF3; + case 3: + return 0x7A6D76E9; + case 4: + return 0x00000000; } } @@ -452,6 +430,5 @@ static void test() { */ int main(int argc, char *argv[]) { test(); - return 0; -} \ No newline at end of file +} From 4df2421e05b37bb4239a8aabd422675a90d8ad2a Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Wed, 9 Oct 2024 20:18:19 +0530 Subject: [PATCH 03/12] modified functions that return array values to static constexpr arrays --- hashing/ripemd_160.cpp | 125 +++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 80 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index bde6d9877b9..cd8fb46562c 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -111,7 +111,7 @@ class RIPEMD160 { * @return returns the function value */ uint32_t f(int j, uint32_t B, uint32_t C, uint32_t D) { - switch(j) { + switch (j) { case 0: return B ^ C ^ D; case 1: @@ -131,16 +131,17 @@ class RIPEMD160 { * @return appropriate K value */ uint32_t K(int j) { - switch(j) { - case 0: return static_cast(0x00000000); - case 1: - return static_cast(0x5A827999); - case 2: - return static_cast(0x6ED9EBA1); - case 3: - return static_cast(0x8F1BBCDC); - case 4: - return static_cast(0xA953FD4E); + switch (j) { + case 0: + return static_cast(0x00000000); + case 1: + return static_cast(0x5A827999); + case 2: + return static_cast(0x6ED9EBA1); + case 3: + return static_cast(0x8F1BBCDC); + case 4: + return static_cast(0xA953FD4E); } } @@ -150,7 +151,7 @@ class RIPEMD160 { * @return appropriate K' value */ uint32_t K_dash(int j) { - switch(j){ + switch (j) { case 0: return 0x50A28BE6; case 1: @@ -159,74 +160,38 @@ class RIPEMD160 { return 0x6D703EF3; case 3: return 0x7A6D76E9; - case 4: + case 4: return 0x00000000; } } - /** - * @brief implements r value for a given j - * @param j round number j - * @return appropriate r value - */ - int r(int j) { - static const int r_value[80] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; - - return r_value[j]; - } - - /** - * @brief implements r' value for a given j - * @param j round number j - * @return appropriate r' value - */ - int r_dash(int j) { - static const int r_dash_value[80] = { - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; - - return r_dash_value[j]; - } - - /** - * @brief implements s value for a given j - * @param j round number j - * @return appropriate s value - */ - int s(int j) { - static const int s_value[80] = { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; - - return s_value[j]; - } - - /** - * @brief implements s' value for a given j - * @param j round number j - * @return appropriate s' value - */ - int s_dash(int j) { - static const int s_dash_value[80] = { - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; - - return s_dash_value[j]; - } + static constexpr int r[80] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; + + static constexpr int r_dash[80] = { + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; + + static constexpr int s[80] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; + + static constexpr int s_dash[80] = { + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; /** * @brief cyclic left shift of uint32_t @@ -257,8 +222,8 @@ class RIPEMD160 { const std::vector ¤t_block_data) { for (int j = 0; j < 80; j++) { *T = cyclic_left_shift(*A + f(j >> 4, *B, *C, *D) + - current_block_data[r(j)] + K(j >> 4), - s(j)) + + current_block_data[r[j]] + K(j >> 4), + s[j]) + *E; *A = *E; @@ -289,9 +254,9 @@ class RIPEMD160 { const std::vector ¤t_block_data) { for (int j = 0; j < 80; j++) { *T = cyclic_left_shift(*A + f(4 - (j >> 4), *B, *C, *D) + - current_block_data[r_dash(j)] + + current_block_data[r_dash[j]] + K_dash(j >> 4), - s_dash(j)) + + s_dash[j]) + *E; *A = *E; From a1c55b99e70972929602029602e47099d8c72025 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Thu, 10 Oct 2024 20:57:28 +0530 Subject: [PATCH 04/12] updated latest requests --- hashing/ripemd_160.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index cd8fb46562c..b7b48114c3b 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -357,7 +357,8 @@ class RIPEMD160 { } // namespace hashing /** - * @brief test example hashes + * @brief self test implementation + * @return void */ static void check_me(std::string data, std::string expected_hash) { hashing::RIPEMD160 obj; @@ -393,7 +394,7 @@ static void test() { * @brief main function * @return 0 on exit */ -int main(int argc, char *argv[]) { - test(); +int main() { + test(); // run self test implementation return 0; } From f6ea88b79f5b64749ab82dabccdaec3379cf2499 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sat, 12 Oct 2024 14:10:39 +0530 Subject: [PATCH 05/12] updated documentation --- hashing/ripemd_160.cpp | 178 ++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 72 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index b7b48114c3b..afdaf983e93 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -25,7 +25,7 @@ #include /// For assert #include /// For data types such as std::int32_t, std::uint32_t, etc -#include /// For functions like setw, setfill +#include /// For functions like std::setw, std::setfill #include /// For managing io #include /// For bytes to hex string #include /// For string data @@ -45,70 +45,10 @@ namespace hashing { class RIPEMD160 { private: /** - * @brief converts string data to vector of uint32_t (4 byte words) - * @details converts the string to 4 byte words in little endian format - * after adding padding and message length as specified in the algorithm - * @param data data to be converted - * @return vector of 4 byte words in little endian format - */ - std::vector string_to_word_data(std::string &data) { - std::vector word_data; - - // convert string data to 4 byte words in little endian format - for (uint64_t i = 0; i < (data.size() / 4) * 4; i += 4) { - word_data.push_back(static_cast(data[i]) | - (static_cast(data[i + 1]) << 8) | - (static_cast(data[i + 2]) << 16) | - (static_cast(data[i + 3]) << 24)); - } - - // add padding to data - int extra = data.size() % 4; - - switch (extra) { - case 0: - word_data.push_back(0x00000080); - break; - - case 1: - word_data.push_back( - static_cast(data[data.size() - 1]) | 0x00008000); - break; - - case 2: - word_data.push_back( - static_cast(data[data.size() - 2]) | - (static_cast(data[data.size() - 1]) << 8) | - 0x00800000); - break; - - case 3: - word_data.push_back( - static_cast(data[data.size() - 3]) | - (static_cast(data[data.size() - 2]) << 8) | - (static_cast(data[data.size() - 1]) << 16) | - 0x80000000); - break; - } - - while (word_data.size() % 16 != 14) { - word_data.push_back(0x00000000); - } - - // add message length - word_data.push_back((static_cast(data.size()) << 3) & - 0xffffffff); - word_data.push_back((static_cast(data.size()) >> 29) & - 0xffffffff); - - return word_data; - } - - /** - * @brief implements f(j,x,y,z) - * @param j round number j / 16 - * @param B,C,D the state values - * @return returns the function value + * @brief Implements f(j,x,y,z) + * @param j Round number j / 16 + * @param B,C,D The state values + * @return Returns the function value */ uint32_t f(int j, uint32_t B, uint32_t C, uint32_t D) { switch (j) { @@ -126,9 +66,9 @@ class RIPEMD160 { } /** - * @brief implements K value for a given j - * @param j round number j / 16 - * @return appropriate K value + * @brief Implements K value for a given j + * @param j Round number j / 16 + * @return Appropriate K value */ uint32_t K(int j) { switch (j) { @@ -146,9 +86,9 @@ class RIPEMD160 { } /** - * @brief implements K' value for a given j - * @param j round number j / 16 - * @return appropriate K' value + * @brief Implements K' value for a given j + * @param j Round number j / 16 + * @return Appropriate K' value */ uint32_t K_dash(int j) { switch (j) { @@ -165,6 +105,14 @@ class RIPEMD160 { } } + /** + * @brief Specifies r value for a given j. + * + * @details Specifies the order in which 4-byte words of the current + * 512-bits block are accessed and processed in each step of the compression + * function. Introduces non-linearity to the code. It is used by one of the + * parallel path. + */ static constexpr int r[80] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, @@ -172,6 +120,14 @@ class RIPEMD160 { 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; + /** + * @brief Specifies the r' value a given j. + * + * @details Specifies the order in which 4-byte words of the current + * 512-bits block are accessed and processed in each step of the compression + * function. Introduces non-linearity to the code. It is used in the other + * parallel path. + */ static constexpr int r_dash[80] = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, @@ -179,6 +135,15 @@ class RIPEMD160 { 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; + /** + * @brief Specifies the s value for a given j. + * + * @details Determines the number of bits to cyclically shift (left rotate) + * the result of each step. The different shift values prevent patterns from + * emerging in the output, which is crucial for achieving properties like + * the avalanche effect (where a small change in the input results in a + * large change in the output). It is used by one of the parallel path. + */ static constexpr int s[80] = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, @@ -186,6 +151,15 @@ class RIPEMD160 { 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; + /** + * @brief Specifies the s' value for a given j. + * + * @details Determines the number of bits to cyclically shift (left rotate) + * the result of each step. The different shift values prevent patterns from + * emerging in the output, which is crucial for achieving properties like + * the avalanche effect (where a small change in the input results in a + * large change in the output). It is used in the other parallel path. + */ static constexpr int s_dash[80] = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, @@ -193,6 +167,66 @@ class RIPEMD160 { 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; + /** + * @brief converts string data to vector of uint32_t (4 byte words) + * @details converts the string to 4 byte words in little endian format + * after adding padding and message length as specified in the algorithm + * @param data data to be converted + * @return vector of 4 byte words in little endian format + */ + std::vector string_to_word_data(std::string &data) { + std::vector word_data; + + // convert string data to 4 byte words in little endian format + for (uint64_t i = 0; i < (data.size() / 4) * 4; i += 4) { + word_data.push_back(static_cast(data[i]) | + (static_cast(data[i + 1]) << 8) | + (static_cast(data[i + 2]) << 16) | + (static_cast(data[i + 3]) << 24)); + } + + // add padding to data + int extra = data.size() % 4; + + switch (extra) { + case 0: + word_data.push_back(0x00000080); + break; + + case 1: + word_data.push_back( + static_cast(data[data.size() - 1]) | 0x00008000); + break; + + case 2: + word_data.push_back( + static_cast(data[data.size() - 2]) | + (static_cast(data[data.size() - 1]) << 8) | + 0x00800000); + break; + + case 3: + word_data.push_back( + static_cast(data[data.size() - 3]) | + (static_cast(data[data.size() - 2]) << 8) | + (static_cast(data[data.size() - 1]) << 16) | + 0x80000000); + break; + } + + while (word_data.size() % 16 != 14) { + word_data.push_back(0x00000000); + } + + // add message length + word_data.push_back((static_cast(data.size()) << 3) & + 0xffffffff); + word_data.push_back((static_cast(data.size()) >> 29) & + 0xffffffff); + + return word_data; + } + /** * @brief cyclic left shift of uint32_t * @param value value to be shifted @@ -395,6 +429,6 @@ static void test() { * @return 0 on exit */ int main() { - test(); // run self test implementation + test(); // run self test implementation return 0; } From 4ad21eef5f9043a9bc8719a70dbd0b56cc4219e5 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sat, 12 Oct 2024 14:12:51 +0530 Subject: [PATCH 06/12] updated documentation --- hashing/ripemd_160.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index afdaf983e93..4aee8fbd69c 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -45,7 +45,7 @@ namespace hashing { class RIPEMD160 { private: /** - * @brief Implements f(j,x,y,z) + * @brief Implements f(j,B,C,D) * @param j Round number j / 16 * @param B,C,D The state values * @return Returns the function value From 699090a5752dceb8ce489a6dd4660571f527a555 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sat, 12 Oct 2024 16:13:06 +0530 Subject: [PATCH 07/12] updated test function --- hashing/ripemd_160.cpp | 47 ++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index 4aee8fbd69c..d0068a05acb 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -394,34 +394,27 @@ class RIPEMD160 { * @brief self test implementation * @return void */ -static void check_me(std::string data, std::string expected_hash) { - hashing::RIPEMD160 obj; - - std::cout << "Hashing the data " + data + "\n"; - std::cout << "Obtained hash : " + obj.hash(data) + "\n"; - std::cout << "Expected hash : " + expected_hash + "\n"; - assert(obj.hash(data).compare(expected_hash) == 0); - std::cout - << "**********************************************************\n\n"; -} - static void test() { - check_me("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"); - check_me("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); - check_me("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); - check_me("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"); - check_me("abcdefghijklmnopqrstuvwxyz", - "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); - check_me("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "12a053384a9c0c88e405a06c27dcf49ada62eb2b"); - check_me( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0" - "123456789", - "b0e20b6e3116640286ed3a87a5713079b21f5189"); - check_me( - "12345678901234567890123456789012345678901234567890123" - "456789012345678901234567890", - "9b752e45573d4b39f4dbd3323cab82bf63326bfb"); + hashing::RIPEMD160 obj; + assert(obj.hash("").compare("9c1185a5c5e9fc54612808977ee8f548b2258d31") == + 0); + assert(obj.hash("a").compare("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe") == + 0); + assert(obj.hash("abc").compare( + "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc") == 0); + assert(obj.hash("message digest") + .compare("5d0689ef49d2fae572b881b123a85ffa21595f36") == 0); + assert(obj.hash("abcdefghijklmnopqrstuvwxyz") + .compare("f71c27109c692c1b56bbdceb5b9d2865b3708dbc") == 0); + assert(obj.hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") + .compare("12a053384a9c0c88e405a06c27dcf49ada62eb2b") == 0); + assert( + obj.hash( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") + .compare("b0e20b6e3116640286ed3a87a5713079b21f5189") == 0); + assert(obj.hash("1234567890123456789012345678901234567890123456789012345678" + "9012345678901234567890") + .compare("9b752e45573d4b39f4dbd3323cab82bf63326bfb") == 0); } /** From 930521da1d3854abc3a62d57d1fa7f1604bf021b Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sun, 13 Oct 2024 09:26:30 +0530 Subject: [PATCH 08/12] resolved warnings for control reaching end of function --- hashing/ripemd_160.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index d0068a05acb..eea5bd456f4 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -28,9 +28,10 @@ #include /// For functions like std::setw, std::setfill #include /// For managing io #include /// For bytes to hex string -#include /// For string data -#include /// To parallelize for efficiency -#include /// For dynamic arrays +#include /// For standard exceptions like std::runtime_error +#include /// For string data +#include /// To parallelize for efficiency +#include /// For dynamic arrays /** * @namespace hashing @@ -49,6 +50,7 @@ class RIPEMD160 { * @param j Round number j / 16 * @param B,C,D The state values * @return Returns the function value + * @note 0 <= j <= 4 */ uint32_t f(int j, uint32_t B, uint32_t C, uint32_t D) { switch (j) { @@ -63,12 +65,15 @@ class RIPEMD160 { case 4: return B ^ (C | ~D); } + + throw std::runtime_error("j value out of bound"); } /** * @brief Implements K value for a given j * @param j Round number j / 16 * @return Appropriate K value + * @note 0 <= j <= 4 */ uint32_t K(int j) { switch (j) { @@ -83,12 +88,15 @@ class RIPEMD160 { case 4: return static_cast(0xA953FD4E); } + + throw std::runtime_error("j value out of bound"); } /** * @brief Implements K' value for a given j * @param j Round number j / 16 * @return Appropriate K' value + * @note 0 <= j <= 4 */ uint32_t K_dash(int j) { switch (j) { @@ -103,6 +111,8 @@ class RIPEMD160 { case 4: return 0x00000000; } + + throw std::runtime_error("j value out of bound"); } /** From 3ed8981293e98acae344144b2215698ce3196388 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sun, 13 Oct 2024 16:23:59 +0530 Subject: [PATCH 09/12] updated error handling --- hashing/ripemd_160.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index eea5bd456f4..91296fe215d 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -28,7 +28,7 @@ #include /// For functions like std::setw, std::setfill #include /// For managing io #include /// For bytes to hex string -#include /// For standard exceptions like std::runtime_error +#include /// For standard exceptions like std::invalid_argument #include /// For string data #include /// To parallelize for efficiency #include /// For dynamic arrays @@ -64,9 +64,9 @@ class RIPEMD160 { return (B & D) | (C & ~D); case 4: return B ^ (C | ~D); + default: + throw std::invalid_argument("j value out of bound"); } - - throw std::runtime_error("j value out of bound"); } /** @@ -87,9 +87,9 @@ class RIPEMD160 { return static_cast(0x8F1BBCDC); case 4: return static_cast(0xA953FD4E); + default: + throw std::invalid_argument("j value out of bound"); } - - throw std::runtime_error("j value out of bound"); } /** @@ -110,9 +110,9 @@ class RIPEMD160 { return 0x7A6D76E9; case 4: return 0x00000000; + default: + throw std::invalid_argument("j value out of bound"); } - - throw std::runtime_error("j value out of bound"); } /** From 3cce6fd3516be65057567b6c0835acf57b806a69 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Sat, 19 Oct 2024 16:15:56 +0530 Subject: [PATCH 10/12] updated comments for readability and placed tables at top --- hashing/ripemd_160.cpp | 114 +++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 62 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index 91296fe215d..70a8f0b0d6c 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -12,6 +12,18 @@ * others. RIPEMD-160 is used in some cryptocurrencies and blockchain * technologies as part of their hashing mechanisms. * + * The r and r' table specifies the order in which 4-byte words of the current + * 512-bits block are accessed and processed in each step of the compression + * function. It introduces non-linearity to the code. The r table is utilised by + * one of the parallel path and the r' table by the other. + * + * The s and s' table dtermines the number of bits to cyclically shift (left + * rotate) the result of each step. The different shift values prevent patterns + * from emerging in the output, which is crucial for achieving properties like + * the avalanche effect (where a small change in the input results in a + * large change in the output). The s table is utilised by + * one of the parallel path and these s' table by the other. + * * Produces a fixed-size output of 160 bits (20 bytes), which is commonly * represented as a 40-character hexadecimal string. * @@ -45,6 +57,46 @@ namespace hashing { */ class RIPEMD160 { private: + /** + * @brief Implements the r table + */ + static constexpr int r[80] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; + + /** + * @brief Implements the r' table + */ + static constexpr int r_dash[80] = { + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; + + /** + * @brief Implements the s table + */ + static constexpr int s[80] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; + + /** + * @brief Implements the s' table + */ + static constexpr int s_dash[80] = { + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; + /** * @brief Implements f(j,B,C,D) * @param j Round number j / 16 @@ -115,68 +167,6 @@ class RIPEMD160 { } } - /** - * @brief Specifies r value for a given j. - * - * @details Specifies the order in which 4-byte words of the current - * 512-bits block are accessed and processed in each step of the compression - * function. Introduces non-linearity to the code. It is used by one of the - * parallel path. - */ - static constexpr int r[80] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; - - /** - * @brief Specifies the r' value a given j. - * - * @details Specifies the order in which 4-byte words of the current - * 512-bits block are accessed and processed in each step of the compression - * function. Introduces non-linearity to the code. It is used in the other - * parallel path. - */ - static constexpr int r_dash[80] = { - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; - - /** - * @brief Specifies the s value for a given j. - * - * @details Determines the number of bits to cyclically shift (left rotate) - * the result of each step. The different shift values prevent patterns from - * emerging in the output, which is crucial for achieving properties like - * the avalanche effect (where a small change in the input results in a - * large change in the output). It is used by one of the parallel path. - */ - static constexpr int s[80] = { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; - - /** - * @brief Specifies the s' value for a given j. - * - * @details Determines the number of bits to cyclically shift (left rotate) - * the result of each step. The different shift values prevent patterns from - * emerging in the output, which is crucial for achieving properties like - * the avalanche effect (where a small change in the input results in a - * large change in the output). It is used in the other parallel path. - */ - static constexpr int s_dash[80] = { - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; - /** * @brief converts string data to vector of uint32_t (4 byte words) * @details converts the string to 4 byte words in little endian format From df9bd8d82f9e2ce8732302136f775b4c7783c7b8 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Tue, 22 Oct 2024 19:42:09 +0530 Subject: [PATCH 11/12] modified comments for tables --- hashing/ripemd_160.cpp | 61 +++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index 70a8f0b0d6c..d8a46d0e227 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -57,45 +57,38 @@ namespace hashing { */ class RIPEMD160 { private: - /** - * @brief Implements the r table - */ static constexpr int r[80] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, + 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, + 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, + 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, + 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}; /// Implements the r + /// table - /** - * @brief Implements the r' table - */ static constexpr int r_dash[80] = { - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, + 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, + 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, + 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, + 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}; /// Implements the r' + /// table + + static constexpr int s[80] = {11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, + 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, + 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, + 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, + 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, + 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, + 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, + 8, 5, 6}; /// Implements the s table - /** - * @brief Implements the s table - */ - static constexpr int s[80] = { - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}; - - /** - * @brief Implements the s' table - */ static constexpr int s_dash[80] = { - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, + 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, + 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, + 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, + 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}; /// Implements the s' + /// table /** * @brief Implements f(j,B,C,D) From a3fc834c754de8ea52921a08c48e856c7b62eeb7 Mon Sep 17 00:00:00 2001 From: Shree Harish S Date: Tue, 29 Oct 2024 22:57:02 +0530 Subject: [PATCH 12/12] modified function name parameter when passing to thread with class name to evade errors when built on mac environment --- hashing/ripemd_160.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hashing/ripemd_160.cpp b/hashing/ripemd_160.cpp index d8a46d0e227..191d8963655 100644 --- a/hashing/ripemd_160.cpp +++ b/hashing/ripemd_160.cpp @@ -351,12 +351,13 @@ class RIPEMD160 { E_dash = h_4; // parallely process the 80 rounds - std::thread compute_for_block_thread(&compute_for_block, this, &A, - &B, &C, &D, &E, &T, + std::thread compute_for_block_thread(&RIPEMD160::compute_for_block, + this, &A, &B, &C, &D, &E, &T, std::ref(current_block_data)); std::thread compute_for_block_dash_thread( - &compute_for_block_dash, this, &A_dash, &B_dash, &C_dash, - &D_dash, &E_dash, &T_dash, std::ref(current_block_data)); + &RIPEMD160::compute_for_block_dash, this, &A_dash, &B_dash, + &C_dash, &D_dash, &E_dash, &T_dash, + std::ref(current_block_data)); compute_for_block_thread.join(); compute_for_block_dash_thread.join();