From: hama Date: Sun, 1 Feb 2015 18:22:53 +0000 (+0100) Subject: MD5 appendHexDump X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=50bcfb3fdfd2584e9670c15bfd5478a27a984fdf;p=crepublib MD5 appendHexDump --- diff --git a/base/ReByteBuffer.cpp b/base/ReByteBuffer.cpp index acf4992..d8d3d77 100644 --- a/base/ReByteBuffer.cpp +++ b/base/ReByteBuffer.cpp @@ -168,6 +168,83 @@ ReByteBuffer& ReByteBuffer::appendInt(int number, const char* format){ ReByteBuffer& ReByteBuffer::append(const ReByteBuffer& source){ return append(source.str(), source.length()); } + +/** + * Appends a hexadecimal dump of a memory array. + * + *
Example:
+ * buffer.appendHex("01234567890abcde", -1, 0x10, 16, "%0x8x", 1, -1, " | ");
+ * 
+ * Buffer contains:
+ * 00000010  30 31 32 33 34 35 36 37  38 39 30 61 62 63 64 65 | 01234567890abcde
+ * 
+ * + * @param data data to dump + * @param length length of data. -1: strlen(data) + * @param offset a format which is used to append a preceeding position + * of source. NULL: no offset is appended + * @param bytesPerLine number of bytes in one line. If length is greater more + * lines are appended + * @param offsetFormat NULL or the sprintf format of the offset, e.g. "0x04x " + * @param withAscii true: the data is interpreted as ASCII too + * @param groupWidth behind groupWidth hex bytes a ' ' is appended + * @param gapBehind behind gapBehind hex bytes a ' ' is appended
+ * -1: bytePerLine / 2 + * @param separator NULL or a string between hex area and ASCII area + */ +ReByteBuffer& ReByteBuffer::appendHexDump(const char* data, size_t length, + int offset, int bytesPerLine, const char* offsetFormat, + bool withAscii, int groupWidth, int gapBehind, const char* separator){ + if (length == -1) + length = strlen(data); + if (gapBehind < 0) + gapBehind = bytesPerLine / 2; + ensureSize(32); + int offsetLength = 0; + if (offsetFormat != NULL){ + snprintf(m_buffer, 31, offsetFormat, offset + length); + offsetLength = strlen(m_buffer); + } + ensureSize((length + bytesPerLine - 1) / bytesPerLine + * (4 + offsetLength + (gapBehind <= 0 ? 0 : bytesPerLine / gapBehind + 1) + + (separator == NULL ? 0 : strlen(separator))+ 1)); + while(length > 0){ + if (offsetFormat != NULL) + appendInt(offset, offsetFormat); + int ix; + for (ix = 0; ix < bytesPerLine; ix++){ + if (ix < length) + appendInt(data[ix], "%02x"); + else + append(" "); + if (ix < bytesPerLine - 1 + && (groupWidth == 1 || ix % groupWidth == groupWidth - 1)) + append(" ", 1); + if (ix < bytesPerLine - 1 && gapBehind > 0 + && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) + append(" ", 1); + } + if (withAscii){ + if (separator != NULL) + append(separator, -1); + } + char cc; + for (ix = 0; ix < bytesPerLine; ix++){ + if (ix < length) + appendInt( (cc = data[ix]) < ' ' || cc > 127 ? '.' : cc, "%c"); + else + append(" "); + if (ix < bytesPerLine - 1 && gapBehind > 0 + && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) + append(" ", 1); + } + append("\n", 1); + length = length <= bytesPerLine ? 0 : length - bytesPerLine; + data += bytesPerLine; + offset += bytesPerLine; + } +} + /** @brief Appends a time (given in milli seconds) as 'dd:HH:MM.mmm'. * * @param time the time (duration) in msec diff --git a/base/ReByteBuffer.hpp b/base/ReByteBuffer.hpp index a3bcc5b..9dcc9f9 100644 --- a/base/ReByteBuffer.hpp +++ b/base/ReByteBuffer.hpp @@ -46,6 +46,10 @@ public: public: ReByteBuffer& append(const Byte* source, size_t length = -1); ReByteBuffer& append(const ReByteBuffer& source); + ReByteBuffer& appendHexDump(const char* data, size_t length = -1, + int offset = 0, int bytePerLine = 16, + const char* offsetFormat = "%04x: ", bool withAscii = true, + int groupWidth = 1, int gapBehind = -1, const char* separator = " | "); ReByteBuffer& appendInt(int number, const char* format = "%d"); ReByteBuffer& appendMilliSec(int time, int minLength = 5); /** @brief Returns the n-th byte of the internal buffer. diff --git a/cunit/cuReByteBuffer.cpp b/cunit/cuReByteBuffer.cpp index 982d3fd..d49fcec 100644 --- a/cunit/cuReByteBuffer.cpp +++ b/cunit/cuReByteBuffer.cpp @@ -15,6 +15,7 @@ public: } private: void run(){ + testHexDump(); testFill(); testAppendMilliSec(); testSetDelta(); @@ -36,6 +37,26 @@ private: testSplice(); testReplace(); } + void testHexDump(){ + ReByteBuffer buf; + /* appendHexDump(const char* data, size_t length, int offset = 0, int bytePerLine = 16, + const char* offsetFormat = "%04x ", bool withAscii = true, + int groupWidth = 1, int gapBehind = -1, const char* separator = " | "); + */ + buf.appendHexDump("abcdefghijklmnopq"); + checkEqu("0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n" + "0010: 71 | q \n", + buf.str()); + buf.setLength(0).appendHexDump("abcdefghijklmnopq", 16); + checkEqu("0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n", + buf.str()); + buf.setLength(0).appendHexDump("\t\nü23456789 1234567890", -1, 20, 8, "%3d: ", true, + 2, 3, NULL); + printf("%s", buf.str()); + checkEqu(" 20: 090a ffffffc3 ffffffbc 3233 3435... .23 45\n" + " 28: 3637 38 39 2031 3233678 9 1 23\n" + " 36: 3435 36 37 3839 30 456 789 0 \n", buf.str()); + } void testFill(){ ReByteBuffer buf; buf.fill('=', 0, 3); diff --git a/cunit/cuReMD5.cpp b/cunit/cuReMD5.cpp index c3fd456..3bac001 100644 --- a/cunit/cuReMD5.cpp +++ b/cunit/cuReMD5.cpp @@ -18,6 +18,7 @@ #include "base/rebase.hpp" #include "math/remath.hpp" +//#include "math/md5.hpp" class TestReMd5 : public ReTestUnit { public: @@ -26,13 +27,28 @@ public: } private: void run(){ + testOld(); testBase(); } + void testOld(){ +#if 0 + MD5 md5; + md5.update("", 0); + md5.finalize(); + std::string dig = md5.hexdigest(); + const char* dig2 = (const char*) dig.c_str(); + dig2++; +#endif + } void testBase(){ ReMD5 md5; md5.update((const uint8_t*)"", 0); checkEqu("d41d8cd98f00b204e9800998ecf8427e", md5.hexDigest().str()); + md5.reset(); + md5.update((const uint8_t*)"01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ01234567890\n", -1); + checkEqu("c0a278c051a6898f6ad05da7fa80a1c4", + md5.hexDigest().str()); } }; extern void testReMD5(void); diff --git a/cunit/testall.cpp b/cunit/testall.cpp index 844d604..2634bb6 100644 --- a/cunit/testall.cpp +++ b/cunit/testall.cpp @@ -13,8 +13,8 @@ #endif void testBase(){ - extern void testReProgramArgs(void); - testReProgramArgs(); + extern void testReByteBuffer(); + testReByteBuffer(); extern void testReTestUnit(); //testReTestUnit(); @@ -70,8 +70,8 @@ void testMath(){ void testAll(){ try { - testMath(); - + testBase(); + testOs(); testBase(); testMath(); diff --git a/math/ReMD5.cpp b/math/ReMD5.cpp index 4621c31..403522e 100644 --- a/math/ReMD5.cpp +++ b/math/ReMD5.cpp @@ -7,6 +7,7 @@ #include "base/rebase.hpp" #include "math/remath.hpp" + #define __LITTLE_ENDIAN__ const int ReMD5::m_s[64] = { @@ -15,7 +16,7 @@ const int ReMD5::m_s[64] = { 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; // for x in [1..64] : int(2**32 * sin(x)) -const int ReMD5::m_K[64] = { +const uint32_t ReMD5::m_K[64] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, @@ -81,7 +82,6 @@ const uint8_t* ReMD5::digest(){ 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. @@ -94,7 +94,7 @@ void ReMD5::finalize(){ // 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 + 1, 0, zeros); + memset(block + blockLength, 0, zeros); blockLength += zeros; //append original length in bits mod (2 pow 64) to message uint64_t lengthBits = 8LL * m_length; @@ -102,21 +102,21 @@ void ReMD5::finalize(){ memcpy(block + blockLength, &lengthBits, 8); blockLength += 8; #else - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; - lengthBits >>= 4; - block[blockLength++] = lengthBits & 0xff; + 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) @@ -126,10 +126,9 @@ void ReMD5::finalize(){ memcpy(m_digest + 4, &m_b0, 4); memcpy(m_digest + 8, &m_c0, 4); memcpy(m_digest + 12, &m_d0, 4); - blockLength += 8; #else -#define oneWord(word, ix) m_digest[ix] = word; word >>= 4; \ - m_digest[ix + 1] = word; word >>= 4; m_digest[ix + 2] = word; word >>= 4; \ +#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); @@ -157,17 +156,18 @@ const ReByteBuffer& ReMD5::hexDigest(){ * Processes a 512 bit block ("chunk"). */ void ReMD5::processChunk(const uint8_t block[64]){ - int M[16]; + 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); #elif defined __BIG_ENDIAN__ for (int ix = 0; ix < 16; ix++){ - M[ix] = block[3]; - for (jj = 2; jj >= 0; jj--){ - M[ix] = (M[ix] << 4) + block[jj]; + uint32_t x = block[3]; + for (int jj = 2; jj >= 0; jj--){ + x = (x << 8) + block[jj]; } + M[ix] = x; block += 4; } #else @@ -175,23 +175,23 @@ void ReMD5::processChunk(const uint8_t block[64]){ #endif //Initialize hash value for this chunk: - int A = m_a0; - int B = m_b0; - int C = m_c0; - int D = m_d0; + 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; for (int i = 0; i < 64; i++){ - if (i <= 15){ + if (i < 16){ // F := (B and C) or ((not B) and D) F = (B & C) | (~ B & D); g = i; - } else if (i > 15 && i <= 31){ - // F := (D and B) or ((not D) and C) - F = (D & B) | (~ D & C); + } else if (i < 32){ + // F := (D and B) or (C and (not D)) + F = (D & B) | (C & ~ D); // g := (5×i + 1) mod 16 g = (5*i + 1) % 16; - } else if (i > 31 && i <= 47){ + } else if (i < 48){ // F := B xor C xor D F = (B ^ C) ^ D; // g := (3×i + 5) mod 16 @@ -202,11 +202,11 @@ void ReMD5::processChunk(const uint8_t block[64]){ // g := (7×i) mod 16 g = (7*i) % 16; } - int dTemp = D; + uint32_t dTemp = D; D = C; C = B; // B := B + leftrotate((A + F + K[i] + M[g]), s[i]) - int x = (A + F + m_K[i] + M[g]) & 0xffffffff; + uint32_t x = (A + F + m_K[i] + M[g]); int shift = m_s[i]; B += (x << shift) | (x >> (32 - shift)); A = dTemp; @@ -230,6 +230,8 @@ void ReMD5::reset(){ 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. @@ -238,6 +240,8 @@ void ReMD5::reset(){ * @param blockLength the length of block */ 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){ @@ -255,15 +259,19 @@ void ReMD5::update(const uint8_t* block, int blockLength){ } } // 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; + if (blockLength > 0){ + if (blockLength > 64){ + 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; + } } } diff --git a/math/ReMD5.hpp b/math/ReMD5.hpp index 7c885ee..1294bc3 100644 --- a/math/ReMD5.hpp +++ b/math/ReMD5.hpp @@ -35,15 +35,17 @@ private: uint8_t m_waiting[64+64]; int m_lengthWaiting; // total count of input bytes: - int m_length; - int m_a0; - int m_b0; - int m_c0; - int m_d0; + uint32_t m_length; + uint32_t m_a0; + uint32_t m_b0; + uint32_t m_c0; + uint32_t m_d0; bool m_finalized; private: + // number of shifts per round: static const int m_s[64]; - static const int m_K[64]; + // Constants: + static const uint32_t m_K[64]; }; #endif /* MATH_REMD5_HPP_ */