Ciphey A* 搜索解码算法深度解析:启发式评估、剪枝策略与工程实现
发布时间:2026/9/20 18:43:23 作者:尧图编辑部 阅读量:1,286

CLI网络安全【免费下载链接】Ciphey⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡项目地址https://gitcode.com/gh_mirrors/ci/Ciphey点击查看免费下载本篇技术指南围绕 Ciphey 的 A* 搜索实现文档系统讲解该项目如何在不知道密钥与具体密码算法的情况下通过 A* 搜索自动编排解码器序列并完成密文破解。读完本文你将掌握 Ciphey 中 A* 的f g h评分模型、五类乘法罚分因子的数学定义、解码器流行度评分体系、基于质量分数的搜索空间剪枝机制以及 Rayon 并行扩展等工程实现细节。为什么 Ciphey 需要一个搜索算法Ciphey 的核心问题是如何决定下一步尝试哪种解码。当输入文本可能经过多次编码例如 Base64 → ROT13 → 十六进制时单个解码器无法一次还原明文程序必须像在状态图中寻路一样不断在当前文本 × 可用解码器的组合中探索。这一决策由 searchers 模块 负责其入口函数search_for_plaintext接收原始输入启动一个独立线程运行astar::astar并通过crossbeam通道接收结果。模块中同时保留了最简单的广度优先搜索实现 bfs.rs 作为对照而 A* 之所以成为默认选择正是因为它在 BFS 的完备性之上增加了启发式引导能够优先探索更像明文的路径。从源码结构看search_for_plaintext中 A* 线程与主循环通过stop: ArcAtomicBool协作找到结果或计时器到期时置位停止信号主循环每 10ms 轮询一次结果通道避免 CPU 空转。这一设计同时支撑了普通模式与top_results模式详见后文。核心算法f g hA* 实现遵循标准的最佳优先搜索公式f g h其中g 搜索树中的深度已付出的代价每应用一个解码器cost字段加 1。在 astar.rs 中AStarNode的cost字段即代表到达当前状态已使用的解码器数量。h 启发式值到目标的估计代价由generate_heuristic计算数值越低表示该状态越接近明文越应优先扩展。AStarNode在f值之上还携带一个next_decoder_name字段详见解码器专属节点一节使每个节点不只是一个文本状态而是一个文本状态 下一步要尝试的解码器。优先队列按total_cost即f排序并通过自定义Ord实现翻转比较将BinaryHeap最大堆当作最小堆使用——f值最小的节点最先被弹出扩展。执行流程两阶段搜索A* 搜索分两个阶段进行1. 初始全量运行Initial Full Run首先对输入文本一次性运行所有解码器目的是不遗漏任何单步解码即成功的简单解结果立即交给 Athena 检查器判定是否命中明文失败的结果不会浪费其反馈会参与初始启发式计算解码器成功率统计等。在 filtration_system/mod.rs 的Decoders::run中可以看到对应实现所有解码器通过rayon::into_par_iter()并行执行.crack()一旦某个解码器被检查器判为success迭代器立即短路return None返回MyResults::Break否则聚合全部结果为MyResults::Continue供 A* 继续探索。2. A* 搜索阶段若初始全量运行未找到解则进入 A* 主循环在每个节点先处理带有decoder标签的解码器它们被认为是更可能产生有意义结果的候选其余解码器按启发式分数排序后放入优先队列等待探索。get_decoder_tagged_decoders通过DecoderFilter::include_tag(decoder)实现标签过滤。从源码看a1z26、atbash、全部 base 系列base32/58/64/91/65536/z85、binary、braille、brainfuck、caesar、citrix_ctx1、hexadecimal、morse_code、railfence、reverse、rot47、substitution_generic、url、vigenere等解码器均带有decoder标签构成了先试快路径、再走启发式慢路径的两级调度。启发式计算乘法罚分模型启发式函数 h(n) 是本文档的核心其数学定义是对一个基础分施加一系列乘法罚分h(n) b * p_s * p_r * p_p * p_q * p_c各符号含义与计算方式如下表符号含义计算方式b基础分Cipher Identifier 输出归一化到 [0.0, 1.0]p_s序列罚分序列不常见时为 1.25否则 1.0p_r成功率罚分1.0 (1.0 - r)p_p流行度罚分1.0 (2.0 × (1.0 - p))p_q质量罚分1.0 (1.0 - q)p_c字符集罚分无非打印字符为 1.0否则 1.0 e^(100r)基础分 bBase Score由 Cipher Identifier密文识别器生成归一化到 [0.0, 1.0]。对于无法识别的未知模式会赋予 0.51.0 之间的随机值以维持搜索的探索性避免启发式过早收敛而错过隐藏路径。序列罚分 p_sSequence Penalty当上一个解码器 → 当前密文类型的组合属于不常见序列时施加 1.25 倍罚分。在 helper_functions.rs 的is_common_sequence中常见序列以白名单方式枚举例如Base64Decoder → Base32Decoder、Base64Decoder → Base58Decoder、Base32Decoder → Base85Decoder、同类型连续使用如Base64 → Base64等均被视为常见其余组合一律视为不常见序列。成功率罚分 p_rSuccess Rate Penalty对成功率为 r 的解码器p_r 1.0 (1.0 - r)罚分随失败率线性放大r 1.0 → p_r 1.0无罚分r 0.5 → p_r 1.550% 罚分r 0.0 → p_r 2.0100% 罚分实现上helper_functions.rs 通过全局静态变量DECODER_SUCCESS_RATES: MutexHashMapString, (usize, usize)记录每个解码器的(成功次数, 总尝试次数)update_decoder_stats在每次解码尝试后更新计数get_decoder_success_rate计算比率未知解码器默认返回 0.5。这是统计学习见性能优化第 4 条的数据基础——成功率并非静态配置而是在单次搜索运行中持续演化。流行度罚分 p_pPopularity Penalty对流行度为 p 的解码器p_p 1.0 (2.0 × (1.0 - p))该罚分对冷门解码器非常激进p 1.0 → p_p 1.0无罚分p 0.5 → p_p 2.0100% 罚分p 0.1 → p_p 2.8180% 罚分流行度是每个解码器的静态属性定义在Decoder结构体的popularity字段中见 interface.rsCracktrait 提供默认返回 0.5 的get_popularity()方法。质量罚分 p_qQuality Penalty对质量为 q 的字符串p_q 1.0 (1.0 - q)其中 q 根据字符串长度 l 计算q 0.1 若 l 3 q 0.3 若 l 5000 q 1.0 - |l - 100| / 900 其他情况这一分段函数表明长度接近 100 的字符串质量最高过短3的字符串几乎无信息量超长5000的字符串质量骤降。在 helper_functions.rs 的calculate_string_quality中还有一条前置规则非打印字符占比超过 50% 的字符串直接返回质量 0.0最低质量。字符集罚分 p_cCharacter Set Penalty对非打印字符占比为 r 的字符串p_c 1.0 若 r 0 p_c 1.0 e^(100r) 其他情况指数型罚分是五个因子中唯一的非线性项只要文本中混入少量二进制控制字符e^(100r)就会爆炸式增长从而强力遏制对二进制/损坏路径的探索。calculate_non_printable_ratio的实现将控制字符排除常见的\n、\r、\t与非 ASCII 字符计为非打印字符空字符串直接返回 1.0。实现示例文档给出了该启发式计算的 Rust 实现骨架fn generate_heuristic(text: str, path: [CrackResult]) - f32 { // Base score from Cipher Identifier let (cipher, base_score) get_cipher_identifier_score(text); let mut final_score base_score; if let Some(last_result) path.last() { // Penalize uncommon sequences if !is_common_sequence(last_result.decoder, cipher) { final_score * 1.25; // 25% penalty } // Penalize low success rates let success_rate get_decoder_success_rate(last_result.decoder); final_score * 1.0 (1.0 - success_rate); // Penalty scales with failure rate // Penalize decoders with low popularity let popularity get_decoder_popularity(last_result.decoder); final_score * 1.0 (2.0 * (1.0 - popularity)); // Penalty scales with unpopularity } // Penalize low quality strings final_score * 1.0 (1.0 - calculate_string_quality(text)); // Penalize non-printable characters let non_printable_ratio calculate_non_printable_ratio(text); if non_printable_ratio 0.0 { final_score * 1.0 (non_printable_ratio * 100.0).exp(); } final_score }需要说明的实现差异仓库中 helper_functions.rs 实际生效的generate_heuristic是简化后的加性版本——它直接累加(1.0 - popularity)、自适应深度罚分(depth_coefficient * path.len()).powi(2)、字符串质量罚分(1.0 - quality) * 0.5以及不常见序列罚分 0.25而不是文档所描述的乘法连乘。这一演化过程在 astar_algorithm_improvements.md 中有明确记录Simplified Heuristic Function一节简化后的启发式更直观、更易维护且三项组件流行度、自适应深度罚分、字符串质量均已落地实现。读者可将docs/astar.md视为算法设计蓝本将helper_functions.rs视为当前工程实现二者共同构成了对 Ciphey 启发式系统的完整认知。解码器流行度评分体系文档为解码器分配了基于真实场景使用频率的静态流行度评分这是p_p罚分的数据来源Base64, Hexadecimal, Binary, rot13, rot47 → 1.0 Base32, Vigenere → 0.8 Base58 → 0.7 Base85, SimpleSubstitution → 0.5 Base91 → 0.3 Citrix CTX1 → 0.1 Unknown decoders → 0.5对照当前仓库中各个解码器文件里的popularity字段实际值见 decoders 目录可以观察到评分的具体落点解码器popularity 实际值源码位置Base64 / Base32 / Binary / Hexadecimal / ROT471.0base64_decoder.rs、base32_decoder.rs、binary_decoder.rs、hexadecimal_decoder.rs、rot47_decoder.rsBase58 Bitcoin / Ripple0.8base58_bitcoin_decoder.rs、base58_ripple_decoder.rsBraille / Caesar / Morse / Vigenere / URL / Z85 / Substitution / Atbash0.60.8对应解码器文件Base58 Flickr / Monero / Reverse0.20.4base58_flickr_decoder.rs、base58_monero_decoder.rs、reverse_decoder.rsBase91 / Base65536 / Citrix CTX10.10.3base91_decoder.rs、base65536_decoder.rs、citrix_ctx1_decoder.rsDecoder::new在 interface.rs 中为未知解码器提供默认实现其popularity为 0.0而Crack::get_popularity的默认返回值为 0.5与文档中未知解码器 → 0.5的口径一致。内存管理质量驱动的搜索空间剪枝A* 搜索最棘手的问题之一是状态空间爆炸——同一段文本可能被几十个解码器反复转换产生海量中间字符串。Ciphey 通过已见集合 质量保留 动态阈值三层机制控制内存超过阈值 T 时触发剪枝为所有已见字符串计算质量分数按质量降序排序仅保留质量最高的前 50% 字符串根据搜索进度动态调整 TT_new T_initial - (5000 × depth / MAX_DEPTH)早期字符串过滤长度 ≤ 2 的字符串立即拒绝calculate_string_worth判定quality 0.2即弃非打印字符占比影响优先级但不会直接导致拒绝占比 30% 时在check_if_string_cant_be_decoded中才会被判定为不可解码。文档给出的实现骨架if seen_count prune_threshold { // Quality-based pruning let mut quality_scores: Vec(String, f32) seen_strings .iter() .map(|s| (s.clone(), calculate_string_quality(s))) .collect(); // Keep top 50% highest quality strings let keep_count seen_strings.len() / 2; seen_strings quality_scores .into_iter() .take(keep_count) .map(|(s, _)| s) .collect(); // Dynamic threshold adjustment prune_threshold INITIAL_PRUNE_THRESHOLD - (progress_factor * 5000.0) as usize; }结合 astar.rs 的实际实现剪枝系统还有三个工程细节值得注意常量配置PRUNE_THRESHOLD 100000、INITIAL_PRUNE_THRESHOLD PRUNE_THRESHOLD、MAX_DEPTH 100。即阈值 T 初始为 10 万条字符串随深度从 0 推进到 100T 最多收缩 5000。去重采用哈希calculate_hash用DefaultHasher计算字符串哈希后存入DashSet线程安全的并发集合避免直接存储大字符串节点扩展时通过哈希已存在判断来预防环从而避免重复访问同一状态。环预防的另一道防线expand_node在扩展时检查路径中最后一个解码器的checker_description是否包含reciprocal标记见 astar.rs若是则从候选集中剔除同名解码器。仓库中 atbash、caesar、reverse、rot47 等解码器的 tags 均带有reciprocal因为编码/解码互为逆运算连续应用会立刻回到原文本。五大性能优化1. 初始全量运行所有解码器立即尝试解码若找到简单解则提前退出失败尝试的统计结果回馈给启发式计算成功率、流行度数据随之更新。这保证了一层编码场景的最优延迟。2. 解码器标签Decoder Tagging带decoder标签的解码器在每个节点立即执行未打标签的进入优先队列等待后续探索。通过 filtration_system/mod.rs 的DecoderFilter按标签筛选避免在不可能的路径上浪费计算。3. 互逆预防Reciprocal Prevention跟踪互逆解码器对如编码/解码对阻止连续应用互逆操作从而消除明显环路、缩减搜索空间。实现即上文提到的checker_description.contains(reciprocal)检查。4. 统计学习Statistical Learning每个解码器的成功率在搜索过程中被持续跟踪update_decoder_stats并通过p_r罚分影响后续路径优先级——表现差的解码器会逐渐被启发式降权搜索能够自适应地遗忘无效解码器。5. 动态剪枝Dynamic Pruning剪枝阈值随搜索深度自适应下调越深的层级剪枝越激进在内存占用与搜索完备性之间取得平衡。源码级实现并行 A* 的关键结构仓库中的 A* 实现相比文档描述还增加了一层并行化详见 astar.rs 与 parallel_astar_search.md线程安全优先队列ThreadSafePriorityQueue用MutexBinaryHeapAStarNode包装开放集提供push/pop/extract_batch等操作批量并行扩展主循环每次从队列提取PARALLEL_BATCH_SIZE 10个最高优先级节点用rayon::par_iter().flat_map(expand_node)并行扩展新产生的节点统一收集后再推回队列特殊结果节点某个解码器被 Athena 判为成功时expand_node会构造一个total_cost -1000.0、next_decoder_name __RESULT__的特殊节点确保它在下一轮被最先处理主循环识别该标记后去重、输出路径并依据配置决定停止或继续top_results 模式当配置开启top_results时搜索在找到第一个明文后不停止而是将结果写入 wait_athena_storage持续收集更多明文直到计时器到期相关配置项timeout、top_results定义于 config/mod.rs。astar.rs 中的单元测试覆盖了三个关键场景空输入返回None、循环输入AAAA不挂死、Base64 输入在独立线程中能返回带非空解码路径的结果。实现说明乘法罚分的复合效应文档在最后强调了乘法模型的行为特性多个维度评分差的解码器会受到复合式重罚——每个罚分因子都放大其他因子差评会互相叠加而非简单相加某些维度的高分可以部分抵消其他维度的低分非打印字符的指数罚分是对二进制/损坏路径的强威慑往往只需少量控制字符即可让整条路径的启发式分数失控。这套调优体系使搜索天然偏向常见、可靠、高成功率的解码器高流行度 高成功率干净的文本输出低非打印字符占比长度合理的字符串接近 100 字符已知的解码器序列基于常见模式白名单。总结Ciphey 的 A* 搜索是启发式评分 × 两级调度 × 动态剪枝 × 并行扩展四者结合的工程实践docs/astar.md 提供了完整的数学设计乘法罚分模型、流行度表、剪枝公式而 astar.rs、helper_functions.rs 与 filtration_system/mod.rs 则呈现了与之配套的 Rust 实现包括解码器专属节点、Rayon 并行批量扩展、DashSet 去重、互逆解码器环预防与动态阈值剪枝。理解这套机制有助于你在遇到多层编码类题目或需要设计自己的自动解码流水线时快速定位 Ciphey 的可复用思路。赞分享CLI网络安全【免费下载链接】Ciphey⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡项目地址https://gitcode.com/gh_mirrors/ci/Ciphey点击查看免费下载相关推荐猫抓 cat-catch把网页视频和 M3U8 流快速存到本地的免费资源嗅探方案猫抓 cat catch把网页视频和 M3U8 流快速存到本地的免费资源嗅探方案 猫抓cat catch是一款免费开源的浏览器资源嗅探扩展说白了就干一件CLI网络安全超高效节点剪枝PySCIPOpt中启发式算法的深度优化与实现超高效节点剪枝PySCIPOpt中启发式算法的深度优化与实现 你是否在解决整数规划问题时遇到过求解时间过长的困境当问题规模超过1000个变量时传统分支定界AutoGen.NET 群聊机制详解RoundRobinGroupChat 与 GroupChat 动态群聊的原理、Graph 工作流与实战示例AutoGen.NET 群聊机制详解RoundRobinGroupChat 与 GroupChat 动态群聊的原理、Graph 工作流与实战示例 AutoGeCLI网络安全上一篇Cosmos-Reason2-32B vs Qwen3-VL-32B性能对比与基准测试详解下一篇探索kfyty725/loveqq-framework的依赖注入依赖注入性能优化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考