news 2026/9/20 15:19:35

Ciphey 搜索内核重构:A* 模块拆分与不可见字符过滤驱动的字符串质量增强实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ciphey 搜索内核重构:A* 模块拆分与不可见字符过滤驱动的字符串质量增强实践

Ciphey 搜索内核重构:A* 模块拆分与不可见字符过滤驱动的字符串质量增强实践

【免费下载链接】Ciphey⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡项目地址: https://gitcode.com/gh_mirrors/ci/Ciphey

导读

本文以 docs/changes/2024-07-10-astar-refactor.md 变更记录为骨架,系统拆解 Ciphey 对 A* 解码搜索实现的一次关键重构:将原本内聚的搜索代码拆分为核心算法与辅助函数两个模块,并增强字符串质量评估——对包含超过 50% 不可见字符的候选字符串立即拒绝,从而提升内存效率与搜索聚焦度。读完本文,你将掌握 Ciphey A* 搜索器的模块边界划分、字符串质量评分公式与阈值语义、对应的测试用例设计,以及该重构与启发式简化、字符串剪枝等后续演进之间的承接关系。

一、重构背景与目标

Ciphey 的搜索器(searcher)负责决定“下一步尝试哪些解码器、按什么顺序尝试”。在其搜索内核中,A* 是最优先采用的算法(src/searchers/mod.rs 中search_for_plaintext直接以独立线程启动astar::astar)。随着启发式函数、统计学习与并行扩展等特性不断叠加,astar.rs单文件日益臃肿,职责混杂。

本次重构的核心目标有两个:

  1. 代码组织优化:将 A* 实现拆分为“搜索算法本体”与“支撑性工具函数”两个文件,让启发式计算、质量评估、统计维护等逻辑从搜索主循环中剥离;
  2. 字符串质量增强:在calculate_string_quality中引入不可见字符占比阈值,对超过 50% 不可见字符的字符串直接返回最低质量分 0.0,使这类候选在进入解码路径之前即被淘汰。

从实际收益看,这次重构属于典型的“整理+加固”:它不改变 A* 的搜索范式,而是让搜索过程中的每一次节点扩展(node expansion)都更快地丢弃低价值分支。

二、模块拆分:从单文件到职责分离

重构最直观的产出是src/searchers/目录下的文件边界变化,其结构为:

  • src/searchers/astar.rs:A* 核心搜索算法实现,包括节点定义、优先级队列、并行批处理与主搜索循环;
  • src/searchers/helper_functions.rs:支撑 A* 的辅助函数,涵盖启发式计算、字符串质量评估、解码器统计与序列模式判断;
  • src/searchers/mod.rs:通过mod astar;mod bfs;mod helper_functions;声明三个子模块,并将astarpub对外暴露(src/searchers/mod.rs)。

2.1 astar.rs:核心搜索算法

重构后的 src/searchers/astar.rs 只负责“搜索”本身,内部包含四个关键构件:

  • AStarNode节点(src/searchers/astar.rs):持有当前解码状态state、已付出代价cost(即搜索树深度 g)、综合代价total_cost(f = g + h),以及下一次要尝试的解码器名next_decoder_name
  • 最小堆优先级队列:基于BinaryHeap反向排序实现ThreadSafePriorityQueue,并封装pushpopextract_batch等线程安全操作(src/searchers/astar.rs);
  • expand_node节点扩展(src/searchers/astar.rs):先执行“decoder 标记”解码器,再回退到全量解码器;期间依次执行空文本跳过、calculate_string_worth质量过滤、seen_strings去重与update_decoder_stats统计更新;
  • astar主循环(src/searchers/astar.rs):以 Rayon 并行批处理(PARALLEL_BATCH_SIZE = 10)扩展节点,识别__RESULT__标记节点并通过crossbeam通道发送结果,在top_results模式下还会将明文写入wait_athena_storage

2.2 helper_functions.rs:辅助函数模块

src/searchers/helper_functions.rs 是本次重构新增的模块,聚合了原本散落在搜索实现中的工具函数:

  • generate_heuristic:A* 启发式(src/searchers/helper_functions.rs);
  • calculate_string_quality/calculate_string_worth:字符串质量评估与可解码性判定(src/searchers/helper_functions.rs);
  • calculate_non_printable_ratio:非可打印字符比例统计(src/searchers/helper_functions.rs);
  • update_decoder_stats/get_decoder_success_rate:解码器成功率的进程内统计(src/searchers/helper_functions.rs);
  • is_common_sequence:解码器序列常见度判断(src/searchers/helper_functions.rs);
  • check_if_string_cant_be_decoded:BFS 路径的剪枝判定(src/searchers/helper_functions.rs)。

该模块同时被 A* 与 BFS 两条搜索路径复用——src/searchers/bfs.rs 导入了check_if_string_cant_be_decoded用于节点过滤。这正是“单一职责 + 跨算法复用”的直接体现。

三、字符串质量评估增强:不可见字符过滤

本次重构的第二个重点是calculate_string_quality的行为增强。

3.1 质量评分公式

重构后的函数逻辑(src/searchers/helper_functions.rs)分为两级:

第一级:不可见字符硬性过滤

let non_printable_ratio = calculate_non_printable_ratio(s); if non_printable_ratio > 0.5 { return 0.0; // Return lowest quality for strings with >50% invisible chars }

一旦字符串中不可见(非可打印)字符占比超过 50%,质量分直接归零。由于后续calculate_string_worth以 0.2 为及格线(见 3.3),这类字符串会在节点扩展阶段被continue跳过,从根本上阻止解码器对垃圾输入的空转。

第二级:长度驱动的分段评分

if s.len() < 3 { 0.1 } else if s.len() > 5000 { 0.3 } else { 1.0 - (s.len() as f32 - 100.0).abs() / 900.0 }
  • 长度小于 3 的字符串质量固定为 0.1(过短,信息量不足);
  • 长度超过 5000 的字符串质量固定为 0.3(过长,多为噪声);
  • 其余字符串以 100 字符为最优长度中心,质量随|len - 100|线性衰减,900 为归一化分母。

3.2 非可打印字符比例的实现

calculate_non_printable_ratio(src/searchers/helper_functions.rs)统计的是控制字符(排除\n\r\t等常规空白)与非 ASCII 字符的占比:

let non_printable_count = text .chars() .filter(|&c| { (c.is_control() && c != '\n' && c != '\r' && c != '\t') || !c.is_ascii() }) .count(); non_printable_count as f32 / text.len() as f32

空字符串被定义为 1.0(全不可打印)。Hello World123!@#\n\t的比例为 0.0,而\u{0}\u{1}\u{2}的比例为 1.0。注意这里的“不可见字符”是从控制字符角度判定的;仓库另有一份独立的不可见字符表 src/storage/invisible_chars/chars.txt,由 src/storage/mod.rs 加载为INVISIBLE_CHARS集合,用于 CLI 明文输出时的安全提示(见 src/cli_pretty_printing/mod.rs),二者用途不同、互为补充。

3.3 与既有过滤机制的协同

本次增强并非孤立修改,而是与字符串剪枝体系协同工作:

  • A路径*:expand_node在每次解码产出新文本后调用calculate_string_worth(&text[0])(src/searchers/astar.rs),质量分低于 0.2 即跳过该结果并标记解码失败;随后才进行哈希去重(calculate_hash+DashSet)与节点入队;
  • BFS 路径check_if_string_cant_be_decoded综合三项判据——长度 ≤ 2、非可打印比例 > 0.3、质量分 < 0.2——任一命中即判定不可解码(src/searchers/helper_functions.rs)。

从源码结构看,A* 的calculate_string_worth只依赖质量分阈值,而 BFS 的check_if_string_cant_be_decoded阈值更激进(0.3 比例即拒绝),两条路径对低质量字符串的容忍度并不相同,属于有意为之的差异化策略。

3.4 新增测试用例

重构同步新增了针对不可见字符过滤的单元测试test_calculate_string_quality_with_invisible_chars(src/searchers/helper_functions.rs),用三组输入验证阈值语义:

  • "Hello\u{0}\u{0}\u{0}\u{0}World"(4/14 ≈ 28.6% 不可见)→ 质量分 > 0.0,通过
  • "\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}Hello"(7/12 ≈ 58.3% 不可见)→ 质量分等于 0.0,被拒绝;
  • 全不可见字符串 → 质量分等于 0.0,被拒绝。

配套的test_calculate_non_printable_ratio(src/searchers/helper_functions.rs)则验证了比例计算本身,包括常规文本为 0.0、混合内容约为 0.1666、纯控制字符为 1.0、空字符串为 1.0 等边界情况。

四、权衡分析:收益与代价

关联文档对该重构的 Trade-off 有明确陈述,结合源码可进一步展开:

优势

  • 内存效率提升:>50% 不可见字符的字符串在进入解码器之前即被淘汰,配合 A* 的seen_strings去重集合(PRUNE_THRESHOLD = 100000,见 src/searchers/astar.rs),显著减少搜索空间的膨胀;
  • 可维护性增强:辅助函数独立成模块后,astar.rs的主循环可读性明显改善,函数级单元测试(如启发式、质量评估)可以直接针对helper_functions编写,无需构造完整搜索场景;
  • 跨算法复用check_if_string_cant_be_decoded被 BFS 引用即是模块拆分带来的直接红利。

代价

  • 模块复杂度略增:新增一个文件意味着模块间函数调用增加,存在轻微的性能开销(跨模块调用对分支预测与内联的扰动);
  • 需要持续校准阈值:50% 不可见字符阈值若设置不当,可能误伤少数“长得奇怪但有效”的编码文本(如部分二进制编码产物),因此必须由测试用例持续守护。

五、结合 A* 全链路理解重构的价值

要真正理解这次字符串质量增强的意义,需要把它放回 A* 的完整决策链路中。

5.1 启发式与质量惩罚

当前实现的generate_heuristic(src/searchers/helper_functions.rs)采用加法式评分,包含四个分量:

  1. 解码器热度分量base_score += 1.0 - decoder.get_popularity(),热度越高贡献越低;
  2. 成功率代理分量base_score += (1.0 - get_decoder_success_rate(name)) * 0.25,用进程内成功率(见update_decoder_stats,src/searchers/helper_functions.rs)作为热度的补充信号;
  3. 深度惩罚(0.05 * (1.0 + depth/20) * depth)²,深度越大惩罚越激进,防止搜索在无意义路径上越走越深;
  4. 字符串质量分量base_score += (1.0 - quality) * 0.5,低质量字符串直接推高启发值,使其在优先级队列中后置。

可见calculate_string_quality的输出同时影响两处:generate_heuristic中的质量惩罚项,以及expand_node中的硬性淘汰判定。硬过滤在前、软惩罚在后,构成“先拒绝、后降权”的双层防线。

5.2 并行扩展与统计学习

A* 主循环每次从队列批量取出至多 10 个节点(PARALLEL_BATCH_SIZE),用 Rayonpar_iter并行执行expand_node(src/searchers/astar.rs)。每个节点的成功/失败都会回调update_decoder_stats,实时更新该解码器的成功次数与总尝试次数,并进而影响后续节点的启发值——这是“统计学习”机制的进程内闭环。文档中提到的“将成功率持久化到磁盘、实现跨会话学习”仍是未完成的 TODO(见 src/searchers/helper_functions.rs 的注释)。

5.3 动态剪枝

seen_strings规模超过当前阈值时,A* 会清空已见集合并按搜索进度收紧阈值(src/searchers/astar.rs):

let progress_factor = new_depth as f32 / MAX_DEPTH as f32; let new_threshold = INITIAL_PRUNE_THRESHOLD - (progress_factor * 5000.0) as usize;

即阈值从 100000 起,随深度(MAX_DEPTH = 100)线性下调至 95000,越深入搜索越频繁剪枝。字符串质量增强与此机制互为补充:质量过滤从“源头”减少进入seen_strings的垃圾字符串,动态剪枝则从“存量”控制集合规模。

六、重构的后续演进脉络

将本次变更与同目录下的其他变更记录对照,可以看到一条清晰的演进主线:

  • 2024-07-10-astar-simplified-heuristic-rewrite.md(docs/changes/2024-07-10-astar-simplified-heuristic-rewrite.md):将启发式从“多因子乘法惩罚”改为“加法式简化模型”,移除 CipherIdentifier 依赖,新增深度惩罚与热度分量——这正是重构后helper_functions.rsgenerate_heuristic的形态来源;
  • 2024-07-10-improve-string-pruning.md(docs/changes/2024-07-10-improve-string-pruning.md):将check_if_string_cant_be_decoded扩展为“长度 + 非可打印比例 + 质量分”三重判据,与本文的 50% 阈值增强同属字符串剪枝主题;
  • 2024-07-10-remove-decoder-popularity.md(docs/changes/2024-07-10-remove-decoder-popularity.md):移除冗余的get_decoder_popularity函数,改为以解码器自身popularity属性与成功率代理,进一步收紧了辅助函数模块的 API 面。

这些变更与本次重构共享同一目标:让 A在更少的节点上做更聪明的决策*。质量评估负责“少生成垃圾节点”,启发式负责“优先生成好节点”,剪枝负责“控制节点总量”。

七、未来改进方向

关联文档列出的 Future Improvements 与源码现状高度吻合:

  1. 成功率持久化DECODER_SUCCESS_RATES目前仅为Lazy<Mutex<HashMap>>的进程内结构(src/searchers/helper_functions.rs),写入磁盘的 TODO 尚未实现;一旦落地,即可实现跨会话学习,让启发式基于历史数据而非单次运行;
  2. 更精细的语言检测:当前质量评估仅依赖长度与控制字符比例,文档建议引入更成熟的语言/文本检测手段(如 n-gram 或熵分析)以提升对“随机噪声”与“真实编码”的区分度;
  3. 工具函数进一步下沉is_common_sequence、质量评估等通用函数可继续沉淀在helper_functions模块中,供 BFS、未来的 Beam Search 等其他搜索算法复用。

结语

2024-07-10的这次重构,是 Ciphey 搜索内核从“能用”走向“可控”的关键一步。通过astar.rshelper_functions.rs的职责切分,搜索算法、启发式、质量评估与统计维护各归其位;通过calculate_string_quality对 50% 不可见字符的硬性拒绝,搜索资源被集中投放到真正值得解码的候选上。对于希望深入理解 Ciphey 搜索机制或借鉴其架构思路的开发者,建议按 src/searchers/mod.rs → src/searchers/astar.rs → src/searchers/helper_functions.rs 的顺序阅读源码,并以 src/searchers/helper_functions.rs 的测试集作为行为规格说明,即可快速建立完整认知。

【免费下载链接】Ciphey⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡项目地址: https://gitcode.com/gh_mirrors/ci/Ciphey

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 15:18:12

SAP PI/PO REST适配器配置实战:5分钟打通同步接口的完整路径

做SAP PI/PO集成这么多年&#xff0c;每次听到"5分钟搞定XXX配置"这种说法&#xff0c;第一反应都是嗤之以鼻。但REST适配器这个场景&#xff0c;我要说句公道话&#xff1a;在准备工作到位的前提下&#xff0c;5分钟把同步接口从零配到能通&#xff0c;真不是标题党…

作者头像 李华
网站建设 2026/9/20 15:18:03

CAT 切面注解埋点实战:SpringMVC 环境下基于 AOP 的零侵入监控方案

可观测性指标监控告警APM后端链路追踪 【免费下载链接】cat CAT 作为服务端项目基础组件&#xff0c;提供了 Java, C/C, Node.js, Python, Go 等多语言客户端&#xff0c;已经在美团点评的基础架构中间件框架&#xff08;MVC框架&#xff0c;RPC框架&#xff0c;数据库框架&…

作者头像 李华
网站建设 2026/9/20 15:17:23

霍普金森杆实验数据处理程序的设计与实现

简介&#xff1a;这份资源是一篇关于霍普金森杆实验数据处理程序设计与实现的学术论文PDF&#xff0c;适合材料动力学、冲击力学及相关军事工程领域的研究人员、工程师和高年级学生阅读。内容系统阐述了SHPB实验原理、入射波/反射波/透射波的分离难点&#xff0c;并给出了基于V…

作者头像 李华
网站建设 2026/9/20 15:16:48

SQL注入实战:sqli-labs靶场6-10关盲注与文件写入技巧详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 15:15:19

Qt 6.8 LTS与Qt for MCUs 2.9全栈嵌入式GUI技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 15:15:10

Kimi 论文调研老断在 Key 上?Base URL 填 TaoToken 的 API 地址

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华