94 lines
3.5 KiB
C++
94 lines
3.5 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_md5_p.h"
|
|
|
|
template<typename T>
|
|
inline T rotate_u(T v, int bits) {
|
|
return (v << bits) | (v >> ((sizeof(T) * 8) - bits));
|
|
}
|
|
|
|
PIByteArray MD5::md5(const PIByteArray & in) {
|
|
constexpr int part_size = 64;
|
|
|
|
static constexpr uint32_t K[64] = {
|
|
0xD76AA478u, 0xE8C7B756u, 0x242070DBu, 0xC1BDCEEEu, 0xF57C0FAFu, 0x4787C62Au, 0xA8304613u, 0xFD469501u, 0x698098D8u, 0x8B44F7AFu,
|
|
0xFFFF5BB1u, 0x895CD7BEu, 0x6B901122u, 0xFD987193u, 0xA679438Eu, 0x49B40821u, 0xF61E2562u, 0xC040B340u, 0x265E5A51u, 0xE9B6C7AAu,
|
|
0xD62F105Du, 0x02441453u, 0xD8A1E681u, 0xE7D3FBC8u, 0x21E1CDE6u, 0xC33707D6u, 0xF4D50D87u, 0x455A14EDu, 0xA9E3E905u, 0xFCEFA3F8u,
|
|
0x676F02D9u, 0x8D2A4C8Au, 0xFFFA3942u, 0x8771F681u, 0x6D9D6122u, 0xFDE5380Cu, 0xA4BEEA44u, 0x4BDECFA9u, 0xF6BB4B60u, 0xBEBFBC70u,
|
|
0x289B7EC6u, 0xEAA127FAu, 0xD4EF3085u, 0x04881D05u, 0xD9D4D039u, 0xE6DB99E5u, 0x1FA27CF8u, 0xC4AC5665u, 0xF4292244u, 0x432AFF97u,
|
|
0xAB9423A7u, 0xFC93A039u, 0x655B59C3u, 0x8F0CCC92u, 0xFFEFF47Du, 0x85845DD1u, 0x6FA87E4Fu, 0xFE2CE6E0u, 0xA3014314u, 0x4E0811A1u,
|
|
0xF7537E82u, 0xBD3AF235u, 0x2AD7D2BBu, 0xEB86D391u};
|
|
static constexpr uint32_t 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};
|
|
|
|
uint32_t a0 = 0x67452301u;
|
|
uint32_t b0 = 0xefcdab89u;
|
|
uint32_t c0 = 0x98badcfeu;
|
|
uint32_t d0 = 0x10325476u;
|
|
|
|
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);
|
|
|
|
uint32_t A = a0;
|
|
uint32_t B = b0;
|
|
uint32_t C = c0;
|
|
uint32_t D = d0;
|
|
for (int i = 0; i < 64; ++i) {
|
|
uint32_t F = 0, g = 0;
|
|
if (i >= 0 && i <= 15) {
|
|
F = (B & C) | ((~B) & D);
|
|
g = i;
|
|
} else if (i >= 16 && i <= 31) {
|
|
F = (D & B) | ((~D) & C);
|
|
g = (5 * i + 1) % 16;
|
|
} else if (i >= 32 && i <= 47) {
|
|
F = B ^ C ^ D;
|
|
g = (3 * i + 5) % 16;
|
|
} else if (i >= 48 && i <= 63) {
|
|
F = C ^ (B | (~D));
|
|
g = (7 * i) % 16;
|
|
}
|
|
F = F + A + K[i] + mw[g];
|
|
A = D;
|
|
D = C;
|
|
C = B;
|
|
B = B + rotate_u(F, s[i]);
|
|
}
|
|
a0 = a0 + A;
|
|
b0 = b0 + B;
|
|
c0 = c0 + C;
|
|
d0 = d0 + D;
|
|
}
|
|
PIByteArray ret;
|
|
ret << a0 << b0 << c0 << d0;
|
|
return ret;
|
|
}
|