-/*
- * ReMD5.cpp
- *
- * Created on: 30.01.2015
- *
- */
-
-#include "base/rebase.hpp"
-#include "math/remath.hpp"
-
-#define __LITTLE_ENDIAN__
-
-const int ReMD5::m_s[64] = {
- 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
- 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
- 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
- 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
-};
-static int s_ix = 0;
-// for x in [1..64] : int(2**32 * sin(x))
-const uint32_t ReMD5::m_K[64] = {
- 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
- 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
- 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
- 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
- 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
- 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
- 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
- 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
- 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
- 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
- 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
- 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
- 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
- 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
- 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
- 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
-};
-
-/**
- * Constructor.
- */
-ReMD5::ReMD5() :
- //m_digest
- // m_hexDigest;
- // m_waiting[64];
- m_lengthWaiting(0),
- m_length(0),
- m_a0(0x67452301),
- m_b0(0xefcdab89),
- m_c0(0x98badcfe),
- m_d0(0x10325476),
- m_finalized(false)
-{
-}
-
-/**
- * Destructor.
- */
-ReMD5::~ReMD5() {
-}
-
-/**
- * Returns the binary digest value.
- *
- * @return the binary digest (16 byte array)
- */
-const uint8_t* ReMD5::digest(){
- if (! m_finalized){
- finalize();
- }
- return m_digest;
-}
-
-/**
- * Finalizes the digest.
- *
- * Handles the rest block (< 64 byte) and append a special tail: a "1" bit
- * and the length of the total input length (in bits).
- *
- * @param block the rest input (incomplete chunk)
- * @param blockLength the length of the block: 0..63
- */
-void ReMD5::finalize(){
- uint8_t* block = m_waiting;
- int blockLength = m_lengthWaiting;
- // append "1" bit to message
- // Notice: the input bytes are considered as bits strings,
- // where the first bit is the most significant bit of the byte.
- block[blockLength++] = 0x80;
- //Pre-processing: padding with zeros
- //append "0" bit until message length in bits ≡ 448 (mod 512)
- // fill the rest of the chunk with '\0'.
- // the last 8 bytes is set to the length in bits (length in bytes * 8)
- int restLength = (m_length + 1) % 64;
- // 0 -> 56, 1 -> 55, 2 -> 54, ... 55 -> 1, 56 -> 0,
- // 57 -> 63, 58 -> 62, ... 63 -> 57
- int zeros = restLength <= 56 ? 56 - restLength : 120 - restLength;
- memset(block + blockLength, 0, zeros);
- blockLength += zeros;
- //append original length in bits mod (2 pow 64) to message
- uint64_t lengthBits = 8LL * m_length;
-#if defined __LITTLE_ENDIAN__
- memcpy(block + blockLength, &lengthBits, 8);
- blockLength += 8;
-#else
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
- lengthBits >>= 8;
- block[blockLength++] = lengthBits;
-#endif
- processChunk(block);
- if (blockLength > 64)
- processChunk(block + 64);
-#if defined __LITTLE_ENDIAN__
- memcpy(m_digest, &m_a0, 4);
- memcpy(m_digest + 4, &m_b0, 4);
- memcpy(m_digest + 8, &m_c0, 4);
- memcpy(m_digest + 12, &m_d0, 4);
-#else
-#define oneWord(word, ix) m_digest[ix] = word; word >>= 8; \
- m_digest[ix + 1] = word; word >>= 8; m_digest[ix + 2] = word; word >>= 8; \
- m_digest[ix + 3] = word
- oneWord(m_a0, 0);
- oneWord(m_b0, 4);
- oneWord(m_c0, 8);
- oneWord(m_d0, 12);
-#endif
-}
-
-/**
- * Returns the binary digest value.
- *
- * @return the binary digest (16 byte array)
- */
-const ReByteBuffer& ReMD5::hexDigest(){
- if (m_hexDigest.length() == 0){
- digest();
- for (int ix = 0; ix < 16; ix++){
- m_hexDigest.appendInt(m_digest[ix], "%02x");
- }
- }
- return m_hexDigest;
-}
-
-/**
- * Processes a 512 bit block ("chunk").
- */
-void ReMD5::processChunk2(const uint8_t block[64]){
- uint32_t M[16];
- // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
-#ifdef __LITTLE_ENDIAN__
- for (int ix = 0; ix < 16; ix++){
- memcpy(&M[ix], block + ix * 4, 4);
- //M[ix] = * (uint32_t*) (block + ix*4);
- }
-#elif defined __BIG_ENDIAN__
- for (int ix = 0; ix < 16; ix++){
- uint32_t x = block[3];
- for (int jj = 2; jj >= 0; jj--){
- x = (x << 8) + block[jj];
- }
- M[ix] = x;
- block += 4;
- }
-#else
-# error "missing __LITTLE_ENDIAN__ or __BIG_ENDIAN__"
-#endif
- //Initialize hash value for this chunk:
- uint32_t A = m_a0;
- uint32_t B = m_b0;
- uint32_t C = m_c0;
- uint32_t D = m_d0;
- //Main loop:
-
- int F, g;
-//#define TRACE_MD5
-#if defined TRACE_MD5
- printf("neu: (%s)\n", block);
-#endif
- for (int i = 0; i < 64; i++){
-#if defined TRACE_MD5
- if (i < 8)
- printf("%2d: A: %08x B: %08x C: %08x D%08x\n", i, A, B, C, D);
-#endif
- if (i < 16){
-# define F1(B, C, D) ((B & C) | (~ B & D))
- // F := (B and C) or ((not B) and D)
- F = F1(B, C, D);
- g = i;
- } else if (i < 32){
- // F := (D and B) or (C and (not D))
- // g := (5×i + 1) mod 16
-# define F2(B, C, D) ((D & B) | (C & ~ D))
- F = F2(B, C, D);
- g = (5*i + 1) % 16;
- } else if (i < 48){
- // F := B xor C xor D
- // g := (3×i + 5) mod 16
-# define F3(B, C, D) ((B ^ C) ^ D)
- F = F3(B, C, D);
- g = (3*i + 5) % 16;
- } else {
- // F := C xor (B or (not D))
-# define F4(B, C, D) (C ^ (B | ~ D))
- // g := (7×i) mod 16
- F = F4(B, C, D);
- g = (7*i) % 16;
- }
-#if defined TRACE_MD5
- if (i < 8)
- printf(" K[%2d]: %08x M[%2d]: %08x shift: %02d\n",
- i, m_K[i], g, M[g], m_s[i]);
-#endif
- uint32_t dTemp = D;
- D = C;
- C = B;
- // B := B + leftrotate((A + F + K[i] + M[g]), s[i])
- uint32_t x = (A + F + m_K[i] + M[g]);
- int shift = m_s[i];
- B += (x << shift) | (x >> (32 - shift));
- A = dTemp;
- }
- //Add this chunk's hash to result so far:
- m_a0 += A;
- m_b0 += B;
- m_c0 += C;
- m_d0 += D;
-}
-/** ----------------------
- */
-
-inline uint32_t rotate_left(uint32_t x, int n) {
- return (x << n) | (x >> (32-n));
-}
-
-inline void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z,
- uint32_t data, uint32_t aConst, uint32_t shift) {
-//#define TRACE_MD5
-#if defined TRACE_MD5
- printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);
- printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",
- s_ix - 1, aConst, data, shift);
-#endif
- var = rotate_left(var+ F1(x, y, z) + data + aConst, shift) + x;
-}
-
-inline void X2(uint32_t& var, uint32_t x, uint32_t y, uint32_t z,
- uint32_t data, uint32_t aConst, uint32_t shift) {
-#if defined TRACE_MD5
- printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);
- printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",
- s_ix - 1, aConst, data, shift);
-#endif
- var = rotate_left(var + F2(x, y, z) + data + aConst, shift) + x;
-}
-
-inline void X3(uint32_t& var, uint32_t x, uint32_t y, uint32_t z,
- uint32_t data, uint32_t aConst, uint32_t shift) {
-#if defined TRACE_MD5
- printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);
- printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",
- s_ix - 1, aConst, data, shift);
-#endif
- var = rotate_left(var + F3(x, y, z) + data + aConst, shift) + x;
-}
-
-inline void X4(uint32_t& var, uint32_t x, uint32_t y, uint32_t z,
- uint32_t data, uint32_t aConst, uint32_t shift) {
-#if defined TRACE_MD5
- printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);
- printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",
- s_ix - 1, aConst, data, shift);
-#endif
- var = rotate_left(var + F4(x, y, z) + data + aConst, shift) + x;
-}
-/**
- * Processes a 512 bit block ("chunk").
- */
-void ReMD5::processChunk(const uint8_t block[64]){
- uint32_t M[16];
- // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
-#ifdef __LITTLE_ENDIAN__
- for (int ix = 0; ix < 16; ix++){
- //memcpy(&M[ix], block + ix * 4, 4);
- M[ix] = * (uint32_t*) (block + ix*4);
- }
-#elif defined __BIG_ENDIAN__
- for (int ix = 0; ix < 16; ix++){
- uint32_t x = block[3];
- for (int jj = 2; jj >= 0; jj--){
- x = (x << 8) + block[jj];
- }
- M[ix] = x;
- block += 4;
- }
-#else
-# error "missing __LITTLE_ENDIAN__ or __BIG_ENDIAN__"
-#endif
- //Initialize hash value for this chunk:
- uint32_t A = m_a0;
- uint32_t B = m_b0;
- uint32_t C = m_c0;
- uint32_t D = m_d0;
-#if 0
- // B := B + leftrotate((A + F + K[i] + M[g]), s[i])
- // D := C;
- // C := B;
- // B := B + leftrotate((A + F + K[i] + M[g]), s[i])
- // A := D(old)
- // (D, C, B, A) = (C, B, B + leftrotate((A + F + K[i] + M[g]), s[i]), D)
- // ==> (A, B, C, D) = (D, B + leftrotate((A + F + K[i] + M[g]), s[i]), B, A)
- // The unrolled loop:
- //i = g = 0;
- (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[0] + M[0]), s[0]), B, A)
- // only one var must be calculated, the other 3 are exchanged only.
- //i = g = 1;
- (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[1] + M[1]), s[1]), B, A)
- //i = g = 2;
- (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[2] + M[2]), s[2]), B, A)
- //i = g = 3;
- (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[3] + M[3]), s[3]), B, A)
- // in each of the 4 statements another variable (of A, B, C and D) will be calculated
- // so we do not exchange in each step, we calculate in the end position
- // we define a function to do this:
- void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, uint32_t data, uint32_t shift, uint32_t aConst){
- var = rotate_left(var+ F1(x, y, z) + data + aConst, shift) + x;
- }
- // note: the input parameter of of X1 must respect the exchange:
- // A -> D -> C -> B ...
- X1(A, B, C, D, M[0], K[0], s[0]);
- X1(D, A, B, C, M[1], K[1], s[1]);
- X1(C, D, A, B, M[2], K[2], s[2]);
- X1(B, C, D, A, M[3], K[3], s[3]);
- // ...
-#endif
- /* Round 1 */
+/*\r
+ * ReMD5.cpp\r
+ *\r
+ * Created on: 30.01.2015\r
+ *\r
+ */\r
+\r
+#include "base/rebase.hpp"\r
+#include "math/remath.hpp"\r
+\r
+#define __LITTLE_ENDIAN__\r
+\r
+const int ReMD5::m_s[64] = {\r
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,\r
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,\r
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,\r
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21\r
+};\r
+static int s_ix = 0;\r
+// for x in [1..64] : int(2**32 * sin(x))\r
+const uint32_t ReMD5::m_K[64] = {\r
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,\r
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,\r
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,\r
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,\r
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,\r
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,\r
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,\r
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,\r
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,\r
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,\r
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,\r
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,\r
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,\r
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,\r
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,\r
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391\r
+};\r
+\r
+/**\r
+ * Constructor.\r
+ */\r
+ReMD5::ReMD5() :\r
+ //m_digest\r
+ // m_hexDigest;\r
+ // m_waiting[64];\r
+ m_lengthWaiting(0),\r
+ m_length(0),\r
+ m_a0(0x67452301),\r
+ m_b0(0xefcdab89),\r
+ m_c0(0x98badcfe),\r
+ m_d0(0x10325476),\r
+ m_finalized(false)\r
+{\r
+}\r
+\r
+/**\r
+ * Destructor.\r
+ */\r
+ReMD5::~ReMD5() {\r
+}\r
+\r
+/**\r
+ * Returns the binary digest value.\r
+ *\r
+ * @return the binary digest (16 byte array)\r
+ */\r
+const uint8_t* ReMD5::digest(){\r
+ if (! m_finalized){\r
+ finalize();\r
+ }\r
+ return m_digest;\r
+}\r
+\r
+/**\r
+ * Finalizes the digest.\r
+ *\r
+ * Handles the rest block (< 64 byte) and append a special tail: a "1" bit\r
+ * and the length of the total input length (in bits).\r
+ *\r
+ * @param block the rest input (incomplete chunk)\r
+ * @param blockLength the length of the block: 0..63\r
+ */\r
+void ReMD5::finalize(){\r
+ uint8_t* block = m_waiting;\r
+ int blockLength = m_lengthWaiting;\r
+ // append "1" bit to message\r
+ // Notice: the input bytes are considered as bits strings,\r
+ // where the first bit is the most significant bit of the byte.\r
+ block[blockLength++] = 0x80;\r
+ //Pre-processing: padding with zeros\r
+ //append "0" bit until message length in bits ≡ 448 (mod 512)\r
+ // fill the rest of the chunk with '\0'.\r
+ // the last 8 bytes is set to the length in bits (length in bytes * 8)\r
+ int restLength = (m_length + 1) % 64;\r
+ // 0 -> 56, 1 -> 55, 2 -> 54, ... 55 -> 1, 56 -> 0,\r
+ // 57 -> 63, 58 -> 62, ... 63 -> 57\r
+ int zeros = restLength <= 56 ? 56 - restLength : 120 - restLength;\r
+ memset(block + blockLength, 0, zeros);\r
+ blockLength += zeros;\r
+ //append original length in bits mod (2 pow 64) to message\r
+ uint64_t lengthBits = 8LL * m_length;\r
+#if defined __LITTLE_ENDIAN__\r
+ memcpy(block + blockLength, &lengthBits, 8);\r
+ blockLength += 8;\r
+#else\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+ lengthBits >>= 8;\r
+ block[blockLength++] = lengthBits;\r
+#endif\r
+ processChunk(block);\r
+ if (blockLength > 64)\r
+ processChunk(block + 64);\r
+#if defined __LITTLE_ENDIAN__\r
+ memcpy(m_digest, &m_a0, 4);\r
+ memcpy(m_digest + 4, &m_b0, 4);\r
+ memcpy(m_digest + 8, &m_c0, 4);\r
+ memcpy(m_digest + 12, &m_d0, 4);\r
+#else\r
+#define oneWord(word, ix) m_digest[ix] = word; word >>= 8; \\r
+ m_digest[ix + 1] = word; word >>= 8; m_digest[ix + 2] = word; word >>= 8; \\r
+ m_digest[ix + 3] = word\r
+ oneWord(m_a0, 0);\r
+ oneWord(m_b0, 4);\r
+ oneWord(m_c0, 8);\r
+ oneWord(m_d0, 12);\r
+#endif\r
+}\r
+\r
+/**\r
+ * Returns the binary digest value.\r
+ *\r
+ * @return the binary digest (16 byte array)\r
+ */\r
+const ReByteBuffer& ReMD5::hexDigest(){\r
+ if (m_hexDigest.length() == 0){\r
+ digest();\r
+ for (int ix = 0; ix < 16; ix++){\r
+ m_hexDigest.appendInt(m_digest[ix], "%02x");\r
+ }\r
+ }\r
+ return m_hexDigest;\r
+}\r
+\r
+/**\r
+ * Processes a 512 bit block ("chunk").\r
+ *\r
+ * This method is a direct programming of the algorithm described in wikipedia.\r
+ */\r
+void ReMD5::processChunk2(const uint8_t block[64]){\r
+ uint32_t M[16];\r
+ // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15\r
+ for (int ix = 0; ix < 16; ix++){\r
+ uint32_t x = block[3];\r
+ for (int jj = 2; jj >= 0; jj--){\r
+ x = (x << 8) + block[jj];\r
+ }\r
+ M[ix] = x;\r
+ block += 4;\r
+ }\r
+ //Initialize hash value for this chunk:\r
+ uint32_t A = m_a0;\r
+ uint32_t B = m_b0;\r
+ uint32_t C = m_c0;\r
+ uint32_t D = m_d0;\r
+ //Main loop:\r
+\r
+ int F, g;\r
+//#define TRACE_MD5\r
+#if defined TRACE_MD5\r
+ printf("neu: (%s)\n", block);\r
+#endif\r
+ for (int i = 0; i < 64; i++){\r
+#if defined TRACE_MD5\r
+ if (i < 8)\r
+ printf("%2d: A: %08x B: %08x C: %08x D%08x\n", i, A, B, C, D);\r
+#endif\r
+ if (i < 16){\r
+# define F1(B, C, D) ((B & C) | (~ B & D))\r
+ // F := (B and C) or ((not B) and D)\r
+ F = F1(B, C, D);\r
+ g = i;\r
+ } else if (i < 32){\r
+ // F := (D and B) or (C and (not D))\r
+ // g := (5×i + 1) mod 16\r
+# define F2(B, C, D) ((D & B) | (C & ~ D))\r
+ F = F2(B, C, D);\r
+ g = (5*i + 1) % 16;\r
+ } else if (i < 48){\r
+ // F := B xor C xor D\r
+ // g := (3×i + 5) mod 16\r
+# define F3(B, C, D) ((B ^ C) ^ D)\r
+ F = F3(B, C, D);\r
+ g = (3*i + 5) % 16;\r
+ } else {\r
+ // F := C xor (B or (not D))\r
+# define F4(B, C, D) (C ^ (B | ~ D))\r
+ // g := (7×i) mod 16\r
+ F = F4(B, C, D);\r
+ g = (7*i) % 16;\r
+ }\r
+#if defined TRACE_MD5\r
+ if (i < 8)\r
+ printf(" K[%2d]: %08x M[%2d]: %08x shift: %02d\n",\r
+ i, m_K[i], g, M[g], m_s[i]);\r
+#endif\r
+ uint32_t dTemp = D;\r
+ D = C;\r
+ C = B;\r
+ // B := B + leftrotate((A + F + K[i] + M[g]), s[i])\r
+ uint32_t x = (A + F + m_K[i] + M[g]);\r
+ int shift = m_s[i];\r
+ B += (x << shift) | (x >> (32 - shift));\r
+ A = dTemp;\r
+ }\r
+ //Add this chunk's hash to result so far:\r
+ m_a0 += A;\r
+ m_b0 += B;\r
+ m_c0 += C;\r
+ m_d0 += D;\r
+}\r
+/** ----------------------\r
+ */\r
+#if defined OPTIMIZER_WORKS_GREAT\r
+inline void rotate_left_and_add(uint32_t& rc, uint32_t data, int shift, uint32_t term) {\r
+ rc = ((data << shift) | (data >> (32-shift))) + term;\r
+}\r
+inline void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, \r
+ uint32_t data, uint32_t aConst, uint32_t shift) {\r
+//#define TRACE_MD5\r
+#if defined TRACE_MD5\r
+ printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);\r
+ printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",\r
+ s_ix - 1, aConst, data, shift);\r
+#endif\r
+ rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x);\r
+}\r
+inline void X2(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, \r
+ uint32_t data, uint32_t aConst, uint32_t shift) {\r
+#if defined TRACE_MD5\r
+ printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);\r
+ printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",\r
+ s_ix - 1, aConst, data, shift);\r
+#endif\r
+ rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x);\r
+}\r
+\r
+inline void X3(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, \r
+ uint32_t data, uint32_t aConst, uint32_t shift) {\r
+#if defined TRACE_MD5\r
+ printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);\r
+ printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",\r
+ s_ix - 1, aConst, data, shift);\r
+#endif\r
+ rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x);\r
+}\r
+\r
+inline void X4(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, \r
+ uint32_t data, uint32_t aConst, uint32_t shift) {\r
+#if defined TRACE_MD5\r
+ printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z);\r
+ printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n",\r
+ s_ix - 1, aConst, data, shift);\r
+#endif\r
+ rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x);\r
+}\r
+#else\r
+#define rotate_left_and_add(var, data, shift, term) { \\r
+ uint32_t val = data; \\r
+ var = ((val << shift) | (val >> (32-shift))) + term; \\r
+}\r
+#define X1(var, x, y, z, data, aConst, shift) \\r
+ rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x)\r
+#define X2(var, x, y, z, data, aConst, shift) \\r
+ rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x)\r
+#define X3(var, x, y, z, data, aConst, shift) \\r
+ rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x)\r
+#define X4(var, x, y, z, data, aConst, shift) \\r
+ rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x)\r
+#endif /* OPTIMIZER_WORKS_GREAT */\r
+\r
+/**\r
+ * Processes a 512 bit block ("chunk").\r
+ *\r
+ * This is a optimized version, derived from the method above.\r
+ * We unroll the loop, this brings speed with factor 2.\r
+ * <pre>\r
+ * B := B + leftrotate((A + F + K[i] + M[g]), s[i])\r
+ * D := C;\r
+ * C := B;\r
+ * B := B + leftrotate((A + F + K[i] + M[g]), s[i])\r
+ * A := D(old)\r
+ * (D, C, B, A) = (C, B, B + leftrotate((A + F + K[i] + M[g]), s[i]), D)\r
+ * ==> (A, B, C, D) = (D, B + leftrotate((A + F + K[i] + M[g]), s[i]), B, A)\r
+ * The unrolled loop:\r
+ * i = g = 0;\r
+ * (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[0] + M[0]), s[0]), B, A)\r
+ * only one var must be calculated, the other 3 are exchanged only.\r
+ * i = g = 1;\r
+ * (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[1] + M[1]), s[1]), B, A)\r
+ * i = g = 2;\r
+ * (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[2] + M[2]), s[2]), B, A)\r
+ * i = g = 3;\r
+ * (A, B, C, D) = (D, B + leftrotate((A + F1(B, C, D) + K[3] + M[3]), s[3]), B, A)\r
+ * in each of the 4 statements another variable (of A, B, C and D) will be calculated\r
+ * so we do not exchange in each step, we calculate in the end position\r
+ * we define a function to do this:\r
+ * void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, uint32_t data, uint32_t shift, uint32_t aConst){\r
+ * var = rotate_left(var+ F1(x, y, z) + data + aConst, shift) + x;\r
+ * }\r
+ * Note: the input parameter of X1 must respect the exchange:\r
+ * A -> D -> C -> B ...\r
+ * X1(A, B, C, D, M[0], K[0], s[0]);\r
+ * X1(D, A, B, C, M[1], K[1], s[1]);\r
+ * X1(C, D, A, B, M[2], K[2], s[2]);\r
+ * X1(B, C, D, A, M[3], K[3], s[3]);\r
+ * ...\r
+ * </pre>\r
+ */\r
+void ReMD5::processChunk(const uint8_t block[64]){\r
+ uint32_t M[16];\r
+ // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15\r
+#ifdef __LITTLE_ENDIAN__\r
+ for (int ix = 0; ix < 16; ix++){\r
+ //memcpy(&M[ix], block + ix * 4, 4);\r
+ M[ix] = * (uint32_t*) (block + ix*4);\r
+ }\r
+#elif defined __BIG_ENDIAN__\r
+ for (int ix = 0; ix < 16; ix++){\r
+ uint32_t x = block[3];\r
+ for (int jj = 2; jj >= 0; jj--){\r
+ x = (x << 8) + block[jj];\r
+ }\r
+ M[ix] = x;\r
+ block += 4;\r
+ }\r
+#else\r
+# error "missing __LITTLE_ENDIAN__ or __BIG_ENDIAN__"\r
+#endif\r
+ //Initialize hash value for this chunk:\r
+ uint32_t A = m_a0;\r
+ uint32_t B = m_b0;\r
+ uint32_t C = m_c0;\r
+ uint32_t D = m_d0;\r
+#if defined NeverAndNeverAndNeverAgain\r
+ // Derivation of the optimization:\r
+\r
+#endif\r
+ /* Round 1 */\r
X1(A, B, C, D, M[ 0], 0xd76aa478, 7);\r
X1(D, A, B, C, M[ 1], 0xe8c7b756, 12);\r
X1(C, D, A, B, M[ 2], 0x242070db, 17);\r
X2 (C, D, A, B, M[11], 0x265e5a51, 14);\r
X2 (B, C, D, A, M[ 0], 0xe9b6c7aa, 20);\r
X2 (A, B, C, D, M[ 5], 0xd62f105d, 5);\r
- X2 (D, A, B, C, M[10], 0x2441453, 9);\r
+ X2 (D, A, B, C, M[10], 0x02441453, 9);\r
X2 (C, D, A, B, M[15], 0xd8a1e681, 14);\r
X2 (B, C, D, A, M[ 4], 0xe7d3fbc8, 20);\r
X2 (A, B, C, D, M[ 9], 0x21e1cde6, 5);\r
X3 (A, B, C, D, M[13], 0x289b7ec6, 4);\r
X3 (D, A, B, C, M[ 0], 0xeaa127fa, 11);\r
X3 (C, D, A, B, M[ 3], 0xd4ef3085, 16);\r
- X3 (B, C, D, A, M[ 6], 0x4881d05, 23);\r
+ X3 (B, C, D, A, M[ 6], 0x04881d05, 23);\r
X3 (A, B, C, D, M[ 9], 0xd9d4d039, 4);\r
X3 (D, A, B, C, M[12], 0xe6db99e5, 11);\r
X3 (C, D, A, B, M[15], 0x1fa27cf8, 16);\r
X4 (D, A, B, C, M[11], 0xbd3af235, 10);\r
X4 (C, D, A, B, M[ 2], 0x2ad7d2bb, 15);\r
X4 (B, C, D, A, M[ 9], 0xeb86d391, 21);\r
-
- //Add this chunk's hash to result so far:
- m_a0 += A;
- m_b0 += B;
- m_c0 += C;
- m_d0 += D;
-}
-/**
- * Prepares the instance for a new checksum.
- */
-void ReMD5::reset(){
- m_a0 = 0x67452301;
- m_b0 = 0xefcdab89;
- m_c0 = 0x98badcfe;
- m_d0 = 0x10325476;
- memset(m_digest, 0, sizeof m_digest);
- memset(m_waiting, 0, sizeof m_waiting);
- m_lengthWaiting = 0;
- m_length = 0;
- m_hexDigest.setLength(0);
- m_finalized = false;
-}
-/**
- * Processes a 64 byte block.
- *
- * @param block a block which should be added to the digest
- * @param blockLength the length of <code>block</code>
- */
-void ReMD5::update(const uint8_t* block, int blockLength){
- if (blockLength == -1)
- blockLength = strlen((const char*) block);
- // process the "waiting" input (incomplete chunk):
- m_length += blockLength;
- if (m_lengthWaiting > 0){
- int rest = 64 - m_lengthWaiting;
- if (rest > blockLength)
- rest = blockLength;
- memcpy(m_waiting + m_lengthWaiting, block, rest);
- blockLength -= rest;
- block += rest;
- m_lengthWaiting += rest;
- // Is the chunk complete?
- if (m_lengthWaiting == 64){
- processChunk(m_waiting);
- m_lengthWaiting = 0;
- }
- }
- // process full 512 bit chunks (64 byte blocks):
- for (int ix = blockLength / 64; ix > 0; ix--){
- processChunk(block);
- block += 64;
- }
- blockLength %= 64;
- if (blockLength != 0){
- assert(m_lengthWaiting == 0);
- memcpy(m_waiting, block, blockLength);
- m_lengthWaiting = blockLength;
- }
-}
-
+\r
+ //Add this chunk's hash to result so far:\r
+ m_a0 += A;\r
+ m_b0 += B;\r
+ m_c0 += C;\r
+ m_d0 += D;\r
+}\r
+/**\r
+ * Prepares the instance for a new checksum.\r
+ */\r
+void ReMD5::reset(){\r
+ m_a0 = 0x67452301;\r
+ m_b0 = 0xefcdab89;\r
+ m_c0 = 0x98badcfe;\r
+ m_d0 = 0x10325476;\r
+ memset(m_digest, 0, sizeof m_digest);\r
+ memset(m_waiting, 0, sizeof m_waiting);\r
+ m_lengthWaiting = 0;\r
+ m_length = 0;\r
+ m_hexDigest.setLength(0);\r
+ m_finalized = false;\r
+}\r
+/**\r
+ * Processes a 64 byte block.\r
+ *\r
+ * @param block a block which should be added to the digest\r
+ * @param blockLength the length of <code>block</code>\r
+ */\r
+void ReMD5::update(const uint8_t* block, int blockLength){\r
+ if (blockLength == -1)\r
+ blockLength = strlen((const char*) block);\r
+ // process the "waiting" input (incomplete chunk):\r
+ m_length += blockLength;\r
+ if (m_lengthWaiting > 0){\r
+ int rest = 64 - m_lengthWaiting;\r
+ if (rest > blockLength)\r
+ rest = blockLength;\r
+ memcpy(m_waiting + m_lengthWaiting, block, rest);\r
+ blockLength -= rest;\r
+ block += rest;\r
+ m_lengthWaiting += rest;\r
+ // Is the chunk complete?\r
+ if (m_lengthWaiting == 64){\r
+ processChunk(m_waiting);\r
+ m_lengthWaiting = 0;\r
+ }\r
+ }\r
+ // process full 512 bit chunks (64 byte blocks):\r
+ for (int ix = blockLength / 64; ix > 0; ix--){\r
+ processChunk(block);\r
+ block += 64;\r
+ }\r
+ blockLength %= 64;\r
+ if (blockLength != 0){\r
+ assert(m_lengthWaiting == 0);\r
+ memcpy(m_waiting, block, blockLength);\r
+ m_lengthWaiting = blockLength;\r
+ }\r
+}\r
+\r