/* 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_sha1_p.h" template inline T rotate_u(T v, int bits) { return (v << bits) | (v >> ((sizeof(T) * 8) - bits)); } template inline T shift_u(T v, int bits) { return v << bits; } PIByteArray SHA1::sha1(const PIByteArray & in) { constexpr int part_size = 64; constexpr int rounds = 80; uint32_t h0 = 0x67452301u; uint32_t h1 = 0xEFCDAB89u; uint32_t h2 = 0x98BADCFEu; uint32_t h3 = 0x10325476u; uint32_t h4 = 0xC3D2E1F0u; 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 << piChangedEndian(l); int parts = msg.size_s() / part_size; // piCout << l << "add" << add_l << "=" << (in.size() + add_l + sizeof(l)) << msg.size() << parts; uint32_t w[80]; for (int p = 0; p < parts; ++p) { uint32_t * mw = (uint32_t *)msg.data(p * part_size); for (int i = 0; i < 16; ++i) w[i] = piChangedEndian(mw[i]); for (int i = 16; i < 80; ++i) { w[i] = rotate_u((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); } uint32_t a = h0; uint32_t b = h1; uint32_t c = h2; uint32_t d = h3; uint32_t e = h4; uint32_t f = 0; uint32_t k = 0; uint32_t t = 0; for (int i = 0; i < rounds; ++i) { if (i >= 0 && i <= 19) { f = (b & c) | ((~b) & d); k = 0x5A827999; } else if (i >= 20 && i <= 39) { f = b ^ c ^ d; k = 0x6ED9EBA1; } else if (i >= 40 && i <= 59) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } else if (i >= 60 && i <= 79) { f = b ^ c ^ d; k = 0xCA62C1D6; } t = rotate_u(a, 5) + f + e + k + w[i]; e = d; d = c; c = rotate_u(b, 30); b = a; a = t; } h0 += a; h1 += b; h2 += c; h3 += d; h4 += e; } PIByteArray ret; ret << piChangedEndian(h0) << piChangedEndian(h1) << piChangedEndian(h2) << piChangedEndian(h3) << piChangedEndian(h4); return ret; }