99 lines
2.7 KiB
C++
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;
|
|
}
|