攻防世界 crypto爆破 hidden key
原题代码如下:
1 | from Crypto.Util.number import * |
题解
观察题目,发现byte_to_long后的key右移12位后得2669175714787937
,即0x97B99E652B261
,共13位数字,转二进制就是52位,52+12 = 64 bits = 8 bytes
,与原题key=os.urandom(8)
对应。而key的前52位我们已经知道了,只需要爆破后12位即可。
易得爆破脚本:
1 | from Crypto.Util.number import * |
这题的考点应该是计算机伪随机数的产生。鉴于题目中用到了较多产生随机数的函数,姑且对这些函数做个不完全的总结。欢迎各路大神在评论区补充。
产生随机数
众所周知,计算机不能产生真正的随机数。在实践中,大多数编程环境会提供一个伪随机数生成器,使得返回值在统计上看起来是随机的。这里不对随机算法进行深入研究,只需知道随机数是由一个名为“种子”的数推算而来。
C的随机数产生
1 | /* 一个简单的用于产生随机数的程序 */ |
我们可以看到,上面这个程序的核心代码是rand()
。它可以随机的产生 0 ~ RAND_MAX 的随机数,RAND_MAX包含在头文件stdlib.h中,默认为32767。
所以我们可以使用a = rand() % (n-m+1) + m;
来生成一个m ~ n的随机数。
然而,我们会发现,虽然函数返回值是无法预料的,但是无论运行多少次,这个函数的返回值都是固定的。其根本原因是没有初始化随机种子。种子在每次启动计算机时是随机的,但是一旦计算机启动以后它就不再变化了。也就是说,每次启动计算机以后,种子就是定值了,所以根据公式推算出来的结果(也就是生成的随机数)就是固定的。
以下代码可以帮助我们初始化随机种子:
1 | srand((unsigned)time(NULL)); // # include <stdlib.h> # include <time.h> |
原理是使用time(NULL)
函数来获取系统时间(从1970年1月1日0点到现在时间的秒数),并转化为unsigned int,最后传给srand()函数作为种子。
Python的随机数产生
os.urandom(n)
返回一个n字节的随机字符串,适用于加密等。
random库
1 | import random |
-
random.seed(a)
设置初始化随机种子,可输出相同随机数序列;a取整数或浮点数,不设置时默认以系统时间为种子。 -
random.random()
用于生成一个0.0到1.0的随机数。 -
random.uniform(a, b)
生成一个[a, b]之间的随机浮点数(a、b取整数或浮点数) -
random.randint(a, b)
生成一个[a, b]之间随机整数。 -
random.randrange(start, stop, \[step\])
生成一个[start, stop]之间以step步数的随机整数;start、stop、step取整数,step不设置时默认值为1。 -
random.choice(seq)
从序列类型seq中随机返回一个元素;seq取序列类型,如字符串、列表、元组。 -
random.shuffle(seq)
将序列类型中元素随机排序,无返回值,seq被改变(改变原序列),shuffle为洗牌之意;seq取序列类型,如字符串、列表;元组不能被洗牌。
运算符优先级
debug了一小时啊一小时,最后发现tmpkey = long_to_bytes((2669175714787937 << 12) + j)
这句左移运算符那里没加括号。
移位的本质不是乘除吗,为什么优先级比加减还要低?
(某乎上有人发了同样的问题)
贴个运算符优先级顺序表在这里以时刻提醒自己。
C:
优先级 | 运算符(们) | 解释 |
---|---|---|
1 | () [] -> . | 括号/函数调用 索引 间接成员访问 成员访问 |
2 | ++ – + - ! ~ & * sizeof 类型转换 | 自增(后缀大于前缀) 自减 正 负 非 按位非 取址 解引用 内存大小 类型转换 |
3 | * / % | 乘 除 模 |
4 | + - | 加 减 |
5 | << >> | 左移位 右移位 |
6 | < <= > >= | 小于 小于等于 大于 大于等于 |
7 | == != | 等于 不等于 |
8 | & | 按位与 |
9 | ^ | 按位异或 |
10 | | | 按位或 |
11 | && | 逻辑与 |
12 | || | 逻辑或 |
13 | ?: | 三目条件运算符 |
14 | = *= /= += -= <<= >= &= |= ^= | 各种赋值运算符 |
15 | , | 逗号运算符 |
Python:
优先级 | 运算符(们) | 解释 |
---|---|---|
1 | () [] . | 括号/函数调用 索引 属性引用 |
2 | ** | 幂 |
3 | + - ~ | 正 负 按位非 |
4 | * / // % | 乘 除 整除 模 |
5 | + - | 加 减 |
6 | << >> | 左移位 右移位 |
7 | & | 按位与 |
8 | ^ | 按位异或 |
9 | | | 按位或 |
10 | < <= > >= | 比较运算 |
11 | == != | 等于 不等于 |
12 | is not is | 实体检查 |
13 | in not in | 成员检查 |
14 | not | 逻辑非 |
15 | and | 逻辑与 |
16 | or | 逻辑或 |