Files
pip/libs/main/digest/pidigest.cpp
peri4 978e350722 version 5.5.1
add SipHash and HalfSipHash for PIDigest
2025-10-08 21:15:28 +03:00

193 lines
6.8 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.h"
#include "pidigest_blake2_p.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"
#include "pidigest_siphash_p.h"
int PIDigest::hashLength(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;
case Type::BLAKE2s_128: return 16;
case Type::BLAKE2s_160: return 20;
case Type::BLAKE2s_224: return 28;
case Type::BLAKE2s_256: return 32;
case Type::BLAKE2b_128: return 16;
case Type::BLAKE2b_160: return 20;
case Type::BLAKE2b_224: return 28;
case Type::BLAKE2b_256: return 32;
case Type::BLAKE2b_384: return 48;
case Type::BLAKE2b_512: return 64;
case Type::SipHash_2_4_64: return 8;
case Type::SipHash_2_4_128: return 16;
case Type::HalfSipHash_2_4_32: return 4;
case Type::HalfSipHash_2_4_64: return 8;
default: break;
}
return 0;
}
int PIDigest::blockLength(Type type) {
switch (type) {
case Type::MD2: return 16;
case Type::MD4:
case Type::MD5: return 64;
case Type::SHA1: return 64;
case Type::SHA2_224:
case Type::SHA2_256: return 64;
case Type::SHA2_384:
case Type::SHA2_512:
case Type::SHA2_512_224:
case Type::SHA2_512_256: return 128;
case Type::BLAKE2s_128:
case Type::BLAKE2s_160:
case Type::BLAKE2s_224:
case Type::BLAKE2s_256: return 64;
case Type::BLAKE2b_128:
case Type::BLAKE2b_160:
case Type::BLAKE2b_224:
case Type::BLAKE2b_256:
case Type::BLAKE2b_384:
case Type::BLAKE2b_512: return 128;
case Type::SipHash_2_4_64: return 8;
case Type::SipHash_2_4_128: return 16;
case Type::HalfSipHash_2_4_32: return 4;
case Type::HalfSipHash_2_4_64: return 8;
default: break;
}
return 0;
}
PIConstChars PIDigest::typeName(Type type) {
switch (type) {
case Type::MD2: return "MD2";
case Type::MD4: return "MD4";
case Type::MD5: return "MD5";
case Type::SHA1: return "SHA1";
case Type::SHA2_224: return "SHA2_224";
case Type::SHA2_256: return "SHA2_256";
case Type::SHA2_384: return "SHA2_384";
case Type::SHA2_512: return "SHA2_512";
case Type::SHA2_512_224: return "SHA2_512_224";
case Type::SHA2_512_256: return "SHA2_512_256";
case Type::BLAKE2s_128: return "BLAKE2s_128";
case Type::BLAKE2s_160: return "BLAKE2s_160";
case Type::BLAKE2s_224: return "BLAKE2s_224";
case Type::BLAKE2s_256: return "BLAKE2s_256";
case Type::BLAKE2b_128: return "BLAKE2b_128";
case Type::BLAKE2b_160: return "BLAKE2b_160";
case Type::BLAKE2b_224: return "BLAKE2b_224";
case Type::BLAKE2b_256: return "BLAKE2b_256";
case Type::BLAKE2b_384: return "BLAKE2b_384";
case Type::BLAKE2b_512: return "BLAKE2b_512";
case Type::SipHash_2_4_64: return "SipHash_2_4_64";
case Type::SipHash_2_4_128: return "SipHash_2_4_128";
case Type::HalfSipHash_2_4_32: return "HalfSipHash_2_4_32";
case Type::HalfSipHash_2_4_64: return "HalfSipHash_2_4_64";
default: break;
}
return "Unknown";
}
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);
case Type::BLAKE2s_128: return BLAKE2::blake2s(msg, {}, 16);
case Type::BLAKE2s_160: return BLAKE2::blake2s(msg, {}, 20);
case Type::BLAKE2s_224: return BLAKE2::blake2s(msg, {}, 28);
case Type::BLAKE2s_256: return BLAKE2::blake2s(msg, {}, 32);
case Type::BLAKE2b_128: return BLAKE2::blake2b(msg, {}, 16);
case Type::BLAKE2b_160: return BLAKE2::blake2b(msg, {}, 20);
case Type::BLAKE2b_224: return BLAKE2::blake2b(msg, {}, 28);
case Type::BLAKE2b_256: return BLAKE2::blake2b(msg, {}, 32);
case Type::BLAKE2b_384: return BLAKE2::blake2b(msg, {}, 48);
case Type::BLAKE2b_512: return BLAKE2::blake2b(msg, {}, 64);
case Type::SipHash_2_4_64: return SipHash::siphash(msg, {}, 8);
case Type::SipHash_2_4_128: return SipHash::siphash(msg, {}, 16);
case Type::HalfSipHash_2_4_32: return SipHash::halfsiphash(msg, {}, 4);
case Type::HalfSipHash_2_4_64: return SipHash::halfsiphash(msg, {}, 8);
default: break;
}
return {};
}
PIByteArray PIDigest::calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type) {
switch (type) {
case Type::BLAKE2s_128: return BLAKE2::blake2s(msg, key, 16);
case Type::BLAKE2s_160: return BLAKE2::blake2s(msg, key, 20);
case Type::BLAKE2s_224: return BLAKE2::blake2s(msg, key, 28);
case Type::BLAKE2s_256: return BLAKE2::blake2s(msg, key, 32);
case Type::BLAKE2b_128: return BLAKE2::blake2b(msg, key, 16);
case Type::BLAKE2b_160: return BLAKE2::blake2b(msg, key, 20);
case Type::BLAKE2b_224: return BLAKE2::blake2b(msg, key, 28);
case Type::BLAKE2b_256: return BLAKE2::blake2b(msg, key, 32);
case Type::BLAKE2b_384: return BLAKE2::blake2b(msg, key, 48);
case Type::BLAKE2b_512: return BLAKE2::blake2b(msg, key, 64);
case Type::SipHash_2_4_64: return SipHash::siphash(msg, key, 8);
case Type::SipHash_2_4_128: return SipHash::siphash(msg, key, 16);
case Type::HalfSipHash_2_4_32: return SipHash::halfsiphash(msg, key, 4);
case Type::HalfSipHash_2_4_64: return SipHash::halfsiphash(msg, key, 8);
default: break;
}
return {};
}
PIByteArray PIDigest::HMAC(const PIByteArray & msg, const PIByteArray & key, Type type) {
int b = PIDigest::blockLength(type);
auto ipad = PIByteArray(b, uchar(0x36));
auto opad = PIByteArray(b, uchar(0x5C));
PIByteArray k0;
if (key.size_s() > b)
k0 = PIDigest::calculate(key, type);
else
k0 = key;
k0.resize(b);
return PIDigest::calculate((k0 ^ opad).append(PIDigest::calculate((k0 ^ ipad).append(msg), type)), type);
}