actpred: 代码审计(16项发现全部修复)+ 文档更新
审计报告: docs/reviews/actpred_CODE_AUDIT_20260808.md - P0(2项): episode索引错位(dataset.py)、推理归一化静默失败(predict.py) - P1(6项): 空训练集校验、图像自然排序、空样本防御、形状校验、 MobileNet下载错误提示、stats路径校验 - P2(8项): README示例修正、公共属性、glob优化、版本约束、 单元测试(17项)、GPU安装说明、BooleanOptionalAction、ONNX验证 新增文件: actpred/test_actpred.py (17项单元测试, 全部通过) 更新文档: README.md配置表扩充、INDEX.md、审计报告修复总结
This commit is contained in:
1 parent
1e34348d6c
commit
3d03f7a1ce
19 files changed
+850
-177
No files matched your search
+27
-41
@@ -1,12 +1,17 @@
|
||||
#pragma once
|
||||
#include "Crypto_Basic.hpp"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
struct EVP_CIPHER_CTX_deleter {
|
||||
void operator()(EVP_CIPHER_CTX* ctx) const { EVP_CIPHER_CTX_free(ctx); }
|
||||
};
|
||||
using EVP_CIPHER_CTX_ptr = std::unique_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_deleter>;
|
||||
|
||||
namespace qing {
|
||||
class AES_CBC: public qing::Crypto_Basic {
|
||||
public:
|
||||
@@ -14,7 +19,9 @@ namespace qing {
|
||||
AES_CBC() {
|
||||
generate_key_iv(key, iv);
|
||||
}
|
||||
AES_CBC(std::vector<unsigned char> &key, std::vector<unsigned char> &iv) {
|
||||
AES_CBC(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv) {
|
||||
CRYPTO_CHECK(key.size() == 32, "AES-256 需要 32 字节密钥");
|
||||
CRYPTO_CHECK(iv.size() == 16, "AES-CBC 需要 16 字节 IV");
|
||||
this->key = key;
|
||||
this->iv = iv;
|
||||
}
|
||||
@@ -25,31 +32,17 @@ namespace qing {
|
||||
return bytes_to_hex(iv);
|
||||
}
|
||||
|
||||
std::string encrypt(std::string original_text) {
|
||||
std::string encrypt(const std::string& original_text) {
|
||||
std::vector<unsigned char> plaintext(original_text.begin(), original_text.end());
|
||||
std::vector<unsigned char> ciphertext = aes_encrypt(plaintext, key, iv);
|
||||
|
||||
// hex-bytes转换测试
|
||||
/*std::string hex = bytes_to_hex(ciphertext);
|
||||
std::vector<unsigned char> cipher2 = hex_to_bytes(hex);
|
||||
print_bytes(ciphertext);
|
||||
print_bytes(cipher2);*/
|
||||
|
||||
return bytes_to_hex(ciphertext);
|
||||
}
|
||||
|
||||
std::string decrypt(std::string cipher_hex) {
|
||||
std::string decrypt(const std::string& cipher_hex) {
|
||||
std::vector<unsigned char> ciphertext = hex_to_bytes(cipher_hex);
|
||||
std::vector<unsigned char> decrypted = aes_decrypt(ciphertext, key, iv);
|
||||
return std::string(decrypted.begin(), decrypted.end());
|
||||
}
|
||||
|
||||
static void print_bytes(std::vector<unsigned char>& bytes) {
|
||||
for (unsigned char byte : bytes) {
|
||||
std::cerr << std::setw(2) << static_cast<int>(byte);
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> key;
|
||||
@@ -71,48 +64,44 @@ namespace qing {
|
||||
static std::vector<unsigned char> aes_encrypt(const std::vector<unsigned char>& plaintext,
|
||||
const std::vector<unsigned char>& key,
|
||||
const std::vector<unsigned char>& iv) {
|
||||
// 创建上下文
|
||||
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
||||
// 创建上下文(RAII 自动释放)
|
||||
EVP_CIPHER_CTX_ptr ctx(EVP_CIPHER_CTX_new());
|
||||
CRYPTO_CHECK(ctx != nullptr, "无法创建加密上下文");
|
||||
|
||||
// 初始化加密操作
|
||||
CRYPTO_CHECK(EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
|
||||
key.data(), iv.data()) , "加密初始化失败");
|
||||
CRYPTO_CHECK(EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr,
|
||||
key.data(), iv.data()) == 1, "加密初始化失败");
|
||||
|
||||
// 输出缓冲区 (密文可能比明文长一个块)
|
||||
std::vector<unsigned char> ciphertext(plaintext.size() + EVP_CIPHER_CTX_block_size(ctx));
|
||||
std::vector<unsigned char> ciphertext(plaintext.size() + EVP_CIPHER_CTX_block_size(ctx.get()));
|
||||
int len = 0;
|
||||
int ciphertext_len = 0;
|
||||
|
||||
// 提供明文数据
|
||||
CRYPTO_CHECK(EVP_EncryptUpdate(ctx, ciphertext.data(), &len,
|
||||
plaintext.data(), plaintext.size()) == 1, "加载更新失败");
|
||||
CRYPTO_CHECK(EVP_EncryptUpdate(ctx.get(), ciphertext.data(), &len,
|
||||
plaintext.data(), static_cast<int>(plaintext.size())) == 1, "加密更新失败");
|
||||
ciphertext_len = len;
|
||||
|
||||
// 完成加密(处理填充)
|
||||
CRYPTO_CHECK(EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &len) == 1, "加密结束失败");
|
||||
CRYPTO_CHECK(EVP_EncryptFinal_ex(ctx.get(), ciphertext.data() + len, &len) == 1, "加密结束失败");
|
||||
ciphertext_len += len;
|
||||
|
||||
// 调整到实际密文长度
|
||||
ciphertext.resize(ciphertext_len);
|
||||
|
||||
// 处理上下文
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return ciphertext;
|
||||
|
||||
}
|
||||
|
||||
// AES-256-CBC
|
||||
// AES-256-CBC 解密
|
||||
static std::vector<unsigned char> aes_decrypt(const std::vector<unsigned char>& ciphertext,
|
||||
const std::vector<unsigned char>& key,
|
||||
const std::vector<unsigned char>& iv) {
|
||||
// 创建上下文
|
||||
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
||||
// 创建上下文(RAII 自动释放)
|
||||
EVP_CIPHER_CTX_ptr ctx(EVP_CIPHER_CTX_new());
|
||||
CRYPTO_CHECK(ctx != nullptr, "无法创建解密上下文");
|
||||
|
||||
// 初始化解密操作
|
||||
CRYPTO_CHECK(EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
|
||||
CRYPTO_CHECK(EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_cbc(), nullptr,
|
||||
key.data(), iv.data()) == 1, "解密初始化失败");
|
||||
|
||||
// 输出缓冲区(明文可能比密文短,但最大为密文长度)
|
||||
@@ -121,20 +110,17 @@ namespace qing {
|
||||
int plaintext_len = 0;
|
||||
|
||||
// 提供密文数据
|
||||
CRYPTO_CHECK(EVP_DecryptUpdate(ctx, plaintext.data(), &len,
|
||||
ciphertext.data(), ciphertext.size()) == 1, "解密更新失败");
|
||||
CRYPTO_CHECK(EVP_DecryptUpdate(ctx.get(), plaintext.data(), &len,
|
||||
ciphertext.data(), static_cast<int>(ciphertext.size())) == 1, "解密更新失败");
|
||||
plaintext_len = len;
|
||||
|
||||
// 完成解密(处理填充)
|
||||
CRYPTO_CHECK(EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len) == 1, "解密结束失败");
|
||||
CRYPTO_CHECK(EVP_DecryptFinal_ex(ctx.get(), plaintext.data() + len, &len) == 1, "解密结束失败");
|
||||
plaintext_len += len;
|
||||
|
||||
// 调整到实际明文长度
|
||||
plaintext.resize(plaintext_len);
|
||||
|
||||
// 清理上下文
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
};
|
||||
|
||||
+34
-42
@@ -1,14 +1,18 @@
|
||||
#pragma once
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include "Crypto_Basic.hpp"
|
||||
|
||||
struct BIO_deleter_b64 {
|
||||
void operator()(BIO* bio) const { BIO_free_all(bio); }
|
||||
};
|
||||
using BIO_ptr_b64 = std::unique_ptr<BIO, BIO_deleter_b64>;
|
||||
|
||||
namespace qing {
|
||||
class Base64 : public qing::Crypto_Basic {
|
||||
public:
|
||||
@@ -44,36 +48,33 @@ namespace qing {
|
||||
|
||||
/* 静态方法:直接编码字节向量(工具函数) */
|
||||
static std::string base64_encode(const std::vector<unsigned char>& input_bytes) {
|
||||
// 创建BIO链:内存BIO -> Base64 BIO
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
// 创建BIO链:内存BIO -> Base64 BIO(RAII 自动释放)
|
||||
BIO_ptr_b64 bio(BIO_new(BIO_s_mem()));
|
||||
CRYPTO_CHECK(bio != nullptr, "无法创建内存BIO");
|
||||
|
||||
BIO* b64 = BIO_new(BIO_f_base64());
|
||||
CRYPTO_CHECK(b64 != nullptr, "无法创建Base64 BIO");
|
||||
|
||||
// 将Base64 BIO连接到内存BIO
|
||||
bio = BIO_push(b64, bio);
|
||||
bio.reset(BIO_push(b64, bio.release()));
|
||||
|
||||
// 设置不添加换行符(默认会添加换行)
|
||||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
|
||||
BIO_set_flags(bio.get(), BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
// 写入数据
|
||||
int written = BIO_write(bio, input_bytes.data(), input_bytes.size());
|
||||
CRYPTO_CHECK(written == (int)input_bytes.size(), "Base64编码写入失败");
|
||||
int written = BIO_write(bio.get(), input_bytes.data(), static_cast<int>(input_bytes.size()));
|
||||
CRYPTO_CHECK(written == static_cast<int>(input_bytes.size()), "Base64编码写入失败");
|
||||
|
||||
// 刷新缓冲区
|
||||
CRYPTO_CHECK(BIO_flush(bio) == 1, "Base64编码刷新失败");
|
||||
CRYPTO_CHECK(BIO_flush(bio.get()) == 1, "Base64编码刷新失败");
|
||||
|
||||
// 读取编码结果
|
||||
BUF_MEM* bptr;
|
||||
BIO_get_mem_ptr(bio, &bptr);
|
||||
BIO_get_mem_ptr(bio.get(), &bptr);
|
||||
|
||||
// 复制结果到字符串(不包括空终止符)
|
||||
std::string result(bptr->data, bptr->length);
|
||||
|
||||
// 清理BIO
|
||||
BIO_free_all(bio);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -85,18 +86,18 @@ namespace qing {
|
||||
|
||||
/* 静态方法:直接解码为字节向量(工具函数) */
|
||||
static std::vector<unsigned char> base64_decode_to_bytes(const std::string& base64_text) {
|
||||
// 创建BIO链:Base64 BIO -> 内存BIO
|
||||
BIO* bio = BIO_new_mem_buf(base64_text.c_str(), -1);
|
||||
// 创建BIO链:Base64 BIO -> 内存BIO(RAII 自动释放)
|
||||
BIO_ptr_b64 bio(BIO_new_mem_buf(base64_text.c_str(), -1));
|
||||
CRYPTO_CHECK(bio != nullptr, "无法创建内存BIO");
|
||||
|
||||
BIO* b64 = BIO_new(BIO_f_base64());
|
||||
CRYPTO_CHECK(b64 != nullptr, "无法创建Base64 BIO");
|
||||
|
||||
// 将Base64 BIO连接到内存BIO
|
||||
bio = BIO_push(b64, bio);
|
||||
bio.reset(BIO_push(b64, bio.release()));
|
||||
|
||||
// 设置不添加换行符(解码时也要匹配)
|
||||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
|
||||
BIO_set_flags(bio.get(), BIO_FLAGS_BASE64_NO_NL);
|
||||
|
||||
// 准备接收缓冲区
|
||||
std::vector<unsigned char> result;
|
||||
@@ -104,47 +105,38 @@ namespace qing {
|
||||
int bytes_read;
|
||||
|
||||
// 循环读取解码数据
|
||||
while ((bytes_read = BIO_read(bio, buffer, sizeof(buffer))) > 0) {
|
||||
while ((bytes_read = BIO_read(bio.get(), buffer, sizeof(buffer))) > 0) {
|
||||
result.insert(result.end(), buffer, buffer + bytes_read);
|
||||
}
|
||||
|
||||
// 检查是否解码成功(BIO_read返回0表示结束,负值表示错误)
|
||||
CRYPTO_CHECK(bytes_read >= 0, "Base64解码失败");
|
||||
|
||||
// 清理BIO
|
||||
BIO_free_all(bio);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 验证Base64格式是否有效 */
|
||||
static bool is_valid_base64(const std::string& base64_text) {
|
||||
// 检查是否只包含Base64字符(A-Z, a-z, 0-9, +, /, =)
|
||||
if (base64_text.empty()) return false;
|
||||
// 长度必须是4的倍数
|
||||
if (base64_text.size() % 4 != 0) return false;
|
||||
|
||||
for (char c : base64_text) {
|
||||
if (!((c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '+' || c == '/' || c == '=')) {
|
||||
size_t padding = 0;
|
||||
for (size_t i = 0; i < base64_text.size(); ++i) {
|
||||
char c = base64_text[i];
|
||||
if (c == '=') {
|
||||
padding++;
|
||||
// '=' 只能出现在末尾且不超过2个
|
||||
if (padding > 2 || i < base64_text.size() - padding) return false;
|
||||
} else if (!((c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '+' || c == '/')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 打印编码结果(调试用) */
|
||||
static void print_encoded(const std::string& encoded_text) {
|
||||
std::cerr << "Base64 Encoded: " << encoded_text << std::endl;
|
||||
}
|
||||
|
||||
/* 打印解码结果(调试用) */
|
||||
static void print_decoded(const std::vector<unsigned char>& decoded_bytes) {
|
||||
std::cerr << "Decoded bytes: ";
|
||||
for (unsigned char byte : decoded_bytes) {
|
||||
std::cerr << std::setw(2) << static_cast<int>(byte);
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
+15
-26
@@ -51,6 +51,7 @@ namespace qing {
|
||||
public:
|
||||
Generator() {
|
||||
key = generate_rsa_key();
|
||||
if (!key) throw Crypto_Basic::CryptoExp("RSA 密钥对生成失败");
|
||||
}
|
||||
|
||||
// 保存私钥为 PKCS#8 格式(AES-256-CBC 加密),支持密码保护
|
||||
@@ -153,7 +154,7 @@ namespace qing {
|
||||
BIO_ptr bio(BIO_new(BIO_s_mem()));
|
||||
if (!bio) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return "";
|
||||
throw Crypto_Basic::CryptoExp("导出 PEM 时无法创建 BIO");
|
||||
}
|
||||
|
||||
int ret;
|
||||
@@ -169,7 +170,7 @@ namespace qing {
|
||||
|
||||
if (ret != 1) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return "";
|
||||
throw Crypto_Basic::CryptoExp("导出 PEM 失败");
|
||||
}
|
||||
|
||||
char* data;
|
||||
@@ -246,18 +247,7 @@ namespace qing {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pem_password_cb* cb = nullptr;
|
||||
if (password) {
|
||||
cb = [](char* buf, int size, int rwflag, void* u) -> int {
|
||||
if (!u) return 0;
|
||||
const char* pass = (const char*)u;
|
||||
int len = strlen(pass);
|
||||
if (len > size) len = size;
|
||||
memcpy(buf, pass, len);
|
||||
return len;
|
||||
};
|
||||
}
|
||||
|
||||
pem_password_cb* cb = password ? &password_callback : nullptr;
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio.get(), nullptr, cb, (void*)password);
|
||||
if (!pkey) {
|
||||
HANDLE_SSL_ERROR();
|
||||
@@ -274,18 +264,7 @@ namespace qing {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pem_password_cb* cb = nullptr;
|
||||
if (password) {
|
||||
cb = [](char* buf, int size, int rwflag, void* u) -> int {
|
||||
if (!u) return 0;
|
||||
const char* pass = (const char*)u;
|
||||
int len = strlen(pass);
|
||||
if (len > size) len = size;
|
||||
memcpy(buf, pass, len);
|
||||
return len;
|
||||
};
|
||||
}
|
||||
|
||||
pem_password_cb* cb = password ? &password_callback : nullptr;
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio.get(), nullptr, cb, (void*)password);
|
||||
if (!pkey) {
|
||||
HANDLE_SSL_ERROR();
|
||||
@@ -294,6 +273,16 @@ namespace qing {
|
||||
return EVP_PKEY_ptr(pkey);
|
||||
}
|
||||
|
||||
// 密码回调(共享,消除重复 lambda)
|
||||
static int password_callback(char* buf, int size, int rwflag, void* u) {
|
||||
if (!u) return 0;
|
||||
const char* pass = static_cast<const char*>(u);
|
||||
int len = static_cast<int>(strlen(pass));
|
||||
if (len > size) len = size;
|
||||
memcpy(buf, pass, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
// RSA 解密(OAEP)
|
||||
static std::vector<unsigned char> rsa_decrypt(EVP_PKEY* private_key,
|
||||
const std::vector<unsigned char>& ciphertext) {
|
||||
|
||||
+21
-19
@@ -1,12 +1,18 @@
|
||||
#pragma once
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <iostream>
|
||||
#include <openssl/crypto.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "Crypto_Basic.hpp"
|
||||
|
||||
struct EVP_MD_CTX_deleter_sha {
|
||||
void operator()(EVP_MD_CTX* ctx) const { EVP_MD_CTX_free(ctx); }
|
||||
};
|
||||
using EVP_MD_CTX_ptr_sha = std::unique_ptr<EVP_MD_CTX, EVP_MD_CTX_deleter_sha>;
|
||||
|
||||
namespace qing {
|
||||
|
||||
class SHA256: public qing::Crypto_Basic {
|
||||
@@ -40,14 +46,18 @@ namespace qing {
|
||||
|
||||
/* 验证数据是否与给定的哈希值匹配 */
|
||||
bool verify(const std::string& input_text, const std::string& expected_hash_hex) {
|
||||
std::string computed_hash = hash(input_text);
|
||||
return computed_hash == expected_hash_hex;
|
||||
std::vector<unsigned char> computed = hash_bytes(input_text);
|
||||
std::vector<unsigned char> expected = hex_to_bytes(expected_hash_hex);
|
||||
if (computed.size() != expected.size()) return false;
|
||||
return CRYPTO_memcmp(computed.data(), expected.data(), computed.size()) == 0;
|
||||
}
|
||||
|
||||
/* 验证数据是否与给定的哈希值匹配(字节向量版本) */
|
||||
bool verify(const std::vector<unsigned char>& input_bytes, const std::string& expected_hash_hex) {
|
||||
std::string computed_hash = hash(input_bytes);
|
||||
return computed_hash == expected_hash_hex;
|
||||
std::vector<unsigned char> computed = sha256_hash(input_bytes);
|
||||
std::vector<unsigned char> expected = hex_to_bytes(expected_hash_hex);
|
||||
if (computed.size() != expected.size()) return false;
|
||||
return CRYPTO_memcmp(computed.data(), expected.data(), computed.size()) == 0;
|
||||
}
|
||||
|
||||
/* 静态方法:直接计算SHA-256哈希(工具函数) */
|
||||
@@ -62,39 +72,31 @@ namespace qing {
|
||||
return hasher.hash_bytes(input_text);
|
||||
}
|
||||
|
||||
/* 打印哈希值(调试用) */
|
||||
static void print_hash(const std::vector<unsigned char>& hash_bytes) {
|
||||
std::string hex = bytes_to_hex(hash_bytes);
|
||||
std::cerr << hex << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
/* SHA-256哈希核心实现 */
|
||||
static std::vector<unsigned char> sha256_hash(const std::vector<unsigned char>& input) {
|
||||
// 创建EVP上下文
|
||||
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
|
||||
// 创建EVP上下文(RAII 自动释放)
|
||||
EVP_MD_CTX_ptr_sha ctx(EVP_MD_CTX_new());
|
||||
CRYPTO_CHECK(ctx != nullptr, "无法创建哈希上下文");
|
||||
|
||||
// 初始化SHA-256操作
|
||||
CRYPTO_CHECK(EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) == 1,
|
||||
CRYPTO_CHECK(EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr) == 1,
|
||||
"SHA-256初始化失败");
|
||||
|
||||
// 提供输入数据
|
||||
CRYPTO_CHECK(EVP_DigestUpdate(ctx, input.data(), input.size()) == 1,
|
||||
CRYPTO_CHECK(EVP_DigestUpdate(ctx.get(), input.data(), input.size()) == 1,
|
||||
"SHA-256更新失败");
|
||||
|
||||
// 获取哈希结果
|
||||
std::vector<unsigned char> digest(EVP_MD_CTX_size(ctx)); // SHA-256输出32字节
|
||||
std::vector<unsigned char> digest(EVP_MD_CTX_size(ctx.get())); // SHA-256输出32字节
|
||||
unsigned int digest_len = 0;
|
||||
CRYPTO_CHECK(EVP_DigestFinal_ex(ctx, digest.data(), &digest_len) == 1,
|
||||
CRYPTO_CHECK(EVP_DigestFinal_ex(ctx.get(), digest.data(), &digest_len) == 1,
|
||||
"SHA-256完成失败");
|
||||
|
||||
// 调整到实际长度(应该是32字节)
|
||||
digest.resize(digest_len);
|
||||
|
||||
// 清理上下文
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return digest;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user