Files
pip/libs/main/digest/pidigest_sha1_p.cpp

99 lines
2.7 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_sha1_p.h"
template<typename T>
inline T rotate_u(T v, int bits) {
return (v << bits) | (v >> ((sizeof(T) * 8) - bits));
}
template<typename T>
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;
}