128 lines
4.0 KiB
C++
128 lines
4.0 KiB
C++
/*
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "pidigest_md4_p.h"
|
|
|
|
template<typename T>
|
|
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;
|
|
}
|