- 新增 smtp3: pymsg/TCP :8008 邮件验证码服务 (smtp_v2.py 重写, 零新增依赖) - 审计实证并修复 2 项 P0: SMTP 响应解析颠倒 (发送 100% 失败)、base64 符号扩展 - 修复 P1-2 SIGPIPE、P3-1 日志注入脱敏、P3-3 IPv6、P3-4 模偏差、P3-5 LogC 长连接复用 - 剩余 P1-1 (TLS 证书校验) 与端到端发信验证待 smtp.ini 凭据就绪 - 新增审计报告 docs/security/smtp3_SECURITY_AUDIT_20260809.md 并更新 INDEX
22 KiB
smtp3 模块安全审计报告
审计日期: 2026-08-09
审计范围: smtp3/src/main.cpp、smtp3/inc/LogC.hpp、smtp3/Makefile、smtp3/_run.sh、smtp3/_set.sh、confs/configs/smtp.ini
代码版本: main @ 6bd0fca
审计方式: 静态代码审查 + 可疑逻辑最小化复现验证(本机编译执行)+ 与 Python 版 smtp_v2.py、gateway 调用方、libmsg 基础库交叉比对
参照文档: smtp_SECURITY_AUDIT_20260801.md(Python 版审计,含 0809 复审)、smtp_cpp_rewrite_dev_doc.md(重写开发方案)
一、结论速览
| 等级 | 数量 | 已修复 | 说明 |
|---|---|---|---|
| P0 | 2 | 2 ✅ | SMTP 响应解析逻辑颠倒(发送 100% 失败)、base64 符号扩展(UTF-8 内容乱码) |
| P1 | 2 | 1 ✅ | P1-2 SIGPIPE 已修;P1-1 TLS 无证书校验/无 SNI 待修 |
| P2 | 1 | 1 ✅ | SMTP 响应读取无大小上限(随 P0-1 一并修复) |
| P3 | 5 | 5 ✅ | 全部修复:P3-2 随 P0-1;P3-1/3/4/5 于 2026-08-09 修复并经运行时验证 |
总体结论: smtp3 对 Python 版 7 项审计遗留(P1-F1 ~ P3-F7)的修复全部落实且实现正确(见 §七),路由协议与响应格式与 gateway 调用方完全兼容(见 §八)。但 SmtpClient(重写中新手写的 SMTP_SSL 客户端)存在 2 个 P0 级功能阻断缺陷——本审计已在本机编译复现实证:审计时点的二进制不具备发出任何一封邮件的能力。此前的重写验证只覆盖了编译、启动、confs 拉取与 --help,未覆盖真实 SMTP 会话(smtp.ini 凭据为空),导致 P0 未被发现。
修复进展(2026-08-09 当日): P0-1 / P0-2 已修复并重建二进制,顺带关闭 P2-1 / P3-2;P1-2(SIGPIPE)已修复并经运行时信号投递验证;P3-1 / P3-3 / P3-4 / P3-5 已修复并经运行时验证(日志脱敏实测、LogC 长连接写入 db 实测);修复代码经 14 项逻辑验证用例全部通过(见 §十一)。剩余:P0/P1-2/P2/P3 已全部关闭;上线阻断条件收敛为:P1-1(TLS 校验)修复 + 真实 SMTP 账号端到端发信验证,在此之前仍禁止用 smtp3 替换 Python 版 smtp。
部署现状(截至本审计):core/init.txt 仍拉起 Python 版 smtp/_run.sh;_inst.sh 仅含 smtp 未含 smtp3;confs/configs/smtp.ini 的 server/user/password 为空。smtp3 尚未上线,上述 P0 未对生产造成实际影响。
二、🔴 P0 — 致命问题(发布阻断)
P0-1: read_response 行解析逻辑颠倒,所有 SMTP 会话必然阻塞超时,send_email 100% 失败 ✅ 已修复
-
位置:
src/main.cppL567-599(SmtpClient::read_response) -
问题: 判定"已收到最终响应行"的逻辑是取
full.rfind("\r\n")之后的内容作为最后一行:auto last_crlf = full.rfind("\r\n"); if (last_crlf != std::string::npos) { std::string last_line = full.substr(last_crlf + 2); // ← 取尾部 CRLF 之后 if (last_line.size() >= 4 && last_line[3] == ' ') { ... return full; } } // 否则继续 SSL_readSMTP 响应每行以 CRLF 结尾(RFC 5321 §4.2),完整响应
"220 OK\r\n"的rfind("\r\n")命中的是尾部 CRLF,last_line为空串 → 判定"未读完" → 继续SSL_read→ 服务器不会再发数据 → 阻塞至 20 秒 socket 超时 → 抛SSL_read 失败。逻辑完全反了:只有残缺的 TCP 分包(最终行尚未收到尾部 CRLF)才会被判定为"读完"。 -
实证(提取原逻辑最小化复现,2026-08-09 本机执行):
输入(模拟一次 SSL_read 收到的数据) 实际判定 正确判定 "220 OK\r\n"(标准单行完整响应)❌ 继续读 → 超时 应返回 "250-A\r\n250 OK\r\n"(多行完整响应)❌ 继续读 → 超时 应返回 "250-A\r\n250 OK"(无尾 CRLF 的残缺包)⚠️ 提前返回 应继续读 -
影响:
- 功能阻断: 第一步
read_response(ssl, 220)(greeting)即挂死,任何配置下 send_email 均在 ~20s 后以"验证码发送失败"告终 → 注册 / 重置密码全流程不可用。 - DoS 放大: 每个 send_email 请求占住一个 worker 线程 ~20s;
workers = 4时 4 个并发请求即可占满全部 worker,期间health/verify_email全部无响应。且发送失败会回滚冷却与限流预占("失败不计入配额"语义),客户端可无限重试,阻断可持续维持。
- 功能阻断: 第一步
-
修复建议: 改为按完整行解析——查找每个以 CRLF 结尾的行,检查最后一个完整行是否匹配
^\d{3}(第 4 字符为空格即最终行,-为续行);缓冲区尾部未闭合的数据视为未完成继续读。修复后必须用真实 SMTP 账号完成一次端到端发信验证。 -
修复记录(2026-08-09): 已按建议重写为完整行解析(
main.cppread_response),响应码改逐字符数字校验(顺带关闭 P3-2),累计缓冲加 64KB 上限(顺带关闭 P2-1)。验证:单行/多行完整响应正确返回,残缺包/续行/空缓冲正确续读,码不匹配走异常路径,14 项用例全部通过;-Wall -Wextra零警告重建smtp3.bin。端到端真实发信验证待 smtp.ini 凭据就绪后执行。
P0-2: base64_encode 对 char 符号扩展,所有含非 ASCII 字节的输入编码损坏(默认中文文案即中招) ✅ 已修复
-
位置:
src/main.cppL80-94(base64_encode),调用方 L473-475(AUTH LOGIN)、L645-646(MIME 主题/正文) -
问题:
uint32_t n = (uint32_t(data[i]) << 16)——data[i]是char(x86-64 Linux 默认有符号),字节 ≥0x80时先符号扩展为0xFFFFFFxx再移位,高位污染同组其余字节:uint32_t n = (uint32_t(data[i]) << 16); // 0xE9 → 0xFFFFFFE9 → 0xFFE90000 if (i + 1 < data.size()) n |= (uint32_t(data[i + 1]) << 8); // OR 进一步互相污染 -
实证(原函数最小化复现,2026-08-09 本机执行):
输入 实际输出 正确输出 "Hello"(纯 ASCII)SGVsbG8=✅SGVsbG8="DNFS 邮箱验证"(生产默认主题)RE5G///p///n///p///o/4E=❌RE5GUyDpgq7nrrHpqozor4E= -
影响:
- 默认主题与正文均为中文(
"DNFS 邮箱验证"/"DNFS: 您的邮箱验证码为 {code},10 分钟内有效。"),base64 损坏后邮件客户端解码出乱码/解码失败——即使 P0-1 修复,用户也拿不到可读的验证码; - AUTH LOGIN 凭据受损: 若 SMTP 账号或密码含非 ASCII 字符(部分服务商授权码允许中文),
base64_encode(user/password)输出错误,认证必然失败且被脱敏文案掩盖; - 纯 ASCII 内容(如英文 subject)不受影响——这是该缺陷隐蔽的原因,但本项目默认配置恰好全部命中。
- 默认主题与正文均为中文(
-
修复建议: 移位前统一转无符号:
uint32_t(data[i] & 0xFF)(或unsigned char强转),三处移位全部适用。修复后以"DNFS 邮箱验证"等 UTF-8 样例做编码往返单测(与 Pythonbase64.b64encode输出逐字节比对)。 -
修复记录(2026-08-09): 三处移位已改为
uint32_t(uint8_t(data[i]))。验证:"DNFS 邮箱验证"、中文正文(含验证码替换后形态)、全高位字节\xE9\xE9\xE9、填充边界共 5 项用例与 Pythonbase64.b64encode基准逐字节一致,全部通过。
三、🟠 P1 — 高危问题
P1-1: TLS 客户端无证书校验、无主机名校验、无 SNI、无最低版本钳制
- 位置:
src/main.cppL457-463(SmtpClient::sendTLS 握手段) - 问题: 握手只做
SSL_CTX_new→SSL_new→SSL_set_fd→SSL_connect,全程:- 未调用
SSL_CTX_set_default_verify_paths+SSL_CTX_set_verify(VERIFY_PEER)→ 不校验服务器证书链; - 未调用
SSL_set1_host/X509_VERIFY_PARAM_set1_host→ 不校验证书主机名; - 未调用
SSL_set_tlsext_host_name→ 不发送 SNI(多租户 SMTP 端点可能握手失败或拿到错误证书); - 未钳制最低 TLS 版本(
SSL_CTX_set_min_proto_version)。
- 未调用
- 影响: SMTP 出站链路存在主动中间人时,攻击者可完整截获
AUTH LOGIN凭据(base64 明文语义)与验证码正文,且客户端毫无感知。Python 版smtplib.SMTP_SSL在 Python 3.4+ 同样默认不校验证书(同源缺陷,见 smtp 版审计),故本项不属于回归,但重写是消除该缺陷的正确时机。 - 修复建议: 加载系统 CA(
SSL_CTX_set_default_verify_paths),SSL_set1_host(ssl, server),SSL_set_tlsext_host_name,SSL_CTX_set_min_proto_version(TLS1_2_VERSION)。如需兼容自签证书可加配置项verify_cert = on/off(默认 on)。
P1-2: 未忽略 SIGPIPE,SMTP 会话中途被服务器断开时整个 smtp3 进程被内核终止 ✅ 已修复
- 位置:
src/main.cpp(全文无信号处理);对比gateway/src/main.cppL773-804(显式sigaction(SIGPIPE, SIG_IGN)并有专门注释说明该风险) - 问题:
SmtpClient经裸 socket 做SSL_write(未带MSG_NOSIGNAL语义)。若 SMTP 服务器在会话中途 RST/关闭连接(超时、限流、反垃圾策略均可能),下一次SSL_write触发 SIGPIPE → 默认行为是终止整个进程,而非仅让该次发送失败。Python 解释器默认忽略 SIGPIPE,故 Python 版不存在此问题——本项是 C++ 重写新引入的缺陷。 - 影响: 单次发送失败升级为全站邮件服务(含 verify_email / health)整体下线;libmsg 的
MsgClient::send虽带MSG_NOSIGNAL,但只覆盖 pymsg 侧连接,不覆盖 SMTP 出站连接。core 守护会拉起进程,但窗口期内内存中的验证码与限流状态全部丢失。 - 修复建议:
main()开头添加signal(SIGPIPE, SIG_IGN)(与 gateway 做法一致),或在 socket 层改用带错误检测的发送路径。 - 修复记录(2026-08-09):
main()入口已加std::signal(SIGPIPE, SIG_IGN)(含<csignal>头)。验证:重建二进制后启动进程并向其投递 SIGPIPE,进程存活(修复前默认行为为终止);零警告编译,--help正常。
四、🟡 P2 — 中危问题
P2-1: read_response 累积缓冲无大小上限,异常 SMTP 服务器可致内存耗尽 ✅ 已修复(随 P0-1)
- 位置:
src/main.cppL567-577(full += buf无界循环) - 问题: 循环
SSL_read累积进std::string full,直到解析出最终响应行或超时。若(恶意或被入侵的、由运营者配置的)SMTP 服务器持续发送不含"NNN "终止行的数据,20 秒 socket 超时窗口内(且 SSL_read 每次收到数据即重置超时,实际可远超 20 秒)full无界增长。 - 影响: 内存耗尽型 DoS。SMTP 服务器为运营者配置的受信目标,故定 P2;修复成本极低。
- 修复建议: 设
full上限(如 64KB,远超任何正常 SMTP 响应),超限即抛异常。 - 修复记录(2026-08-09): 已随 P0-1 修复一并加入 64KB 上限,超限抛异常进入发送失败回滚路径。
五、🔵 P3 — 低危 / 健壮性问题
P3-1: verify_email 路由 email 未校验直接入日志,存在日志注入 ✅ 已修复
- 位置:
src/main.cppL921、L927、L936 - 问题:
send_email有严格邮箱正则(P3-F5),但verify_email对任意字符串(含\r\n等控制字符)原样拼入日志消息写入 db Logs 表。gateway 传入的 email 已经过校验,直接 pymsg 调用(127.0.0.1 信任域内)则未校验。 - 影响: 低——攻击者需已处于本机信任域;日志按行检索时可能被伪造行干扰。
- 修复建议: 日志拼接前剥离控制字符,或复用 send_email 的邮箱正则做入口校验。
- 修复记录(2026-08-09): 新增
sanitize_for_log(控制字符/DEL 替换为?),verify_email三处日志均经脱敏。实测:email 传evil\r\nINJECTED,db Logs 表落库为evil??INJECTED,无法伪造新日志行。
P3-2: read_response 内 std::stoi 未捕获异常,非数字响应行导致不可诊断错误 ✅ 已修复(随 P0-1)
- 位置:
src/main.cppL586 - 问题: 若服务器最终行第 4 字符恰为空格但前 3 字符非数字(畸形响应),
stoi抛invalid_argument,错误路径无响应内容上下文。 - 修复建议: 先逐字符校验
isdigit,非数字按协议错误处理并携带原始行。 - 修复记录(2026-08-09): 已随 P0-1 修复改为逐字符
isdigit校验 + 手工解码,畸形行不再抛异常而是继续读(由 64KB 上限兜底)。
P3-3: connect_to_server 硬编码 AF_INET,仅支持 IPv4 ✅ 已修复
- 位置:
src/main.cppL506 - 问题: 双栈环境下若 SMTP 服务器仅有 AAAA 记录则解析失败。Python
smtplib支持 IPv6,存在轻微行为差异。 - 修复建议:
AF_UNSPEC。 - 修复记录(2026-08-09):
ai_family改为AF_UNSPEC,后续getaddrinfo结果链表按序尝试连接,IPv4/IPv6 均可达。
P3-4: generate_code 存在模偏差 ✅ 已修复
- 位置:
src/main.cppL633(rd() % 10) - 问题:
std::random_device返回 32 位值,% 10使数字 0-5 的出现概率比 6-9 高约 2/2³²——偏差量级可忽略,但修复成本同样可忽略。 - 修复建议:
std::uniform_int_distribution<int>(0, 9)。 - 修复记录(2026-08-09): 改用
std::uniform_int_distribution<int>(0, 9),模偏差消除。
P3-5: LogC 每批日志逐条同步 RPC,且每批新建 TCP 连接 ✅ 已修复(连接复用部分)
- 位置:
inc/LogC.hppL80-99 - 问题: 与 captcha2 审计 P3-4 同源(该模式自 captcha2 移植而来):一批最多 50 条日志逐条
call(),且每批新建一次 db 连接。 - 影响: 性能开销,无安全影响;fail-safe 语义正确。
- 修复建议: 批量 INSERT 或连接复用(可留待 LogC 统一重构时一并处理,db2/captcha2/smtp3 共享同一模式)。
- 修复记录(2026-08-09): LogC 改用底层
detail::openConnection+pmsg_send/pmsg_recv长连接(与MsgClient::call线路格式一致,无前缀),跨批复用同一 fd,故障时关闭重建、本批丢弃(fail-safe 不变)。实测:启动与 verify_email 日志经长连接成功落库 db Logs 表。逐条 RPC 改批量 INSERT 需 db 侧协议配合,留待 LogC 统一重构(captcha2/db2 同源模式)。
六、✅ 已有安全机制(14 项)
| # | 机制 | 位置 |
|---|---|---|
| 1 | 常数时间验证码比较(XOR 累积,防时序侧信道) | CodeStore::const_time_eq L307-313 |
| 2 | 验证码一次性消费,防重放 | CodeStore::verify L269-271 |
| 3 | 连续失败 5 次作废(防 6 位数字码在线枚举) | CodeStore::verify L275-279 |
| 4 | 惰性过期清理,内存无界增长防护 | CodeStore::expire_locked L296-304 |
| 5 | 邮箱级双窗口限流(3/h + 10/d)+ 全局熔断(100/h) | SendLimiter L323-426 |
| 6 | ts_id 精确回滚(根治 Python 版 P1-F1 的浮点比较回滚失效) |
SendLimiter::rollback L364-377 |
| 7 | 同邮箱 60s 发送冷却,预占 + 失败回滚,并发防重 | send_email 路由 L792-827 |
| 8 | std::random_device 生成验证码(修复 Python 版 P2-F3) |
generate_code L628-635 |
| 9 | 日志不打印验证码明文(修复 Python 版 P2-F2,对比 Python L250 明文入日志) | L884 |
| 10 | 失败响应脱敏,SMTP 错误细节仅入服务端日志(修复 Python 版 P3-F7) | L858-865 |
| 11 | 严格邮箱正则,与 gateway 对齐(修复 Python 版 P3-F5) | L752 |
| 12 | subject ≤256B / content ≤4KB 长度上限(修复 Python 版 P3-F6) | L772-789 |
| 13 | 配置白名单合并(仅识别已知 section/key),confs 强依赖阻塞等待,凭据缺失仅警告不阻断 | merge_ini / validate_config |
| 14 | pymsg 侧 EPIPE 防护继承自 libmsg MSG_NOSIGNAL;日志 fail-safe(db 不可用静默丢弃) |
libmsg/Msg.hpp L234、LogC.hpp |
七、与 Python 版审计 7 项遗留的对照
| 编号 | Python 版缺陷 | smtp3 落实情况 | 复核结论 |
|---|---|---|---|
| P1-F1 | now 变量遮蔽 + 浮点 == 比较导致发送失败时限流/熔断回滚失效 |
ts_id 单调 ID 预占,erase_by_tsid 精确删除 |
✅ 根治,实现优于 Python 修复方案 |
| P2-F2 | logs.info(f"...({code})") 验证码明文写入 Logs 表 |
成功日志仅 "验证码发送成功" |
✅ 已修复 |
| P2-F3 | random.randint 弱随机源 |
std::random_device(P3-4 模偏差亦已修复) |
✅ 已修复 |
| P3-F4 | == 比较存在时序侧信道 |
const_time_eq XOR 累积比较 |
✅ 已修复 |
| P3-F5 | 邮箱仅校验 "@" in email |
严格正则 ^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$ |
✅ 已修复(send_email 路径) |
| P3-F6 | subject/content 无长度限制 | 256B / 4KB 上限 | ✅ 已修复 |
| P3-F7 | 发送失败响应原样回传 SMTP 异常细节 | 通用文案返回客户端,细节仅入日志 | ✅ 已修复 |
结论: 重写方案的"一并根除 7 项审计遗留"目标全部达成。本轮新发现的 P0/P1 均集中在重写新增的 SmtpClient 组件,与上述修复项无交集。
八、与 gateway 的协议兼容性核对
对照 gateway/src/main.cpp 的调用点(L525-540 verify、L2064-2085 注册发码、L2177-2195 重置发码)逐项核对:
| 核对项 | gateway 期望 | smtp3 实际 | 结论 |
|---|---|---|---|
| 传输/封装 | pymsg TCP :8008,响应 {success, data} |
libmsg RpcServer 自动封装 |
✅ |
verify_email 字段 |
email / code,读 data.valid |
一致,另兼容旧字段 input_captcha |
✅ |
send_email 字段 |
email(+ 可选 subject/content) |
一致 | ✅ |
| 冷却拒绝 | 读 retry_after(int64)与 error 文案透传客户端 |
一致 | ✅ |
| 发码超时 | 20s(_TIMEOUT_SMTP_SEND) |
内部 SMTP 会话 20s 超时,边界相当 | ✅ |
health |
{status, service} |
{"status":"ok","service":"smtp"} |
✅ |
有意的行为差异(均为改进,不影响 gateway):
- 限流(双窗口/熔断)拒绝时 smtp3 会回滚 60s 冷却预占,Python 版不回滚——smtp3 语义更合理(冷却只应锚定真实发送);
subject/content为非字符串类型时 smtp3 回退默认值,Python 版str()强转(如"None")——smtp3 更稳健;- email 做 strip 与否:Python
strip()、smtp3 不 strip——带首尾空格的邮箱两侧均无法通过后续正则/存储匹配,无实际影响。
九、继承自 Python 版 / 架构层面的已知项(不计入本轮发现)
- pymsg 无认证: 与所有 pymsg 服务同源(smtp P0-2、captcha、db 同),依赖 127.0.0.1 绑定隔离,待
SECURITY_HARDENING_PLAN_20260803.md内网通信加固统一解决。 - 验证码存进程内存: 重启即失效,单实例不可水平扩展——与 Python 版完全一致,属设计取舍。
- SMTP 凭据明文: 存于
confs/configs/smtp.ini并经明文 pymsg 分发,与全项目 confs 模式一致。
十、修复路线图
立即(上线前置条件)
- ✅ P0-1 重写
read_response为按完整行解析(最后完整行^\d{3}判定),并加 64KB 缓冲上限(顺带修复 P2-1)——2026-08-09 完成; - ✅ P0-2
base64_encode三处移位改经uint8_t转无符号,补 UTF-8 编码往返单测——2026-08-09 完成; - 用真实 SMTP 账号完成一次端到端发信验证(含中文主题/正文解码核对、残缺包/多行响应/超时路径测试)——本次审计证明"编译通过 + 绑定端口"级别的验证不足以覆盖网络协议栈重写。待凭据就绪后执行。
短期
- ✅ P1-2
main()忽略 SIGPIPE——2026-08-09 完成; - P1-1 TLS 证书链 + 主机名校验 + SNI + TLS≥1.2(待修)。
中期
- ✅ P3-1 ~ P3-5 全部完成(2026-08-09);逐条 INSERT 改批量仍留待 LogC 统一重构(db2/captcha2 同源)。
上线切换(全部 P0/P1 关闭后)
confs/configs/smtp.ini填充真实凭据 →core/init.txt切换smtp3/_run.sh→_inst.sh增加smtp3→ 观察 24h 日志后下线 Python 版。
十一、P0 修复验证用例清单(2026-08-09,14/14 通过)
验证程序从修复后的 main.cpp 原样提取 base64_encode 与 read_response 行判定逻辑,g++ -std=c++20 -Wall -Wextra -O2 编译执行,用后即删;base64 基准由 Python base64.b64encode 计算。
| # | 用例 | 预期 | 结果 |
|---|---|---|---|
| 1 | base64 纯 ASCII "Hello" |
SGVsbG8= |
✅ |
| 2 | base64 中文主题(生产默认值 "DNFS 邮箱验证") |
与 Python 基准逐字节一致 | ✅ |
| 3 | base64 中文正文(验证码占位替换后形态) | 与 Python 基准逐字节一致 | ✅ |
| 4 | base64 全高位字节 \xE9\xE9\xE9 |
6enp |
✅ |
| 5 | base64 长度 1/2 填充边界 | QQ== / QUI= |
✅ |
| 6 | 单行完整响应 "220 OK\r\n" |
解析返回 | ✅ |
| 7 | 多行完整 EHLO 响应(含 SIZE/AUTH 续行) | 解析返回 | ✅ |
| 8 | 残缺包(无尾 CRLF) | 继续读 | ✅ |
| 9 | 残缺包(多行尾行未闭合) | 继续读 | ✅ |
| 10 | 续行结尾 "250-AUTH\r\n" |
继续读 | ✅ |
| 11 | 响应码不匹配(550 vs 预期 250) | 异常路径 | ✅ |
| 12 | 畸形行 "ABC X\r\n" |
继续读,不抛 stoi | ✅ |
| 13 | 空缓冲 | 继续读 | ✅ |
| 14 | 仅 CRLF | 继续读 | ✅ |
配套验证:bash _set.sh 零警告重建 smtp3.bin(438KB),--help 正常响应。
附:实证记录
- 复现程序从
main.cpp原样提取base64_encode(L77-94)与read_response行判定逻辑(L567-599),g++ -std=c++20 -O2编译执行(2026-08-09); - base64 基准值由
python3 -c "base64.b64encode(...)"计算; - 复现文件用后即删,未入库;结论可通过上述代码段独立复核。