概述
Embryonic Plant是来自于HTB(hackthebox.com)的一个容易级密码学挑战,完成该挑战所需要掌握的知识点在于模计算和AES加解密。
题目分析
相关的任务文件包括一个script.py源代码和output.txt文本文件。
script.py内容如下
from Crypto.Util.number import getPrime, long_to_bytes, inverse
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import sha256
from secret import FLAG
class RNG:
def __init__(self, seed):
self.e = 0x10001
self.s = seed
self.r = getPrime(768)
while True:
self.p, self.q = getPrime(768), getPrime(768)
if self.p < self.r and self.q < self.r:
break
self.n = self.p * self.q * self.r
phi = (self.p - 1) * (self.q - 1) * (self.r - 1)
self.d = inverse(self.e, phi)
def next(self):
self.s = (self.s * self.p + self.q) % self.r
return self.s
def main():
rng = RNG(getPrime(512))
rns = [rng.next() for _ in range(5)]
key = sha256(long_to_bytes(rng.d)).digest()
cipher = AES.new(key, AES.MODE_ECB)
enc_flag = cipher.encrypt(pad(FLAG, 16)).hex()
with open('output.txt', 'w') as f:
f.write(f'n = {rng.n}\n')
f.write(f's = {rns}\n')
f.write(f'enc_flag = {enc_flag}\n')
if __name__ == "__main__":
main()
从中我们可以得知该加密算法首先随机生成r, p和q三个素数,并分别计算n,以及包含5个元素的s数组。 然后使用sha256生成d`的哈希字串以作为AES的密钥对flag进行加密。
output.txt则给出了n, s数组的各个元素以及enc_flag密文。
结合如上数据,我们可以得到如下的关系式
n = p * q * r
s[0] = (seed * p + q) % r
s[1] = (s[0] * p + q) % r
s[2] = (s[1] * p + q) % r
s[3] = (s[2] * p + q) % r
s[4] = (s[3] * p + q) % r
#解题过程
使用模数计算规则,可以通过如下步骤得到r。
得到r之后,就可以此得出p和q, 然后得出d用于最后的解密。
n = 953212452632162415623854742466108898886257018761981737488515480124784784754313403541058723530771941185648440076953890845364164881753643355212476926626742101375422468157394494383915186197027584298810203766388023131196821200163753827759350781726289328080241887775877824351482527440834821313689834438591567613042759531267263403394331824891899899505726815540209695860955058659042180466101027165453544129867565132811217413181292156021136184504130428910065116301275284964237087553827437109939035287527986380535446925078275313404977210504275217640523278087762041948497195357622678060873426815474421439984697128135689500335385151376561597600186415289317989920506634067994928935237389715706143172780083
s = [107663563520221758967681052016945344894135463272720867342404293429418113761640130338846143415694339846703472327422471509923932434685628383794998869995327761272087050985560474031629673883432008583476972873462387774454021532562638911, 375715892557297364364744701696307763009546269920835800827316473134718210911604668305115761037621526838903749589794728067744014884724708180550902913867595275270476040258585551516530116122396379615935241551413224529146764536011818960, 1142431136128743680237588635513380046580339971378804783979851430431837015880156204447030433004896454182104721893126547029880672333914367506184442229874405762062665597996081499892502200704128255903361177726702376303206644325660472696, 696181402062958907421352186902458487367420124659441418095569426735447880619442484035499857372339751543528153083380619139649590779544110176169319718082842863368788080781170847125373363885050864587076550882230251633851030744318779877, 1090087409231264760633243725379604084008037546075358826209944877794280528534452761945892984736121167182908072643369909923239008686694491992033132238021506681618226619691505113704791978765000558863195023783700460638272869374754376211]
enc_flag = "d3587442177b157fa0cecb6dd880872d86e15a50e3f05ecfeea8b90f5cfca22835a59d9c4f23e87a68317d4ccabe1bf3aa2e6cdf0a9ef1ada0a2e83d8da0bff2b739cf0e2b2b779958d9b1154a6f3698"
import gmpy2
r = gmpy2.gcd(((s[1] - s[0]) * (s[3] - s[2]) - (s[2] - s[1]) * (s[2] - s[1])), ((s[2] - s[1]) * (s[4] - s[3]) - (s[3] - s[2]) * (s[3] - s[2])))
a = s[2] - s[1]
b = s[1] - s[0]
p = a * pow(b, -1, r)
p = p % r
q = s[2] - s[1] * p
q = q % r
e = 0x10001
phi = (p - 1) * (q - 1) * (r - 1)
d = pow(e, -1, phi)
from Crypto.Util.number import bytes_to_long, long_to_bytes
from hashlib import sha256
from Crypto.Cipher import AES
key = sha256(long_to_bytes(d)).digest()
cipher = AES.new(key, AES.MODE_ECB)
cipher_text = bytes.fromhex(enc_flag)
flag = cipher.decrypt(cipher_text)
print("FLAG =", flag)