diff --git a/libs/http_client/pihttpclient.cpp b/libs/http_client/pihttpclient.cpp index 42d5c0ca..3287b33b 100644 --- a/libs/http_client/pihttpclient.cpp +++ b/libs/http_client/pihttpclient.cpp @@ -167,7 +167,7 @@ PIHTTPClient * PIHTTPClient::create(const PIString & url_, PIHTTP::Method method static_cast(ret->request) = req; ret->request.setMethod(method); ret->reply.setMethod(method); - ret->url = url_; + ret->url = url_.toPercentageEncoding(); return ret; } diff --git a/libs/main/digest/pidigest.cpp b/libs/main/digest/pidigest.cpp new file mode 100644 index 00000000..4d1a3e1f --- /dev/null +++ b/libs/main/digest/pidigest.cpp @@ -0,0 +1,60 @@ +/* + 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.h" + +#include "pidigest_md2_p.h" +#include "pidigest_md4_p.h" +#include "pidigest_md5_p.h" +#include "pidigest_sha1_p.h" +#include "pidigest_sha2_p.h" + + +int PIDigest::length(Type type) { + switch (type) { + case Type::MD2: return 16; + case Type::MD4: return 16; + case Type::MD5: return 16; + case Type::SHA1: return 20; + case Type::SHA2_224: return 28; + case Type::SHA2_256: return 32; + case Type::SHA2_384: return 48; + case Type::SHA2_512: return 64; + case Type::SHA2_512_224: return 28; + case Type::SHA2_512_256: return 32; + } + return 0; +} + + +PIByteArray PIDigest::calculate(const PIByteArray & msg, Type type) { + switch (type) { + case Type::MD2: return MD2::md2(msg); + case Type::MD4: return MD4::md4(msg); + case Type::MD5: return MD5::md5(msg); + case Type::SHA1: return SHA1::sha1(msg); + case Type::SHA2_224: return SHA2::sha2xx(msg, SHA2::initial_224, 28); + case Type::SHA2_256: return SHA2::sha2xx(msg, SHA2::initial_256, 32); + case Type::SHA2_384: return SHA2::sha5xx(msg, SHA2::initial_384, 48); + case Type::SHA2_512: return SHA2::sha5xx(msg, SHA2::initial_512, 64); + case Type::SHA2_512_224: return SHA2::sha5xx(msg, SHA2::initial_512_224, 28); + case Type::SHA2_512_256: return SHA2::sha5xx(msg, SHA2::initial_512_256, 32); + } + return {}; +} diff --git a/libs/main/digest/pidigest.h b/libs/main/digest/pidigest.h new file mode 100644 index 00000000..95833f43 --- /dev/null +++ b/libs/main/digest/pidigest.h @@ -0,0 +1,56 @@ +/*! \file pidigest.h + * \ingroup Core + * \~\brief + * \~english Digest algorithms + * \~russian Алгоритмы хэш-сумм + * + * \~\details + * \~english + * This file implements several common-usage hash algorithms + * \~russian + * Этот файл реализует несколько распространенных алгоритмов хэширования + */ +/* + 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 . +*/ + +#ifndef pidigest_h +#define pidigest_h + +#include "pibytearray.h" + +class PIP_EXPORT PIDigest { +public: + enum class Type { + SHA1, + SHA2_224, + SHA2_256, + SHA2_384, + SHA2_512, + SHA2_512_224, + SHA2_512_256, + MD2, + MD4, + MD5, + }; + + static int length(Type type); + static PIByteArray calculate(const PIByteArray & msg, Type type); +}; + +#endif diff --git a/libs/main/digest/pidigest_md2_p.cpp b/libs/main/digest/pidigest_md2_p.cpp new file mode 100644 index 00000000..1337df7d --- /dev/null +++ b/libs/main/digest/pidigest_md2_p.cpp @@ -0,0 +1,88 @@ +/* + 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_md2_p.h" + + +PIByteArray MD2::md2(const PIByteArray & in) { + constexpr int part_size = 16; + static constexpr uchar S[] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, + 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, + 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, + 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, + 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, + 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, + 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, + 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, + 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20}; + + PIByteArray msg = in; + int add_l = part_size - (msg.size() % part_size); + if (add_l <= 0) add_l += part_size; + for (int i = 0; i < add_l; ++i) + msg.append(uchar(add_l)); + int parts = msg.size_s() / part_size; + // piCout << "add" << add_l << "=" << (in.size() + add_l) << msg.size() << parts; + uchar cs[16]; + for (int i = 0; i < 16; ++i) + cs[i] = 0; + + uchar l = 0; + + for (int p = 0; p < parts; ++p) { + uchar * mb = (uchar *)msg.data(p * part_size); + for (int j = 0; j < 16; ++j) { + uchar c = mb[j]; + cs[j] = cs[j] ^ S[c ^ l]; + l = cs[j]; + } + } + msg.append(cs, 16); + ++parts; + + uchar x[48]; + for (int i = 0; i < 48; ++i) + x[i] = 0; + for (int p = 0; p < parts; ++p) { + uchar * mb = (uchar *)msg.data(p * part_size); + + for (int j = 0; j < 16; ++j) { + uchar c = mb[j]; + cs[j] = cs[j] ^ S[c ^ l]; + l = cs[j]; + } + + for (int j = 0; j < 16; ++j) { + x[16 + j] = mb[j]; + x[32 + j] = (x[16 + j] ^ x[j]); + } + + uchar t = 0; + for (int j = 0; j < 18; ++j) { + for (int k = 0; k < 48; ++k) { + t = x[k] = (x[k] ^ S[t]); + } + t = (t + j) % 256; + } + } + + return PIByteArray(x, 16); +} diff --git a/libs/main/digest/pidigest_md2_p.h b/libs/main/digest/pidigest_md2_p.h new file mode 100644 index 00000000..01c327b8 --- /dev/null +++ b/libs/main/digest/pidigest_md2_p.h @@ -0,0 +1,30 @@ +/* + 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 . +*/ + +#ifndef pidigest_md2_h +#define pidigest_md2_h + +#include "pibytearray.h" + +class MD2 { +public: + static PIByteArray md2(const PIByteArray & in); +}; + +#endif diff --git a/libs/main/digest/pidigest_md4_p.cpp b/libs/main/digest/pidigest_md4_p.cpp new file mode 100644 index 00000000..482d49e3 --- /dev/null +++ b/libs/main/digest/pidigest_md4_p.cpp @@ -0,0 +1,127 @@ +/* + 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_md4_p.h" + +template +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; +} diff --git a/libs/main/digest/pidigest_md4_p.h b/libs/main/digest/pidigest_md4_p.h new file mode 100644 index 00000000..61f774d2 --- /dev/null +++ b/libs/main/digest/pidigest_md4_p.h @@ -0,0 +1,30 @@ +/* + 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 . +*/ + +#ifndef pidigest_md4_h +#define pidigest_md4_h + +#include "pibytearray.h" + +class MD4 { +public: + static PIByteArray md4(const PIByteArray & in); +}; + +#endif diff --git a/libs/main/digest/pidigest_md5_p.cpp b/libs/main/digest/pidigest_md5_p.cpp new file mode 100644 index 00000000..182384e2 --- /dev/null +++ b/libs/main/digest/pidigest_md5_p.cpp @@ -0,0 +1,93 @@ +/* + 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_md5_p.h" + +template +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; +} diff --git a/libs/main/digest/pidigest_md5_p.h b/libs/main/digest/pidigest_md5_p.h new file mode 100644 index 00000000..04fb47ba --- /dev/null +++ b/libs/main/digest/pidigest_md5_p.h @@ -0,0 +1,30 @@ +/* + 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 . +*/ + +#ifndef pidigest_md5_h +#define pidigest_md5_h + +#include "pibytearray.h" + +class MD5 { +public: + static PIByteArray md5(const PIByteArray & in); +}; + +#endif diff --git a/libs/main/digest/pidigest_sha1_p.cpp b/libs/main/digest/pidigest_sha1_p.cpp new file mode 100644 index 00000000..26d267ab --- /dev/null +++ b/libs/main/digest/pidigest_sha1_p.cpp @@ -0,0 +1,98 @@ +/* + 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; +} diff --git a/libs/main/digest/pidigest_sha1_p.h b/libs/main/digest/pidigest_sha1_p.h new file mode 100644 index 00000000..0d010b69 --- /dev/null +++ b/libs/main/digest/pidigest_sha1_p.h @@ -0,0 +1,30 @@ +/* + 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 . +*/ + +#ifndef pidigest_sha1_h +#define pidigest_sha1_h + +#include "pibytearray.h" + +class SHA1 { +public: + static PIByteArray sha1(const PIByteArray & in); +}; + +#endif diff --git a/libs/main/digest/pidigest_sha2_p.cpp b/libs/main/digest/pidigest_sha2_p.cpp new file mode 100644 index 00000000..e9b89382 --- /dev/null +++ b/libs/main/digest/pidigest_sha2_p.cpp @@ -0,0 +1,240 @@ +/* + 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_sha2_p.h" + +const uint32_t SHA2::initial_224[8] = + {0xC1059ED8u, 0x367CD507u, 0x3070DD17u, 0xF70E5939u, 0xFFC00B31u, 0x68581511u, 0x64F98FA7u, 0xBEFA4FA4u}; +const uint32_t SHA2::initial_256[8] = + {0x6A09E667u, 0xBB67AE85u, 0x3C6EF372u, 0xA54FF53Au, 0x510E527Fu, 0x9B05688Cu, 0x1F83D9ABu, 0x5BE0CD19u}; + +const uint64_t SHA2::initial_384[8] = {0xCBBB9D5DC1059ED8U, + 0x629A292A367CD507U, + 0x9159015A3070DD17U, + 0x152FECD8F70E5939U, + 0x67332667FFC00B31U, + 0x8EB44A8768581511U, + 0xDB0C2E0D64F98FA7U, + 0x47B5481DBEFA4FA4U}; +const uint64_t SHA2::initial_512[8] = {0X6A09E667F3BCC908U, + 0XBB67AE8584CAA73BU, + 0X3C6EF372FE94F82BU, + 0XA54FF53A5F1D36F1U, + 0X510E527FADE682D1U, + 0X9B05688C2B3E6C1FU, + 0X1F83D9ABFB41BD6BU, + 0X5BE0CD19137E2179U}; +const uint64_t SHA2::initial_512_256[8] = {0x22312194FC2BF72CU, + 0x9F555FA3C84C64C2U, + 0x2393B86B6F53B151U, + 0x963877195940EABDU, + 0x96283EE2A88EFFE3U, + 0xBE5E1E2553863992U, + 0x2B0199FC2C85B8AAU, + 0x0EB72DDC81C52CA2U}; +const uint64_t SHA2::initial_512_224[8] = {0x8C3D37C819544DA2U, + 0x73E1996689DCD4D6U, + 0x1DFAB7AE32FF9C82U, + 0x679DD514582F9FCFU, + 0x0F6D2B697BD44DA8U, + 0x77E36F7304C48942U, + 0x3F9D85A86A1D36C8U, + 0x1112E6AD91D692A1U}; + +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 SHA2::sha2xx(const PIByteArray & in, const uint32_t * initial, int out_bytes) { + constexpr int part_size = 64; + constexpr int rounds = 64; + + static constexpr uint32_t k[part_size] = { + 0x428A2F98u, 0x71374491u, 0xB5C0FBCFu, 0xE9B5DBA5u, 0x3956C25Bu, 0x59F111F1u, 0x923F82A4u, 0xAB1C5ED5u, 0xD807AA98u, 0x12835B01u, + 0x243185BEu, 0x550C7DC3u, 0x72BE5D74u, 0x80DEB1FEu, 0x9BDC06A7u, 0xC19BF174u, 0xE49B69C1u, 0xEFBE4786u, 0x0FC19DC6u, 0x240CA1CCu, + 0x2DE92C6Fu, 0x4A7484AAu, 0x5CB0A9DCu, 0x76F988DAu, 0x983E5152u, 0xA831C66Du, 0xB00327C8u, 0xBF597FC7u, 0xC6E00BF3u, 0xD5A79147u, + 0x06CA6351u, 0x14292967u, 0x27B70A85u, 0x2E1B2138u, 0x4D2C6DFCu, 0x53380D13u, 0x650A7354u, 0x766A0ABBu, 0x81C2C92Eu, 0x92722C85u, + 0xA2BFE8A1u, 0xA81A664Bu, 0xC24B8B70u, 0xC76C51A3u, 0xD192E819u, 0xD6990624u, 0xF40E3585u, 0x106AA070u, 0x19A4C116u, 0x1E376C08u, + 0x2748774Cu, 0x34B0BCB5u, 0x391C0CB3u, 0x4ED8AA4Au, 0x5B9CCA4Fu, 0x682E6FF3u, 0x748F82EEu, 0x78A5636Fu, 0x84C87814u, 0x8CC70208u, + 0x90BEFFFAu, 0xA4506CEBu, 0xBEF9A3F7u, 0xC67178F2u}; + + uint32_t h0 = initial[0]; + uint32_t h1 = initial[1]; + uint32_t h2 = initial[2]; + uint32_t h3 = initial[3]; + uint32_t h4 = initial[4]; + uint32_t h5 = initial[5]; + uint32_t h6 = initial[6]; + uint32_t h7 = initial[7]; + + 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[64]; + 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 < 64; ++i) { + uint32_t s0 = rotate_u(w[i - 15], 7) ^ rotate_u(w[i - 15], 18) ^ shift_u(w[i - 15], 3); + uint32_t s1 = rotate_u(w[i - 2], 17) ^ rotate_u(w[i - 2], 19) ^ shift_u(w[i - 2], 10); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + uint32_t a = h0; + uint32_t b = h1; + uint32_t c = h2; + uint32_t d = h3; + uint32_t e = h4; + uint32_t f = h5; + uint32_t g = h6; + uint32_t h = h7; + for (int i = 0; i < rounds; ++i) { + uint32_t S1 = rotate_u(e, 6) ^ rotate_u(e, 11) ^ rotate_u(e, 25); + uint32_t ch = (e & f) ^ (~e & g); + uint32_t t1 = h + S1 + ch + k[i] + w[i]; + uint32_t S0 = rotate_u(a, 2) ^ rotate_u(a, 13) ^ rotate_u(a, 22); + uint32_t maj = (a & b) ^ (a & c) ^ (b & c); + uint32_t t2 = S0 + maj; + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + h0 += a; + h1 += b; + h2 += c; + h3 += d; + h4 += e; + h5 += f; + h6 += g; + h7 += h; + } + PIByteArray ret; + ret << piChangedEndian(h0) << piChangedEndian(h1) << piChangedEndian(h2) << piChangedEndian(h3) << piChangedEndian(h4) + << piChangedEndian(h5) << piChangedEndian(h6) << piChangedEndian(h7); + ret.resize(out_bytes); + return ret; +} + +PIByteArray SHA2::sha5xx(const PIByteArray & in, const uint64_t * initial, int out_bytes) { + constexpr int part_size = 128; + constexpr int rounds = 80; + + static constexpr uint64_t k[80] = { + 0X428A2F98D728AE22U, 0X7137449123EF65CDU, 0XB5C0FBCFEC4D3B2FU, 0XE9B5DBA58189DBBCU, 0X3956C25BF348B538U, 0X59F111F1B605D019U, + 0X923F82A4AF194F9BU, 0XAB1C5ED5DA6D8118U, 0XD807AA98A3030242U, 0X12835B0145706FBEU, 0X243185BE4EE4B28CU, 0X550C7DC3D5FFB4E2U, + 0X72BE5D74F27B896FU, 0X80DEB1FE3B1696B1U, 0X9BDC06A725C71235U, 0XC19BF174CF692694U, 0XE49B69C19EF14AD2U, 0XEFBE4786384F25E3U, + 0X0FC19DC68B8CD5B5U, 0X240CA1CC77AC9C65U, 0X2DE92C6F592B0275U, 0X4A7484AA6EA6E483U, 0X5CB0A9DCBD41FBD4U, 0X76F988DA831153B5U, + 0X983E5152EE66DFABU, 0XA831C66D2DB43210U, 0XB00327C898FB213FU, 0XBF597FC7BEEF0EE4U, 0XC6E00BF33DA88FC2U, 0XD5A79147930AA725U, + 0X06CA6351E003826FU, 0X142929670A0E6E70U, 0X27B70A8546D22FFCU, 0X2E1B21385C26C926U, 0X4D2C6DFC5AC42AEDU, 0X53380D139D95B3DFU, + 0X650A73548BAF63DEU, 0X766A0ABB3C77B2A8U, 0X81C2C92E47EDAEE6U, 0X92722C851482353BU, 0XA2BFE8A14CF10364U, 0XA81A664BBC423001U, + 0XC24B8B70D0F89791U, 0XC76C51A30654BE30U, 0XD192E819D6EF5218U, 0XD69906245565A910U, 0XF40E35855771202AU, 0X106AA07032BBD1B8U, + 0X19A4C116B8D2D0C8U, 0X1E376C085141AB53U, 0X2748774CDF8EEB99U, 0X34B0BCB5E19B48A8U, 0X391C0CB3C5C95A63U, 0X4ED8AA4AE3418ACBU, + 0X5B9CCA4F7763E373U, 0X682E6FF3D6B2B8A3U, 0X748F82EE5DEFB2FCU, 0X78A5636F43172F60U, 0X84C87814A1F0AB72U, 0X8CC702081A6439ECU, + 0X90BEFFFA23631E28U, 0XA4506CEBDE82BDE9U, 0XBEF9A3F7B2C67915U, 0XC67178F2E372532BU, 0XCA273ECEEA26619CU, 0XD186B8C721C0C207U, + 0XEADA7DD6CDE0EB1EU, 0XF57D4F7FEE6ED178U, 0X06F067AA72176FBAU, 0X0A637DC5A2C898A6U, 0X113F9804BEF90DAEU, 0X1B710B35131C471BU, + 0X28DB77F523047D84U, 0X32CAAB7B40C72493U, 0X3C9EBE0A15C9BEBCU, 0X431D67C49C100D4CU, 0X4CC5D4BECB3E42B6U, 0X597F299CFC657E2AU, + 0X5FCB6FAB3AD6FAECU, 0X6C44198C4A475817U}; + + uint64_t h0 = initial[0]; + uint64_t h1 = initial[1]; + uint64_t h2 = initial[2]; + uint64_t h3 = initial[3]; + uint64_t h4 = initial[4]; + uint64_t h5 = initial[5]; + uint64_t h6 = initial[6]; + uint64_t h7 = initial[7]; + + 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; + uint64_t w[80]; + for (int p = 0; p < parts; ++p) { + uint64_t * mw = (uint64_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) { + uint64_t s0 = rotate_u(w[i - 15], 1) ^ rotate_u(w[i - 15], 8) ^ shift_u(w[i - 15], 7); + uint64_t s1 = rotate_u(w[i - 2], 19) ^ rotate_u(w[i - 2], 61) ^ shift_u(w[i - 2], 6); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + uint64_t a = h0; + uint64_t b = h1; + uint64_t c = h2; + uint64_t d = h3; + uint64_t e = h4; + uint64_t f = h5; + uint64_t g = h6; + uint64_t h = h7; + for (int i = 0; i < rounds; ++i) { + uint64_t S1 = rotate_u(e, 14) ^ rotate_u(e, 18) ^ rotate_u(e, 41); + uint64_t ch = (e & f) ^ (~e & g); + uint64_t t1 = h + S1 + ch + k[i] + w[i]; + uint64_t S0 = rotate_u(a, 28) ^ rotate_u(a, 34) ^ rotate_u(a, 39); + uint64_t maj = (a & b) ^ (a & c) ^ (b & c); + uint64_t t2 = S0 + maj; + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + h0 += a; + h1 += b; + h2 += c; + h3 += d; + h4 += e; + h5 += f; + h6 += g; + h7 += h; + } + PIByteArray ret; + ret << piChangedEndian(h0) << piChangedEndian(h1) << piChangedEndian(h2) << piChangedEndian(h3) << piChangedEndian(h4) + << piChangedEndian(h5) << piChangedEndian(h6) << piChangedEndian(h7); + ret.resize(out_bytes); + return ret; +} diff --git a/libs/main/digest/pidigest_sha2_p.h b/libs/main/digest/pidigest_sha2_p.h new file mode 100644 index 00000000..37fc2dcf --- /dev/null +++ b/libs/main/digest/pidigest_sha2_p.h @@ -0,0 +1,39 @@ +/* + 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 . +*/ + +#ifndef pidigest_sha2_h +#define pidigest_sha2_h + +#include "pibytearray.h" + +class SHA2 { +public: + static const uint32_t initial_224[8]; + static const uint32_t initial_256[8]; + + static const uint64_t initial_384[8]; + static const uint64_t initial_512[8]; + static const uint64_t initial_512_256[8]; + static const uint64_t initial_512_224[8]; + + static PIByteArray sha2xx(const PIByteArray & in, const uint32_t * initial, int out_bytes); + static PIByteArray sha5xx(const PIByteArray & in, const uint64_t * initial, int out_bytes); +}; + +#endif