赞
踩
给AES设置 key, iv时, 如果长度不够, 需要填充.
刚开始实现填充时, 用的固定内容, 感觉不太好.
看到github上有个xxHash工程, 很多星, 准备用这个工程来生成固定长度的hash来填充key, iv. 这样填充内容的随机性和确定性就好很多.
不管原始key, iv的长度多少, 都先用xxHash处理成符合AES要求的key, iv长度的buf, 再调用AES加解密函数, 这样就不用考虑key, iv的填充问题了.
https://github.com/Cyan4973/xxHash.git
迁出到本地
打开普通的cmd命令行
cd /d D:\3rd_prj\crypt\xxHash\cmake_unofficial
mkdir .\build
cd .\build
cmake -G "Visual Studio 16 2019" -A x64 ..
cmake --build .
cmake --build . --target install
库安装后的路径为 C:\Program Files\xxHash
目录内容如下:
C:\Program Files\xxHash>tree /F 文件夹 PATH 列表 卷序列号为 BA70-59B2 C:. ├─bin │ xxhash.dll │ xxhsum.exe │ ├─include │ xxh3.h │ xxhash.h │ ├─lib │ │ xxhash.lib │ │ │ ├─cmake │ │ └─xxHash │ │ xxHashConfig.cmake │ │ xxHashConfigVersion.cmake │ │ xxHashTargets-debug.cmake │ │ xxHashTargets.cmake │ │ │ └─pkgconfig │ libxxhash.pc │ └─share └─man └─man1 xxhsum.1
现在就可以拿 /lib/xxhash.lib, /include/*.h, /bin/xxhash.dll包含到自己工程干活了.
看 xxhsum.exe的实现.
在编译目录中, 有xxhsum的VS工程实现.
打开 xxHash.sln
将xxhsum设置活动工程.
找到程序入口
/*
* The preferred method of obtaining the real UTF-16 arguments. Always works
* on MSVC, sometimes works on MinGW-w64 depending on the compiler flags.
*/
#ifdef __cplusplus
extern "C"
#endif
int __cdecl wmain(int argc, wchar_t* utf16_argv[])
{
return XSUM_wmain(argc, utf16_argv);
}
#else /* !XSUM_WIN32_USE_WMAIN */
下断点, 单步单步xxhsum的实现, 大致看一下.
用安装后的xxHash库和xxhsum工程实现, 自己搭建一个独立测试工程.
整了一个命令行工程(cosole x64 debug), 将库拷贝到自己工程, 设置头文件包含路径和库路径
先加入xxhsum.c, 尝试编译, 确啥补啥.
官方cli工程里面包含xxhash.h时, 都是用…/xxhash.h, 改为xxhash.h
编译通过, 功能正常.
D:\my_dev\my_local_git_prj\study\xxHash\my_xxhsum>tree /F 文件夹 PATH 列表 卷序列号为 36AD-51CE D:. │ my_xxhsum.sln │ my_xxhsum.vcxproj │ my_xxhsum.vcxproj.filters │ my_xxhsum.vcxproj.user │ xsum_arch.h │ xsum_bench.c │ xsum_bench.h │ xsum_config.h │ xsum_os_specific.c │ xsum_os_specific.h │ xsum_output.c │ xsum_output.h │ xsum_sanity_check.c │ xsum_sanity_check.h │ xxhsum.c │ └─xxHash_lib ├─bin │ xxhash.dll │ xxhsum.exe │ ├─include │ xxh3.h │ xxhash.h │ ├─lib │ │ xxhash.lib │ │ │ ├─cmake │ │ └─xxHash │ │ xxHashConfig.cmake │ │ xxHashConfigVersion.cmake │ │ xxHashTargets-debug.cmake │ │ xxHashTargets.cmake │ │ │ └─pkgconfig │ libxxhash.pc │ └─share └─man └─man1 xxhsum.1
static int XSUM_usage(const char* exename) { XSUM_log( WELCOME_MESSAGE(exename) ); XSUM_log( "Print or verify checksums using fast non-cryptographic algorithm xxHash \n\n" ); XSUM_log( "Usage: %s [options] [files] \n\n", exename); XSUM_log( "When no filename provided or when '-' is provided, uses stdin as input. \n"); XSUM_log( "\nOptions: \n"); XSUM_log( " -H# select an xxhash algorithm (default: %i) \n", (int)g_defaultAlgo); XSUM_log( " 0: XXH32 \n"); XSUM_log( " 1: XXH64 \n"); XSUM_log( " 2: XXH128 (also called XXH3_128bits) \n"); XSUM_log( " 3: XXH3 (also called XXH3_64bits) \n"); XSUM_log( " -c, --check read xxHash checksum from [files] and check them \n"); XSUM_log( " -h, --help display a long help page about advanced options \n"); return 0; } static int XSUM_usage_advanced(const char* exename) { XSUM_usage(exename); XSUM_log( "\nAdvanced :\n"); XSUM_log( " -V, --version Display version information \n"); XSUM_log( " --tag Produce BSD-style checksum lines \n"); XSUM_log( " --little-endian Checksum values use little endian convention (default: big endian) \n"); XSUM_log( " --binary Read in binary mode \n"); XSUM_log( " -b Run benchmark \n"); XSUM_log( " -b# Bench only algorithm variant # \n"); XSUM_log( " -i# Number of times to run the benchmark (default: %i) \n", NBLOOPS_DEFAULT); XSUM_log( " -q, --quiet Don't display version header in benchmark mode \n"); XSUM_log( "\n"); XSUM_log( "The following five options are useful only when verifying checksums (-c): \n"); XSUM_log( " -q, --quiet Don't print OK for each successfully verified file \n"); XSUM_log( " --status Don't output anything, status code shows success \n"); XSUM_log( " --strict Exit non-zero for improperly formatted checksum lines \n"); XSUM_log( " --warn Warn about improperly formatted checksum lines \n"); XSUM_log( " --ignore-missing Don't fail or report status for missing files \n"); return 0; }
给出不同命令行参数, 试试效果.
-H3 D:\my_tmp\my_xxhsum.pdb
结果如下:
\XXH3_82fc89454f8a2238 D:\\my_tmp\\my_xxhsum.pdb
-H3 --binary D:\my_tmp\my_xxhsum.pdb
结果如下:
\XXH3_82fc89454f8a2238 D:\\my_tmp\\my_xxhsum.pdb
看来都是2进制读取文件内容并计算hash.
单步时, 发现 --binary 是无效的, 被忽略掉了
if (!strcmp(argument, "--binary")) { continue; } /* Just ignore it. See https://github.com/Cyan4973/xxHash/issues/812 */
算hash的cli函数
return XSUM_hashFiles(argv+filenamesStart, argc-filenamesStart, algo, displayEndianess, convention);
看到使用xxHash库的最终用法了
/* * XSUM_hashStream: * Reads data from `inFile`, generating an incremental hash of type hashType, * using `buffer` of size `blockSize` for temporary storage. */ static Multihash XSUM_hashStream(FILE* inFile, AlgoSelected hashType, void* buffer, size_t blockSize) { XXH32_state_t state32; XXH64_state_t state64; XXH3_state_t state3; /* Init */ (void)XXH32_reset(&state32, XXHSUM32_DEFAULT_SEED); (void)XXH64_reset(&state64, XXHSUM64_DEFAULT_SEED); (void)XXH3_128bits_reset(&state3); /* Load file & update hash */ { size_t readSize; while ((readSize = fread(buffer, 1, blockSize, inFile)) > 0) { switch(hashType) { case algo_xxh32: (void)XXH32_update(&state32, buffer, readSize); break; case algo_xxh64: (void)XXH64_update(&state64, buffer, readSize); break; case algo_xxh128: (void)XXH3_128bits_update(&state3, buffer, readSize); break; case algo_xxh3: (void)XXH3_64bits_update(&state3, buffer, readSize); break; default: assert(0); } } if (ferror(inFile)) { XSUM_log("Error: a failure occurred reading the input file.\n"); exit(1); } } { Multihash finalHash = {0}; switch(hashType) { case algo_xxh32: finalHash.hash32 = XXH32_digest(&state32); break; case algo_xxh64: finalHash.hash64 = XXH64_digest(&state64); break; case algo_xxh128: finalHash.hash128 = XXH3_128bits_digest(&state3); break; case algo_xxh3: finalHash.hash64 = XXH3_64bits_digest(&state3); break; default: assert(0); } return finalHash; } }
保存Hash值
/* display Hash value in selected format */ switch(hashType) { case algo_xxh32: { XXH32_canonical_t hcbe32; (void)XXH32_canonicalFromHash(&hcbe32, hashValue.hash32); f_displayLine(fileName, &hcbe32, hashType); break; } case algo_xxh64: { XXH64_canonical_t hcbe64; (void)XXH64_canonicalFromHash(&hcbe64, hashValue.hash64); f_displayLine(fileName, &hcbe64, hashType); break; } case algo_xxh128: { XXH128_canonical_t hcbe128; (void)XXH128_canonicalFromHash(&hcbe128, hashValue.hash128); f_displayLine(fileName, &hcbe128, hashType); break; } case algo_xxh3: { XXH64_canonical_t hcbe64; (void)XXH64_canonicalFromHash(&hcbe64, hashValue.hash64); f_displayLine(fileName, &hcbe64, hashType); break; } default: assert(0); /* not possible */ }
显示hash值
static void XSUM_printLine_GNU(const char* filename,
const void* canonicalHash, const AlgoSelected hashType)
{
XSUM_printLine_GNU_internal(filename, canonicalHash, hashType, XSUM_display_BigEndian);
}
static void XSUM_printLine_GNU_internal(const char* filename, const void* canonicalHash, const AlgoSelected hashType, XSUM_displayHash_f f_displayHash) { assert(0 <= hashType && (size_t)hashType <= XSUM_TABLE_ELT_SIZE(XSUM_algoName)); { const size_t hashLength = XSUM_algoLength[hashType]; const int needsEscape = XSUM_filenameNeedsEscape(filename); if (needsEscape) { XSUM_output("%c", '\\'); } XSUM_displayPrefix(hashType); f_displayHash(canonicalHash, hashLength); XSUM_output(" "); XSUM_printFilename(filename, needsEscape); XSUM_output("\n"); } }
static void XSUM_display_BigEndian(const void* ptr, size_t length)
{
const XSUM_U8* const p = (const XSUM_U8*)ptr;
size_t idx;
for (idx=0; idx<length; idx++)
XSUM_output("%02x", p[idx]);
}
懂了
官方工程是针对文件做hash, 我要的是对buffer做hash.
通过单步, 这个库的用法已经清楚了. 自己来整一遍, 只不过, 我要的是对buffer做hash.
整完了, 好使
在xxHash基础上, 封装了3个应用接口:
bool buffer_hash_XXH3_32bits(uint8_t* pBuf, size_t nLenBuf, uint32_t& hash_4Byte);
bool buffer_hash_XXH3_64bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_8Byte);
bool buffer_hash_XXH3_128bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_H8Byte, uint64_t& hash_K8Byte);
用这3个应用接口来做流的hash, 就方便多了.
// @file test_xxHash_form_buffer.cpp #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #define XXH_STATIC_LINKING_ONLY // 在包含xxhash.h之前, 必须定义这个宏 #include "xxhash.h" #pragma comment(lib, "xxhash.lib") bool buffer_hash_XXH3_32bits(uint8_t* pBuf, size_t nLenBuf, uint32_t& hash_4Byte); bool buffer_hash_XXH3_64bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_8Byte); bool buffer_hash_XXH3_128bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_H8Byte, uint64_t& hash_K8Byte); void test_hash_128(); void test_hash_64(); void test_hash_32(); int main() { printf("test xxHash from buffer\n"); test_hash_128(); test_hash_64(); test_hash_32(); return 0; } void test_hash_128() { uint64_t hash_H8Byte = 0; uint64_t hash_L8Byte = 0; char szBuf[0x100]; memset(szBuf, 0, sizeof(szBuf)); strcpy(szBuf, "hello xxHash 128"); // add vs option _CRT_SECURE_NO_WARNINGS size_t nLenBuf = strlen(szBuf); if (buffer_hash_XXH3_128bits((uint8_t*)szBuf, nLenBuf, hash_H8Byte, hash_L8Byte)) { printf("hash value = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X", (uint8_t)(((hash_H8Byte >> (8 * 7)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 6)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 5)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 4)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 3)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 2)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 1)) & 0xff)), (uint8_t)(((hash_H8Byte >> (8 * 0)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 7)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 6)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 5)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 4)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 3)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 2)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 1)) & 0xff)), (uint8_t)(((hash_L8Byte >> (8 * 0)) & 0xff)) ); printf("\n"); } else { printf("error\n"); } } void test_hash_64() { uint64_t hash_8Byte = 0; char szBuf[0x100]; memset(szBuf, 0, sizeof(szBuf)); strcpy(szBuf, "hello xxHash 64"); // add vs option _CRT_SECURE_NO_WARNINGS size_t nLenBuf = strlen(szBuf); if (buffer_hash_XXH3_64bits((uint8_t*)szBuf, nLenBuf, hash_8Byte)) { printf("hash value = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X", (uint8_t)(((hash_8Byte >> (8 * 7)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 6)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 5)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 4)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 3)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 2)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 1)) & 0xff)), (uint8_t)(((hash_8Byte >> (8 * 0)) & 0xff)) ); printf("\n"); } else { printf("error\n"); } } void test_hash_32() { uint32_t hash_4Byte = 0; char szBuf[0x100]; memset(szBuf, 0, sizeof(szBuf)); strcpy(szBuf, "hello xxHash 32"); // add vs option _CRT_SECURE_NO_WARNINGS size_t nLenBuf = strlen(szBuf); if (buffer_hash_XXH3_32bits((uint8_t*)szBuf, nLenBuf, hash_4Byte)) { printf("hash value = %2.2X %2.2X %2.2X %2.2X", (uint8_t)(((hash_4Byte >> (8 * 3)) & 0xff)), (uint8_t)(((hash_4Byte >> (8 * 2)) & 0xff)), (uint8_t)(((hash_4Byte >> (8 * 1)) & 0xff)), (uint8_t)(((hash_4Byte >> (8 * 0)) & 0xff)) ); printf("\n"); } else { printf("error\n"); } } bool buffer_hash_XXH3_128bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_H8Byte, uint64_t& hash_K8Byte) { bool b_rc = false; XXH3_state_t state3; XXH128_hash_t finalHash; do { // size_t 没有负数 if ((NULL == pBuf) || (nLenBuf <= 0)) { break; } (void)XXH3_128bits_reset(&state3); (void)XXH3_128bits_update(&state3, pBuf, nLenBuf); finalHash = XXH3_128bits_digest(&state3); hash_H8Byte = finalHash.high64; hash_K8Byte = finalHash.low64; b_rc = true; } while (false); return b_rc; } bool buffer_hash_XXH3_64bits(uint8_t* pBuf, size_t nLenBuf, uint64_t& hash_8Byte) { bool b_rc = false; XXH3_state_t state3; XXH64_hash_t finalHash; do { // size_t 没有负数 if ((NULL == pBuf) || (nLenBuf <= 0)) { break; } (void)XXH3_128bits_reset(&state3); (void)XXH3_64bits_update(&state3, pBuf, nLenBuf); finalHash = XXH3_64bits_digest(&state3); hash_8Byte = finalHash; b_rc = true; } while (false); return b_rc; } bool buffer_hash_XXH3_32bits(uint8_t* pBuf, size_t nLenBuf, uint32_t& hash_4Byte) { bool b_rc = false; XXH32_state_t state32; XXH32_hash_t finalHash; do { // size_t 没有负数 if ((NULL == pBuf) || (nLenBuf <= 0)) { break; } // #define XXHSUM32_DEFAULT_SEED 0 /* Default seed for algo_xxh32 */ (void)XXH32_reset(&state32, 0 /*XXHSUM32_DEFAULT_SEED*/); (void)XXH32_update(&state32, pBuf, nLenBuf); finalHash = XXH32_digest(&state32); hash_4Byte = finalHash; b_rc = true; } while (false); return b_rc; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。