引言
无
[CISCN2018]sm
加密代码如下:
from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
order=[]
while len(order)!=512:
tmp=randint(1,512)
if tmp not in order:
order.append(tmp)
ps=[]
for i in range(512):
p=getPrime(512-order[i]+10)
pre=bin(p)[2:][0:(512-order[i])]+"1"
ps.append(int(pre+"0"*(512-len(pre)),2))
return ps
def run():
choose=getPrime(512)
ps=gen512num()
print "gen over"
bchoose=bin(choose)[2:]
r=0
bchoose = "0"*(512-len(bchoose))+bchoose
for i in range(512):
if bchoose[i]=='1':
r=r^ps[i]
flag=open("flag","r").read()
key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
aes_obj = AES.new(key, AES.MODE_ECB)
ef=aes_obj.encrypt(flag).encode("base64")
open("r", "w").write(str(r))
open("ef","w").write(ef)
gg=""
for p in ps:
gg+=str(p)+"\n"
open("ps","w").write(gg)
run()
分析代码可知,加密过程是先生成一个随机数choose
和一串数ps
,然后根据choose
的比特位,若为1则与r
做异或运算,得到r
,然后将choose
经过md5
加密,作为AES加密的key
,再将AES加密得到的密文base64加密得到最终密文
由于base64是方便逆向的,而AES解密所需的key
是未知的,所以解密的关键是得到AES的key
;而要求出key
,就需要先求出choose
;要求出choose
,就要根据r
和ps
求出bchoose
由生成ps
的过程可知,ps
中的每个数都在末位填充了0,因此ps
中的数末位为1当且仅当位数为512位
于是根据这一特性,若r
末位为1,就可以判断bchoose
对应位置也为1;若不为1,则跳过且在下一循环中排除这个数
同理,若r
的倒数第二位为1,则异或的对象末两位只有11和10两种可能,而在上一循环排除了11,那么仅由可能是10的情况
以此类推,即可从后往前还原bchoose
,进而完成解密
解密代码如下:
from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Cipher import AES
import hashlib
import base64
import copy
with open('ps', 'r') as f:
ps = [int(n.strip()) for n in f.readlines()]
psb = [bin(n)[2:].zfill(512) for n in ps]
with open('r', 'r') as f:
r = int(f.readlines()[0])
bchoose = ['0'] * 512
psb_ = copy.deepcopy(psb)
for i in range(511, -1, -1):
rb = bin(r)[2:].zfill(512)
if rb[i] == '1':
for sb in psb:
if sb[i] == '1':
t = psb_.index(sb)
bchoose[t] = '1'
r ^= int(sb, 2)
psb.remove(sb)
break
else:
for sb in psb:
if sb[i] == '1':
psb.remove(sb)
break
choose = int(''.join(bchoose), 2)
key = long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(), 16))
aes_obj = AES.new(key, AES.MODE_ECB)
with open('ef', 'r') as f:
ef = f.readlines()[0]
enc = base64.b64decode(ef)
flag = aes_obj.decrypt(enc)
print(flag)
结果为:
结语
无