刚接触CTF的时候很多人一打开Crypto密码学方向的题目就是一脸懵给一串不明觉厉的字符、一份看不懂的脚本、或者一个打不开的加密文件完全不知道从哪里下手。我自己也是从零基础一路踩坑过来的所以特别理解这种“看了WPWriteUp解题报告觉得不难真拿到题还是不会”的状态。这一篇系列开篇文章我打算先把“CTF里的密码学到底在解什么”这件事彻底讲透帮零基础的朋友建立起一个清晰的知识框架再附上真正能落地的入门路线和第一波实操。1. 先搞清楚CTF里的Crypto到底在解什么1.1 一道Crypto题目的真实结构CTF里的Crypto题目和教科书上的密码学完全不是一回事。教科书告诉你怎么设计一个安全的加密系统CTF则反着来给你一个“被加密/处理过”的结果让你想办法还原出原始信息这个原始信息里往往藏着flag一般是flag{...}这种格式。一道典型的入门级Crypto题通常由三部分构成一段密文可能是一串Base64字符、十六进制字符串、一串看起来像乱码的bytes甚至是一张图片里藏着的字符。一段脚本可选出题人用来加密flag的Python代码很多时候会直接附在题目附件里。一个目标从密文反推出flag。有的题目密文就是flag直接编码后的结果有的则要求你在理解了加密流程之后写脚本反推。举个例子一道最简单的题可能是这样的密文ZmxhZ3t5MHVfZ290X3RoMVN9如果你能一眼看出这是Base64编码解码后得到flag{y0u_got_th1S}这道题就做完了。但事实上真实比赛里的题目远没有这么直白考点会层层嵌套这也是为什么我把这个系列命名为“解什么”——解的不是密文本身而是“出题人到底用了什么手法”这个谜题。1.2 识别能力永远比计算能力重要我见过太多新手一上来就死磕数学原理觉得不懂数论就做不了RSA。这个认知需要纠正CTF比赛的Crypto本质上是“模式识别逆向思维”的游戏而不是数学考试。你真正需要的核心能力是看到一段密文能快速判断出它可能属于哪一类加密方式然后调用对应的工具或脚本去处理。换句话说你需要“认得出”Base64的特征大小写字母数字/结尾的、认得出凯撒密码的特征字母错位但保留字母表、认得出RSA的特征给了n、e、c三个大整数。这种识别能力怎么练没有捷径就是多看多解。做题做多了你看到一串字符大脑会自动弹出“这像Base64”“这像是十六进制”“这像是栅栏密码”的直觉。我自己的经验是入门阶段先别追求自己推导加密算法而是先建立“识别→解码→验证”的肌肉记忆等接触得多了再回头补数学原理效率会高很多。1.3 主流的题目分类速览在动手之前先给零基础的朋友一张“地图”知道Crypto板块大致有哪些山头的题分类典型考点难度解题侧重点编码类Base64、Hex、URL编码、ASCII、ROT13入门识别工具调用古典密码凯撒、维吉尼亚、仿射、栅栏、培根入门-简单字母频率分析爆破现代密码哈希MD5/SHA、AES/DES、分组模式中等理解模式脚本编写公钥密码RSA、ECC、ElGamal中等-困难数学原理攻击脚本特殊类型随机数预测、侧信道、隐藏信息困难按场景定制新人入门的路径非常清晰先掌握编码类和古典密码这是最容易拿分的再过渡到哈希和对称加密最后才啃RSA这块硬骨头。千万别一上来就挑战高难度RSA题那只会打击信心。2. 入坑第一周工具、环境与一条通用解题思路2.1 工具准备三个够用就行的武器工欲善其事必先利其器。零基础入门Crypto不需要装一堆花里胡哨的软件下面这三个工具就足够你撑过前两个月。第一个是CyberChef。这是一个网页版的数据处理工具被大家叫作“网络瑞士军刀”。它最大的优点是把几十种常见的编码、加密、哈希操作做成了拖拽式模块你只需要把密文拖进输入框然后拖一个“From Base64”模块过去结果就出来了。不需要安装、不需要配置打开浏览器就能用对新手极其友好。第二个是Python环境。如果说CyberChef是快手菜那Python就是正式的厨具。很多题目的加密脚本是Python写的你需要读懂它并且写脚本反推。我建议用Anaconda或者直接装官方Python 3再配合一个IDE比如VS Code或PyCharm社区版就足够了。基础的pycryptodome库提供AES、DES等加密算法的Python实现需要提前装好命令一行搞定pip install pycryptodome第三个是现成的解密网站。dCode、cmd5这类网站虽然看起来不太起眼但关键时刻真的能救急。尤其是dCode提供了大量古典密码的在线破解工具支持频率分析、自动爆破。我遇到陌生加密方式时第一反应常常就是去dCode碰碰运气很多时候真的能直接解出来。2.2 一条通用的五步解题流程拿到一道Crypto题之后不要慌按下面这条流程走大部分情况下能理出头绪。读题仔细看题目描述和附件文件名出题人经常会把提示藏在描述里比如“Caesar was here”“public key”这种单词直接指向考点。认格式观察密文的字符组成。如果只有大小写字母和数字可能是Base64或Hex如果只是字母且保持了大小写可能是凯撒或维吉尼亚如果是大整数多半是RSA。试编码先用CyberChef批量试一遍常见的编码解码Base64、Hex、URL、Unicode很多题到这一步就结束了。看脚本有Python附件就打开读理清加密流程。重点关注密钥怎么来的、填充方式是什么、有没有明显的“漏洞”比如随机数固定、公钥指数太小。搜索写脚本识别出加密算法后如果不会解先搜有没有现成脚本或在线工具搜不到再自己写。写不出来就检索这类算法的常见攻击方式比如RSA的小公钥指数攻击、共模攻击找到对应的Python脚本模板改一改。这套流程听起来简单但真到了比赛里能救很多人。我最开始做题的时候经常在第五步卡住后来发现其实是第三步没做彻底——有些题是Base64编码套了一层十六进制再套一层URL编码多嵌套几次就认不出来了。2.3 Python脚本需要掌握到什么程度零基础的朋友可能担心我不会写Python怎么办我的建议是不需要系统学完整个Python语言掌握下面这些就足够入门Crypto了。字符串和字节串的基本操作encode()、decode()、bytes.fromhex()循环和条件语句for循环里的爆破for key in range(26)这类调用第三方库from Crypto.Cipher import AES这类这些语法练个两三天就能上手。Crypto题目的常规解题脚本说白了就是把加密过程逆向写一遍或者暴力枚举密钥空间。不需要你写出多么优雅的代码能跑出flag就是胜利。再分享一个实战中很有用的调试技巧写解密脚本时先打印中间步骤的输出确认每一步的结果是否符合预期。比如解密AES之前先确认密钥和初始向量的类型是不是字节串这个细节我踩过无数次坑。3. 从零手解三道典型入门题编码、古典密码、RSA初体验3.1 第一题双层编码的识别与拆解先看一道我在入门阶段遇到过的经典题密文是NjM3YzYzNjM2YzYzNjM2YzYzNjM2YzYzNjM2YzYzNjM2YzYzDQo新手拿到这串东西第一眼会觉得像Base64以结尾字符由大小写字母和数字组成。如果你直接丢到CyberChef里用From Base64解一次得到的结果是637c63636c63636c63636c63636c63636c63636c63636c这一串全是0-9和a-f的字符标准的十六进制格式。继续用From Hex解一次得到clclclclclclclclclclclcl再仔细一看cl重复出现其实这是flag被某种方式替换后的结果。把cl看成一组对照flag四个字母的位置你会发现f-c、l-l、a-c……实际上这是一个简单的ROT旋转替换偏移量固定。这个例子想说明一个关键点Crypto题很少有单层加密多数是多层嵌套。每一层解出来的结果都可能变成下一层的输入所以你必须学会“剥洋葱”。我把这个思路整理成一条很实用的经验只要拿到密文先把URL解码、Base64解码、Hex解码、ROT13这些最基础的“净化操作”全部过一遍。如果解出来还是可读格式就继续解直到结果变成一串意义不明但格式完整的文本或出现flag字样为止。3.2 第二题凯撒密码的频率分析爆破古典密码里最有代表性的就是凯撒密码Caesar Cipher。它的加密原理很简单把每个字母按照字母表顺序往后移动固定的位数。比如偏移3时a变成db变成e以此类推。破解凯撒密码的核心思路是枚举密钥。因为字母表只有26个字母偏移量也就只有26种可能直接暴力试一遍就行。这里我给出一个非常简短的Python脚本枚举所有偏移并输出可读文本def caesar_brute_force(ciphertext): for shift in range(26): plain for ch in ciphertext: if ch.isalpha(): base ord(A) if ch.isupper() else ord(a) plain chr((ord(ch) - base shift) % 26 base) else: plain ch print(fshift {shift:2d}: {plain}) caesar_brute_force(Dwwdfn dw gdzq dw qrq0)如果密文足够长打印出的26条结果里总有一条读起来通顺那条对应的偏移量就是真正的密钥。这个方法一旦熟练处理凯撒题就是半分钟内的事。稍微进阶一点的维吉尼亚密码Vigenère Cipher也没那么可怕它相当于用一组循环的凯撒偏移量来加密。破解时先通过计算重复子串的距离推断密钥长度再对每一列分别做频率分析。这个过程手算太麻烦直接用dCode这类在线工具粘贴密文进去基本上几秒钟就能出结果。我的建议是古典密码这类题优先靠工具把时间省下来去研究更需要动脑的题目。3.3 第三题RSA的第一个攻击点——小公钥指数RSA是Crypto板块的重头戏也是很多新手觉得劝退的地方。但入门RSA其实没有想象中那么难先从一个最经典也最简单的攻击场景说起小公钥指数攻击。RSA加密中c m^e mod n其中e是公钥指数。很多出题人不小心把e设成3本来是为了加密速度更快如果m^3 n那么加密结果c其实就是m^3的完整值根本没有经过取模。这种情况下直接对c开三次方根就能还原m。题目一般会给你三个值n、e、c解题脚本长这样from Crypto.Util.number import long_to_bytes from sympy import integer_nthroot n 0x... e 3 c 0x... m, exact integer_nthroot(c, e) if exact: print(long_to_bytes(m))这里用到了sympy库的integer_nthroot函数它能对大整数进行精确的整数开方运算。exact变量用来判断开方结果是否是整数如果是整数说明m^3确实没有超过n也就成功解出了明文。我当初第一次跑通这个脚本的时候真的有一种“原来数学还能这么玩”的感觉。这也是Crypto的迷人之处它考的不是死记硬背而是你能不能发现算法在特定参数下的“破绽”。随着你后面学到更多攻击方法共模攻击、低解密指数攻击、维纳攻击等你会逐渐意识到RSA题目本质上是“出题人故意留破绽你来当侦探”的游戏。3.4 实战手把手解一道多层嵌套的入门综合题把前面这些知识点串起来咱们来解一道我临时设计的综合性入门题。题目附件是一个脚本from Crypto.Util.number import bytes_to_long, getPrime import base64 flag flag{example_flag} p getPrime(512) q getPrime(512) n p * q e 3 m bytes_to_long(flag.encode()) c pow(m, e, n) data base64.b64encode(str(c).encode()).decode() with open(cipher.txt, w) as f: f.write(data)而在cipher.txt里你看到的是一串Base64MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ现在按照五步法来第一步读题。脚本里e3这就是最大的提示基本上可以锁定小公钥指数攻击。第二步认格式。cipher.txt里明显是Base64先解码import base64 c int(base64.b64decode(open(cipher.txt, rb).read()).decode()) print(c)第三步直接用小公钥指数的思路对c开三次方根from sympy import integer_nthroot from Crypto.Util.number import long_to_bytes m, exact integer_nthroot(c, 3) print(exact) if exact: print(long_to_bytes(m).decode())第四步如果exact是True直接输出明文flag到手。如果exact是False说明密文取过模需要用更高级的攻击手段不过这道题不会那么复杂。这道题虽然是我自己拼接的但它的解题思路和真实比赛里的入门题几乎一模一样识别脚本漏洞小e、处理编码Base64、编写逆向脚本。希望大家通过这道题能把前两节的内容真正串联起来。4. 现代密码学考点速览哈希、对称加密与RSA扩展4.1 哈希题识别与“破解”真相哈希Hash在CTF题目里也经常出现但很多人对它的理解有偏差哈希不是加密它是一种不可逆的摘要算法MD5、SHA-1、SHA-256等。你没法把e99a18c428cb38d5f260853678922e03直接“解密”成abc123因为哈希函数本身就是单向的。那CTF里怎么考哈希入门阶段最常见的是两种哈希查找给一个哈希值让你在彩虹表或在线库里查到原始字符串。比方说管理员密码的MD5值泄露了你去cmd5这类网站搜一下往往能直接搜出明文。哈希长度扩展攻击这个稍后进阶一点会遇到它利用了MD5/SHA-1这类Merkle-Damgard结构哈希的弱点可以在不知道原始消息的情况下把新内容附加到消息后面并计算出合法的新哈希值。入门阶段你只需要掌握第一种就够应付大部分简单题了。说实话哈希题是最没技术含量但也最容易拿分的一类看到明显是32位或40位的十六进制字符串先丢到在线哈希查询网站去搜一圈十有八九能搜出来。4.2 对称加密AES题目的三个核心参数AES这类对称加密在CTF里属于中等难度出题人通常会配合各种“不安全的模式”来考你。拿到一道AES题你需要从脚本或描述里提取三个关键参数密钥key最简单的题目可能直接硬编码在脚本里那你就能直接解密复杂的题目则可能要求你通过其他手段比如已知明文攻击推断出密钥。初始向量IVCBC等模式下需要IV才能正确解密如果出题人把IV固定为全零或者写在题目附件里这就是一个可以利用的点。分组模式和填充方式ECB模式存在一个著名的特点——相同的明文块产生相同的密文块这可以用来做字节级的模式分析。CBC模式如果IV固定或可控则可能引发字节翻转攻击。我建议入门阶段先自己写一遍AES的加密解密流程把pycryptodome库的基本用法混个脸熟后面再慢慢接触各种攻击手法。下面是一段标准CBC模式的解密模板可以直接保存备用from Crypto.Cipher import AES from Crypto.Util.Padding import unpad key bytes.fromhex(...) iv bytes.fromhex(...) ciphertext bytes.fromhex(...) cipher AES.new(key, AES.MODE_CBC, iv) plaintext unpad(cipher.decrypt(ciphertext), AES.block_size) print(plaintext.decode())4.3 RSA的其他入门攻击面RSA的考点简直是Crypto界的半壁江山这里再补充两个入门后不久就会遇到的攻击面。第一个是共模攻击。如果出题人用同一个n但两个不同的指数e1、e2加密了同一条明文你就获得了两个密文c1、c2。数学上可以证明只要gcd(e1, e2) 1就一定存在整数a、b使得a*e1 b*e2 1于是可以用扩展欧几里得算法求出m c1^a * c2^b mod n。这个攻击经常出现在两个人共享同一个模数、但各自使用不同公钥指数的场景里。第二个是低解密指数攻击维纳攻击。当私钥指数d比较小通常小于n^(1/4)时可以通过连分数逼近的方法还原出d。这种攻击有现成的脚本遇到d取值小的情况直接套模板不过入门阶段先了解即可等RSA基础扎实了再去深入实现。我想强调的是学习RSA攻击方法最好的方式不是背公式而是把每种攻击对应到一个“出题场景”里。比如看到e3脑子里立刻浮现“小公钥指数攻击”和“开三次方根”的画面看到同一个n出现两对e和c立刻想到“共模攻击”。这种“场景-手法”的对应关系就是Crypto解题能力提升的核心。5. 零基础高频翻车现场与避坑记录5.1 常见问题速查表以下是我带过不少新人、自己也踩过无数坑之后整理出来的高频问题速查表。建议直接截图收藏。问题现象根本原因解决办法Base64解出来是乱码可能不是纯Base64而是Base64后再Hex/压缩继续对结果尝试各种解码Python解密时报错bytes-like object is required密钥或密文是字符串不是字节串调用.encode()或bytes.fromhex()转换类型解出来的字符串没有flag{}格式可能结果还需要经过一层ROT或字符替换对所有可能偏移量做循环尝试RSA脚本跑得很慢可能用了效率低的算法或数值过大优先用pow内置函数避免自写大数运算在线解密网站解不出来密文可能被自定义字符集编码过观察字符集是否包含、/以外字符考虑自定义Base明文有可读单词但整体不通顺可能是维吉尼亚或替换密码不止一层凯撒用dCode的自动检测功能多跑几个算法5.2 新人最常犯的四个思维误区误区一一定要把整个加密算法完全理解才动手。恰恰相反先动手解解完再回头看原理效率更高。很多新人卡在第一步就是觉得“我还不懂RSA数学原理”于是一个星期过去了还在看数论一道题都没做。我的建议是直接拿题目练手不会什么就查什么以题带学比系统看书快得多。误区二只解自己擅长的题型。有的人编码题解得好就一直做编码题碰到古典密码就跳过。这样练习的覆盖面太窄比赛时遇到其他题型就只能干瞪眼。建议大家按照题型的难度梯度各类型都刷上二三十道建立全面的识别能力。误区三忽视题目描述和文件名。Crypto的出题人其实很“善良”经常在描述或文件命名里给提示。比如caesar.txt明确告诉你这是凯撒rsa_public_key.pem告诉你这是RSA。只看密文不看题面等于把自己眼睛蒙上一半做题。误区四不习惯看别人的WriteUp。有的朋友觉得看WP等于作弊其实完全不是这样。Crypto题目的解题思路常常是一层窗户纸你不去捅破就想破头也想不出来。正确做法是先自己努力一阵子如果实在没有头绪就去看WP看懂后一定要亲自把题目重做一遍把思路内化成自己的这样才真正有收获。5.3 入门期的训练节奏建议最后给零基础的朋友一个可执行的训练计划。第一个月不要贪多按以下节奏走第一周掌握CyberChef的常用模块刷30道左右的编码类题目各个CTF平台的入门题都行把Base64、Hex、URL、ROT13这些解码做到闭着眼睛都能操作。第二周学习古典密码的识别和破解重点是凯撒、维吉尼亚、仿射。建议自己在本地跑一遍dCode的解密流程理解频率分析的原理顺便写一个凯撒爆破脚本练手。第三周过一遍Python操作pycryptodome库的基本接口写AES-CBC的加密和解密各一遍再尝试解两三道对称加密入门题。第四周正式进入RSA先掌握n、e、c三件套的理解、小公钥指数攻击和共模攻击把脚本跑通每道题都尝试不看WP独立复现。按照这个节奏一个月后你已经具备独立解决简单Crypto题的能力了。说到训练平台有一个很重要的小建议刚开始别贪图高难度比赛先在本地搭建一个训练环境或者使用面向新手的练习平台把上面的分类题库刷一遍。很多公开的入门题库都自带WriteUp做完一道看一道学到的经验会非常扎实。6. 一个小技巧善用搜索引擎和“复现消耗”法6.1 遇到不会的题怎么搜最有效这里额外分享一个我后来才琢磨明白的技巧遇到不熟悉的概念或报错信息把完整的关键词直接丢进搜索引擎/社区而不是问“这道题怎么做”。比如你遇到error when starting dev server: typeerror: crypto$2.getrandomvalues is not a这种报错这是JavaScript环境里crypto对象的问题不是CTF考点搜的时候直接搜报错原文比搜“Crypto题目”有用得多。同样的Python里遇到AttributeError: module Crypto has no attribute Cipher多半是包名冲突或库没装对搜报错原文马上能找到答案。搜索本身也是一项CTF技能。会用正确的关键词能让你在解题卡住时节省大量时间。我的经验是搜索时优先用英文关键词因为CTF的国际社区资料远比中文社区丰富RSA common modulus attack搜出来的内容质量通常比“RSA共模攻击”更高。6.2 “复现消耗”学习法最后一个压箱底的学习方法我叫它“复现消耗法”。具体操作每看完一道题的WriteUp关掉网页凭记忆自己独立把解题脚本重写一遍直到能跑出正确的flag。不要小看这个动作。很多新手看WP的时候觉得“哦原来这么简单”关上网页之后三分钟就忘了。而当你亲手把每一步代码敲出来、把每个参数打印出来检查你才是真正“消耗”掉了这道题。Crypto的解题能力就是在这样一个又一个“消耗”中积累起来的。我到现在依然保持这个习惯即使在比赛里做出来的题赛后也会重新看一遍最佳WriteUp找出自己思路里绕远路的部分然后思考下次遇到同类题能不能做得更快。这种持续的自我迭代才是Crypto水平稳步提升的关键。