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:
qing committed 2026-08-08 16:05:01 +00:00
1 parent 1e34348d6c
commit 3d03f7a1ce
19 files changed
+850 -177

No files matched your search

+27 -41
View File
@@ -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;
}
};