292 lines
9.7 KiB
C++
292 lines
9.7 KiB
C++
#include "dl_crypto.h"
|
|
|
|
#include <cstdint>
|
|
#include <array>
|
|
#include <cassert>
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/md5.h>
|
|
#include <openssl/sha.h>
|
|
|
|
#include "math/dl_algorithm.h"
|
|
#include "memory/dl_code_cvt.h"
|
|
#include "io/dl_log.h"
|
|
#include "math/dl_random.h"
|
|
#include "base/dl_string.h"
|
|
|
|
// from zlib
|
|
extern "C" {
|
|
unsigned long crc32(
|
|
unsigned long crc,
|
|
const unsigned char* buf,
|
|
unsigned len);
|
|
}
|
|
|
|
namespace dl::Crypto
|
|
{
|
|
std::array<uint32_t, 256> map_key = {
|
|
0x9f299c37, 0x6685d0d5, 0x79a250a6, 0x28c3077f, 0x683e8b14, 0xeb22ee26, 0x96d41f96, 0x9b8f6bc6,
|
|
0xb24396fc, 0xd80c7504, 0x37ac69d8, 0x38c730ec, 0x1741b09f, 0xe0f5c354, 0x5bce7a63, 0x619a64a0,
|
|
0xcf50e0f8, 0x65d59573, 0x8dc6e9f8, 0x727de110, 0xed11bf48, 0x56d0f506, 0x18c42a32, 0xa7bcdc53,
|
|
0xaf741176, 0x84ba8ffc, 0x6230b121, 0x60c81f34, 0xbb94aeed, 0x67c03614, 0x43620e6a, 0xa44fde40,
|
|
0xa271ee1f, 0xf085ec1b, 0x6e89fea0, 0x3f97a87c, 0xb7bfafbf, 0x7a2ab129, 0x6bbd8186, 0x47720465,
|
|
0xea82986e, 0x4298cbea, 0x6bf3e229, 0xddae306a, 0x88e42ae6, 0x12f64576, 0xff0f15b3, 0x354765ed,
|
|
0x6c51a48b, 0x56c3ed34, 0x23eeef1c, 0x31a85aeb, 0x52f56b70, 0xd195a3fa, 0xc7551d4b, 0x4bed0ed0,
|
|
0xff81692a, 0x432fc740, 0xa27fa6a8, 0xfe87c779, 0x89e26fa8, 0xbecd85c6, 0xd989b565, 0xbf01bd0e,
|
|
0xfb2f4aac, 0xae57c13f, 0xfd2e359e, 0x56e8b58e, 0xa5768040, 0x16c720e6, 0x3806044c, 0x9436c94d,
|
|
0xeabef817, 0x93dccd58, 0x5877b2af, 0x7372744a, 0x7bd5ed87, 0x4aac1851, 0xa24889df, 0x5f801d82,
|
|
0x4b24ba4a, 0x5b9344d6, 0xfd90354d, 0xe6d46cee, 0xd57fa9c8, 0x2fc4911c, 0x1f4e86d6, 0x172b0e80,
|
|
0xcf08d816, 0xd16ea587, 0x4ae17944, 0x59833ee2, 0x372b5826, 0x227b62f7, 0x3ce4e05f, 0x6c9da58a,
|
|
0xd15b8e3d, 0x5d2dbf7e, 0xd1be90b3, 0x8c85937e, 0xf7667a99, 0xc45b8213, 0x84a67c8d, 0x2f1e179a,
|
|
0x8ab4fc3e, 0x5a9990fb, 0x7f4804f1, 0x6982f623, 0x74dc03cd, 0x73f09862, 0xd66a9144, 0xca131ee0,
|
|
0x4c508b6c, 0x390aa6ee, 0xeb770f95, 0xb38ce227, 0x16905d25, 0x6dcf7144, 0x1535fc14, 0x1acec609,
|
|
0xb09f4b1a, 0x976bc982, 0xc466d775, 0x2367d1b9, 0xad1ba63b, 0x7183cd80, 0xcaed4522, 0xab507e3c,
|
|
0x98380421, 0xe27e07a9, 0xee0440a5, 0x1e7bf20b, 0xa78777a5, 0xc51ae078, 0x52ce070b, 0x795bbca5,
|
|
0x7dece403, 0xec909392, 0xf29b2458, 0xad438632, 0xdcf0221e, 0xf974fe28, 0x524cbd84, 0x9acd29c9,
|
|
0x24ac6a41, 0xfa2bd044, 0x3e62e11f, 0x22ab31ee, 0xf87d92c5, 0xcc18ea9d, 0x1a1ea78d, 0xc8dcb329,
|
|
0x33bb5b50, 0x67842bc2, 0x123003cf, 0xdc2660df, 0x83f79444, 0xb0635410, 0xeca6e99a, 0x95545781,
|
|
0x5a73aaa3, 0x5ff43d74, 0x3fb16726, 0xb16f238f, 0xbceaff33, 0x749836df, 0xf3ef6ca4, 0x1a9d8cb0,
|
|
0x28357201, 0x8a2dba74, 0xb0d30faa, 0x509539b8, 0xf6893bdd, 0xcd8ba47c, 0x689b8b71, 0xc3883b23,
|
|
0xa8efd5de, 0x9aa1869b, 0x8633837f, 0xd7838010, 0x6be9ed01, 0xbf7ea8af, 0xf0f427f1, 0xa9c8ac00,
|
|
0x4b76abfb, 0x182428f3, 0xee2bebd8, 0xe476369c, 0x63a6d323, 0xcc6459d0, 0xa5147a81, 0xefe9d0d4,
|
|
0xca3df385, 0xf40a34ce, 0x2bc7db4e, 0xa3e93419, 0x2f81e4d9, 0xe64c380a, 0x7126a0f4, 0x3cfe8d14,
|
|
0x4bd3716c, 0xa8be4b61, 0xfb9ce811, 0x2f2628ae, 0xdb9dfa51, 0xe5450719, 0xe0ce127b, 0x8aef9dab,
|
|
0xa64d09cf, 0x4fe6bafd, 0x70c77a61, 0x2235991b, 0x552b5b10, 0x73fa93d0, 0x5b7a6efe, 0x3f3eab5b,
|
|
0x57956170, 0xf17bffb9, 0x941a12b9, 0x5011ea85, 0xeb8e44b0, 0x480cdd7d, 0x46e79154, 0xa5ba0285,
|
|
0x7bf9f6e6, 0x6e0f4193, 0xb50d33e6, 0x1b60470b, 0xa08a9192, 0x784146cc, 0xc1e8f223, 0xc490044d,
|
|
0x24592f14, 0x16b3062b, 0x875b5a0b, 0xeee3dea0, 0x8c39eaeb, 0xf62166ea, 0x9cc9f658, 0x8cec8240,
|
|
0xc8bcf0f0, 0xc7591af0, 0xd2737c1a, 0xa78e5510, 0x6af2dae4, 0x8278abd7, 0xbfcaefc4, 0x8090f3aa,
|
|
0x4ce5a4d7, 0x26263fa4, 0xc48b59b3, 0x45089f72, 0x42cb7e66, 0x369827bf, 0xe3ffb83b, 0x1cb82ad1,
|
|
};
|
|
void EncryptXor(BufferView buf)
|
|
{
|
|
size_t num = buf.size() / 20;
|
|
size_t tail = buf.size() % 20;
|
|
unsigned char* p = (unsigned char*)buf.data();
|
|
|
|
for (size_t i = 0; i < num; ++i)
|
|
{
|
|
*(uint32_t*)(p + 0) ^= map_key[i % 256];
|
|
*(uint32_t*)(p + 4) ^= map_key[*(p + 0)];
|
|
*(uint32_t*)(p + 8) ^= map_key[*(p + 1)];
|
|
*(uint32_t*)(p + 12) ^= map_key[*(p + 2)];
|
|
*(uint32_t*)(p + 16) ^= map_key[*(p + 3)];
|
|
p += 20;
|
|
}
|
|
|
|
for (size_t i = 0; i < tail; ++i)
|
|
*(p + i) ^= i;
|
|
}
|
|
|
|
void DecryptXor(BufferView buf)
|
|
{
|
|
size_t num = buf.size() / 20;
|
|
size_t tail = buf.size() % 20;
|
|
unsigned char* p = (unsigned char*)buf.data();
|
|
|
|
for (size_t i = 0; i < num; ++i)
|
|
{
|
|
*(uint32_t*)(p + 4) ^= map_key[*(p + 0)];
|
|
*(uint32_t*)(p + 8) ^= map_key[*(p + 1)];
|
|
*(uint32_t*)(p + 12) ^= map_key[*(p + 2)];
|
|
*(uint32_t*)(p + 16) ^= map_key[*(p + 3)];
|
|
*(uint32_t*)(p + 0) ^= map_key[i % 256];
|
|
p += 20;
|
|
}
|
|
for (size_t i = 0; i < tail; ++i)
|
|
*(p + i) ^= i;
|
|
}
|
|
|
|
static std::wstring g_HAN256_TABLE =
|
|
L"〇一二三四五六七八九十百千万亿兆"
|
|
L"零壹贰叁肆伍陆柒捌玖拾佰仟阴阳中"
|
|
L"天子丑寅卯辰巳午未申酉戌亥年月日"
|
|
L"无甲乙丙丁戊己庚辛壬癸木火土金水"
|
|
L"地正杏桃槐榴荷瓜桂菊露葭腊春夏秋"
|
|
L"冬上下乾兑离震巽坎艮坤泰华衡恒嵩"
|
|
L"人鼠牛虎兔龙蛇马羊猴鸡狗猪礼乐射"
|
|
L"御书数琴棋書画诗酒花茶角徵宫商羽"
|
|
L"东蛟亢氐房狐尾箕南井鬼柳星张翼轸"
|
|
L"西奎娄胃昴毕觜参北斗牵女虚危室壁"
|
|
L"代禹殷周秦汉晋隋唐宋元明清古今来"
|
|
L"州隶兖青豫徐冀幽并扬荆益凉交分合"
|
|
L"族壮回满维苗彝家藏蒙侗布瑶白朝哈"
|
|
L"身肝心脾肾肺筋脉肉皮骨目舌口鼻耳"
|
|
L"感怒喜思悲恐风热湿燥寒酸苦甘辣咸"
|
|
L"行呼笑歌哭呻碧赤黄缟黑色味触香声";
|
|
|
|
|
|
std::wstring EncodeHan256(BufferView buf)
|
|
{
|
|
assert(find_equal(g_HAN256_TABLE) == g_HAN256_TABLE.end());
|
|
|
|
std::wstring ret;
|
|
|
|
for (auto& iter : buf)
|
|
{
|
|
ret.push_back(g_HAN256_TABLE[(size_t)iter]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool DecodeHan256(const std::wstring& str, Buffer& buf)
|
|
{
|
|
assert(find_equal(g_HAN256_TABLE) == g_HAN256_TABLE.end());
|
|
|
|
buf.resize(str.size());
|
|
|
|
for (size_t i = 0; i < str.size(); ++i)
|
|
{
|
|
auto iter = g_HAN256_TABLE.find(str[i]);
|
|
if (iter == std::wstring::npos)
|
|
{
|
|
std::wstring str_log = L"不是有效的Han256编码:";
|
|
str_log += str[i];
|
|
|
|
for (size_t i = 0; i < g_HAN256_TABLE.size(); ++i)
|
|
{
|
|
if (i % 16 == 0)
|
|
str_log.push_back(L'\n');
|
|
str_log.push_back(g_HAN256_TABLE[i]);
|
|
}
|
|
log_warn0(CodeCvt::WideCharToUtf8(str_log));
|
|
|
|
buf.clear();
|
|
return false;
|
|
}
|
|
((std::byte*)buf.data())[i] = (std::byte)iter;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint32_t HashCrc32(BufferView buf, uint32_t crc)
|
|
{
|
|
return crc32((unsigned long)crc, (const unsigned char*)buf.data(), (unsigned)buf.size());
|
|
}
|
|
|
|
std::string EncodeBase64(BufferView buf)
|
|
{
|
|
size_t base64_len = (buf.size() + 2) / 3 * 4;
|
|
if (base64_len == 0)
|
|
return {};
|
|
std::string ret;
|
|
ret.resize(base64_len);
|
|
EVP_EncodeBlock((unsigned char*)ret.data(), (unsigned char*)buf.data(), (int)buf.size());
|
|
return ret;
|
|
}
|
|
|
|
bool DecodeBase64(std::string_view str, Buffer& buf)
|
|
{
|
|
size_t n = str.size();
|
|
if (n % 4 != 0)
|
|
return false;
|
|
buf.resize(n / 4 * 3);
|
|
int ret = EVP_DecodeBlock((unsigned char*)buf.data(), (unsigned char*)str.data(), (int)str.size());
|
|
if (ret == -1)
|
|
{
|
|
log_warn("解码失败!");
|
|
buf.clear();
|
|
return false;
|
|
}
|
|
// EVP_DecodeBlock 返回值包含 padding 字节,按 '=' 数量减去
|
|
size_t num_pad = 0;
|
|
if (n > 0 && str[n - 1] == '=')
|
|
num_pad++;
|
|
if (n > 1 && str[n - 2] == '=')
|
|
num_pad++;
|
|
buf.resize((size_t)ret - num_pad);
|
|
return true;
|
|
}
|
|
|
|
Buffer HashMd5(BufferView buf)
|
|
{
|
|
Buffer ret{ 16 };
|
|
MD5((unsigned char*)buf.data(), buf.size(), (unsigned char*)ret.data());
|
|
return ret;
|
|
}
|
|
|
|
Buffer HashSha256(BufferView buf)
|
|
{
|
|
Buffer ret{ 32 };
|
|
SHA256((unsigned char*)buf.data(), buf.size(), (unsigned char*)ret.data());
|
|
return ret;
|
|
}
|
|
|
|
Buffer HashSha512(BufferView buf)
|
|
{
|
|
Buffer ret{ 64 };
|
|
SHA512((unsigned char*)buf.data(), buf.size(), (unsigned char*)ret.data());
|
|
return ret;
|
|
}
|
|
Buffer HashBlake2b(BufferView buf)
|
|
{
|
|
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
|
|
if (!ctx)
|
|
return {};
|
|
|
|
const EVP_MD* md = EVP_blake2b512();
|
|
if (!EVP_DigestInit_ex(ctx, md, NULL))
|
|
{
|
|
EVP_MD_CTX_free(ctx);
|
|
return {};
|
|
}
|
|
|
|
EVP_DigestUpdate(ctx, buf.data(), buf.size());
|
|
unsigned int hash_len;
|
|
Buffer ret{ 64 };
|
|
EVP_DigestFinal_ex(ctx, (unsigned char*)ret.data(), &hash_len);
|
|
assert(hash_len == ret.size());
|
|
EVP_MD_CTX_free(ctx);
|
|
|
|
return ret;
|
|
}
|
|
|
|
dl::Crypto::Aes256Key GenerateKeyAes256()
|
|
{
|
|
Aes256Key ret;
|
|
ret._key = Random::BufferX(32);
|
|
ret._iv = Random::BufferX(12);
|
|
ret._tag = Random::BufferX(16);
|
|
|
|
//std::string str = dl::to_string_hex(ret._key);
|
|
return ret;
|
|
}
|
|
|
|
dl::Buffer EncryptAes256(BufferView buf, const Aes256Key& key)
|
|
{
|
|
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
|
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
|
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)key._iv.size(), nullptr);
|
|
EVP_EncryptInit_ex(ctx, nullptr, nullptr,
|
|
(unsigned char*)key._key.data(), (unsigned char*)key._iv.data());
|
|
|
|
Buffer cipher = CreateBuffer(buf);
|
|
int len;
|
|
|
|
EVP_EncryptUpdate(ctx, (unsigned char*)cipher.data(), &len, (unsigned char*)buf.data(), (int)buf.size());
|
|
EVP_EncryptFinal_ex(ctx, (unsigned char*)cipher.data() + len, &len);
|
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)key._tag.size(), (void*)key._tag.data());
|
|
|
|
EVP_CIPHER_CTX_free(ctx);
|
|
return cipher;
|
|
}
|
|
|
|
dl::Buffer DecryptAes256(BufferView buf, const Aes256Key& key)
|
|
{
|
|
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
|
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
|
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)key._iv.size(), nullptr);
|
|
EVP_DecryptInit_ex(ctx, nullptr, nullptr,
|
|
(unsigned char*)key._key.data(), (unsigned char*)key._iv.data());
|
|
|
|
Buffer cipher = CreateBuffer(buf);
|
|
int len;
|
|
|
|
EVP_DecryptUpdate(ctx, (unsigned char*)cipher.data(), &len, (unsigned char*)buf.data(), (int)buf.size());
|
|
EVP_DecryptFinal_ex(ctx, (unsigned char*)cipher.data() + len, &len);
|
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, (int)key._tag.size(), (void*)key._tag.data());
|
|
|
|
EVP_CIPHER_CTX_free(ctx);
|
|
return cipher;
|
|
}
|
|
} |