Crypto
random_RSA
题目:
1 | from gmpy2 import next_prime, invert as inverse_mod |
*思路*:
观察题目可得,加密flag的时候,q,p的参数都是未知的,而在此之前有一个choice1可以拿到之前生成过的参数,所以就可以确定要用随机数预测的办法去获取,q,p的参数。
简单计算一下可以获取到的位数:(在预测最终参数前,有21次获取随机数的的机会)
((1024-32)2+(1024-32-32))//32 == 92\ 927 = 644 >624
只要在此之前通过公钥(N,e)获取q,p,d,就可以获取到大于624个状态参数,那么就可以稳定预测下一次生成的随机数,但是在题目中q,p的位置是未知的,要获取到正确的顺序需要爆破一下这个位置。
观察生成公钥的办法,可以发现e的生成比较诡异,导致e的位数大很多,简单地推一下式子:
ed=1 \mod(p{2}-1)*(q2-1)\ 展开可得:ed = 1+k*(p{2}-1)*(q2-1)\ ed = 1+k(N{2}-q{2}-p^{2}+1)
估算一下位数:e大概4096位,N为2048位,因子1024位,k的范围通过测试可知小于1024位。
那么可以尝试一下SVP问题求解的办法,在模e下,找到小根,即:
1 | #part1: |
Crib:
题目:
1 | from hashlib import sha256 |
myEngma:
1 | from pyenigma import rotor |
剩余的pyenigma可以在github上面找到,故不放出。
直接上github梭哈脚本,里面有猜测位置的函数,直接多次调用函数猜测密文就可以获得准确的pos
1 | from pwn import* |
bombe-Rejewski-revenge:
题目
1 | from hashlib import sha256 |
myenigma:
1 | from pyenigma import rotor |
思路:
目标是获取daily key。题目给出了用daily key加密两次key后的结果,同时提示了一个人名。
打开bilibili:一看就懂的历史小故事
观后可知,如果把每一位加密视作一次函数,通过一定群论的证明,可以知道,在同一日密钥加密对话密钥两次的情况下,我们可以根据字母之间映射的关系构成一个映射环。同一日密钥加密的情况下,一轮字母表所构成的环的个数、环中字母的数量相同,这个特征很像数字指纹,利用这个特征,在本地生成一遍数据库,将数字指纹对应的日密钥保存下来,拿到服务器进行比对就可以获得flag。
生成脚本:
1 | import signal |
去服务器比对数据:
1 | import signal |
Recover:
题目:
1 | 暂时找不到了:( |
思路:仔细观察P盒的特征,结合异或运算就是模2下的加法运算这个性质,整个加密都是线性的,所以可以通过以下关系式构造解出原文。(其中可以试一下发现原文头是固定的,也就是说可以使用已知明文攻击去解密原文)
E = P(P(P(M)+B_1)+B_2)+B_3\ E = P{3}M+P{2}B_1+PB_2+B_3\ T = P^{2}B_1+PB_2+B_3\ E = P^{3}M+T\
1 | from Crypto.Util.number import * |
然后就是最烧脑的一步了,解出原文发现,真正的flag藏在密钥里,要是直接爆破穷举密钥的话有上亿种可能,也跑不了,要考虑削减复杂度。经过尝试可以发现密钥的第一部分可以随便构造,既然说密钥是可读的,那就用"flag{"这个头去爆破剩下三位试试。
1 | import itertools |
从中硬搜查找爆破试试吧,肉眼解题了属于是,最后看了别人WP发现真的是神仙过海各显神通了,
最终key: flag{hardtorecoverkey}
AggServer:
题目:
1 | # !/usr/bin/env python |
AggServer:
1 | from Crypto.Util.number import * |
user:
1 | from Crypto.Util.number import * |
代码审计题,给年幼无知的我带来了巨大的伤害,暂时就没做了,以后有空再更新吧(