/* PIP - Platform Independent Primitives Digest algorithms Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "pidigest_md4_p.h" template inline T rotate_u(T v, int bits) { return (v << bits) | (v >> ((sizeof(T) * 8) - bits)); } #define F(X, Y, Z) (((X) & (Y)) | ((~(X)) & (Z))) #define G(X, Y, Z) (((X) & (Y)) | ((X) & (Z)) | ((Y) & (Z))) #define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) #define MD4ROUND1(a, b, c, d, x, s) \ a += F(b, c, d) + x; \ a = rotate_u(a, s); #define MD4ROUND2(a, b, c, d, x, s) \ a += G(b, c, d) + x + 0x5A827999u; \ a = rotate_u(a, s); #define MD4ROUND3(a, b, c, d, x, s) \ a += H(b, c, d) + x + 0x6ED9EBA1u; \ a = rotate_u(a, s); PIByteArray MD4::md4(const PIByteArray & in) { constexpr int part_size = 64; uint32_t a = piChangedEndian(0x01234567u); uint32_t b = piChangedEndian(0x89ABCDEFu); uint32_t c = piChangedEndian(0xFEDCBA98u); uint32_t d = piChangedEndian(0x76543210u); uint64_t l = in.size() * 8; PIByteArray msg = in; int add_l = (part_size - 8) - (msg.size() % (part_size)); if (add_l <= 0) add_l += part_size; msg.append(0x80); for (int i = 1; i < add_l; ++i) msg.append(0x0); msg << l; int parts = msg.size_s() / part_size; // piCout << l << "add" << add_l << "=" << (in.size() + add_l + sizeof(l)) << msg.size() << parts; for (int p = 0; p < parts; ++p) { uint32_t * mw = (uint32_t *)msg.data(p * part_size); // piCout << PIByteArray(w, 64); uint32_t a0 = a; uint32_t b0 = b; uint32_t c0 = c; uint32_t d0 = d; MD4ROUND1(a, b, c, d, mw[0], 3); MD4ROUND1(d, a, b, c, mw[1], 7); MD4ROUND1(c, d, a, b, mw[2], 11); MD4ROUND1(b, c, d, a, mw[3], 19); MD4ROUND1(a, b, c, d, mw[4], 3); MD4ROUND1(d, a, b, c, mw[5], 7); MD4ROUND1(c, d, a, b, mw[6], 11); MD4ROUND1(b, c, d, a, mw[7], 19); MD4ROUND1(a, b, c, d, mw[8], 3); MD4ROUND1(d, a, b, c, mw[9], 7); MD4ROUND1(c, d, a, b, mw[10], 11); MD4ROUND1(b, c, d, a, mw[11], 19); MD4ROUND1(a, b, c, d, mw[12], 3); MD4ROUND1(d, a, b, c, mw[13], 7); MD4ROUND1(c, d, a, b, mw[14], 11); MD4ROUND1(b, c, d, a, mw[15], 19); MD4ROUND2(a, b, c, d, mw[0], 3); MD4ROUND2(d, a, b, c, mw[4], 5); MD4ROUND2(c, d, a, b, mw[8], 9); MD4ROUND2(b, c, d, a, mw[12], 13); MD4ROUND2(a, b, c, d, mw[1], 3); MD4ROUND2(d, a, b, c, mw[5], 5); MD4ROUND2(c, d, a, b, mw[9], 9); MD4ROUND2(b, c, d, a, mw[13], 13); MD4ROUND2(a, b, c, d, mw[2], 3); MD4ROUND2(d, a, b, c, mw[6], 5); MD4ROUND2(c, d, a, b, mw[10], 9); MD4ROUND2(b, c, d, a, mw[14], 13); MD4ROUND2(a, b, c, d, mw[3], 3); MD4ROUND2(d, a, b, c, mw[7], 5); MD4ROUND2(c, d, a, b, mw[11], 9); MD4ROUND2(b, c, d, a, mw[15], 13); MD4ROUND3(a, b, c, d, mw[0], 3); MD4ROUND3(d, a, b, c, mw[8], 9); MD4ROUND3(c, d, a, b, mw[4], 11); MD4ROUND3(b, c, d, a, mw[12], 15); MD4ROUND3(a, b, c, d, mw[2], 3); MD4ROUND3(d, a, b, c, mw[10], 9); MD4ROUND3(c, d, a, b, mw[6], 11); MD4ROUND3(b, c, d, a, mw[14], 15); MD4ROUND3(a, b, c, d, mw[1], 3); MD4ROUND3(d, a, b, c, mw[9], 9); MD4ROUND3(c, d, a, b, mw[5], 11); MD4ROUND3(b, c, d, a, mw[13], 15); MD4ROUND3(a, b, c, d, mw[3], 3); MD4ROUND3(d, a, b, c, mw[11], 9); MD4ROUND3(c, d, a, b, mw[7], 11); MD4ROUND3(b, c, d, a, mw[15], 15); a += a0; b += b0; c += c0; d += d0; } PIByteArray ret; ret << a << b << c << d; return ret; }