题目:
assert(len(open('flag.txt', 'rb').read()) <= 50)
assert(str(int.from_bytes(open('flag.txt', 'rb').read(), byteorder='big') << 10000).endswith('1002773875431658367671665822006771085816631054109509173556585546508965236428620487083647585179992085437922318783218149808537210712780660412301729655917441546549321914516504576'))
没见过int.from_bytes和endswith函数,先学一学:
与int.from_bytes对应的还有int.to_bytes。
1、int.from_bytes
函数格式:int.from_bytes(bytes, byteorder, *, signed=False),bytes为输入的变量,byteorder有'big'和'little',signed有'True'和'False'。
作用:把bytes类型的变量,转化为十进制整数
举例1:int_s = int.from_bytes(s, byteorder='little', signed=True),且s = '\xf1\xff'。
byteorder='little',表示高位在前,低位在后,s = '\xf1\xff','\x'表示16进制,而f1是低位,ff是高位,故把ff放前面,f1放后面。先将f1和ff分别写成二进制f1 = 1111 0001,ff = 1111 1111。如果byteorder='big',则是正常顺序,低位在前,高位在后。
再看signed=True。表示要区分二进制数的正负。ff第一位为1,则是负数,故要进行取反加一操作,符号位不变。得到10000000 00001111,对应十进制为-15.如果signed=False,则无符号位。
举例2:int_s = int.from_bytes(s, byteorder='big', signed=False),且s = '\xf1\xff'。
得到二进制(1111 0001 1111 1111),故转十进制int_s = 61951
2、int.to_bytes
上面操作的逆过程,将十进制整数转为bytes类型
endswith
作用判断字符串是否以指定字符或子字符串结尾,常用于判断文件类型。
再来看:
assert(str(int.from_bytes(open('flag.txt', 'rb').read(), byteorder='big') << 10000).endswith('1002773875431658367671665822006771085816631054109509173556585546508965236428620487083647585179992085437922318783218149808537210712780660412301729655917441546549321914516504576'))
将二进制的明文进行左移10000操作,即乘上2*10000,并给了转成十进制后的明文的后175位。
故可以得到下面的关系式:
c = 2^10000 * m (mod 10^175),推导一下:
2^10000 * m/c = 1 (mod 10^175),故m/c就等于2^10000关于1模10^175的逆元,通过计算发现,该逆元不存在,因为2^10000和10^175间有公因数2^175,把它约去即可
代码如下:
from gmpy2 import *
from Crypto.Util.number import *
c = 1002773875431658367671665822006771085816631054109509173556585546508965236428620487083647585179992085437922318783218149808537210712780660412301729655917441546549321914516504576
x = invert(pow(2,10000),pow(5,175))
m = c*x%(pow(5,175))
print(long_to_bytes(m))