题目所给的文件内容为

from Crypto.Util.number import *
from secret import n,o,_,flag

def any(m):
	return bytes_to_long(m)^o^pow(2,2**_,n)

print(n,o,_,any(flag))

#(126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883,22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339,1138895128842708275167,22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832)

该代码中定义了一个any()加密函数函数,输入一个m,也就是明文。bytes_to_long()函数将m转换成长整数,然后异或变量o和pow(2,2**_,n)

很容易看出,这个题目解密的核心是异或的自反性,即A^B^B=A

所以直接利用公式:M = cipher^o^pow(2,2**_,n)

所以给出如下代码:

from Crypto.Util.number import long_to_bytes

n = 126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883
o = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339
_ = 1138895128842708275167
cipher = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832

plain_int = cipher ^ o ^ pow(2, 2**_, n)

flag = long_to_bytes(plain_int)

print(flag.decode())

但是很显然,运行结果出现内存溢出的报错,这是因为Python 的内置函数pow(a,b,c)中,会优先计算指数的表达式,也就是优先计算2**_,在题目中这个数字数量级庞大,造成了内存的溢出。但是pow(a,b,c)函数在每次计算的时候会不断的取模,会将结果的大小限制在c以内。因此,我们需要将 2**_ 也交给 pow 函数去处理,即写成嵌套形式:pow(2, pow(2, _, n), n)

然后依然报错

用几种不同的方式解码,不直接用decode

from Crypto.Util.number import long_to_bytes

n = 126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883
o = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339
_ = 1138895128842708275167
cipher = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832

mod_pow_result = pow(2, pow(2, _, n), n)

plain_int = cipher ^ o ^ mod_pow_result

flag_bytes = long_to_bytes(plain_int)

print("解密成功,原始字节为:")
print(flag_bytes)
print("十六进制:", flag_bytes.hex())

# 尝试安全解码
try:
    print("UTF-8 解码:", flag_bytes.decode('utf-8'))
except UnicodeDecodeError:
    print("UTF-8 解码失败,尝试 GBK 或 Latin-1...")
    print("GBK 解码:", flag_bytes.decode('gbk', errors='replace'))
    print("Latin-1 解码:", flag_bytes.decode('latin-1'))

运行出现乱码,说明我们解密的逻辑与出题人的逻辑存在一些偏差。当计算pow(base,exp,n)的模运算的时候,如果指数exp极大,根据欧拉定理,指数部分实际上是对ϕ(n) (欧拉函数)取模,而不是对 n 取模。

这时需要因式分解n,然后重新计算plain_int,完整代码如下:

from Crypto.Util.number import long_to_bytes, inverse
import sympy

n = 126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883
o = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339
_ = 1138895128842708275167
cipher = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832

# 1. 分解 n
factors = sympy.factorint(n)
print("n 的因子:", factors)

# 2. 计算 phi(n)
# phi(n) = n * ∏(1 - 1/p) for all prime factors p
phi_n = n
for p in factors.keys():
    phi_n = phi_n * (p - 1) // p

print("phi(n) =", phi_n)

# 3. 使用 phi(n) 重新计算模幂
# 加密时: pow(2, 2**_, n) 实际上等价于 pow(2, (2**_) % phi_n, n)
mod_pow_result = pow(2, pow(2, _, phi_n), n)

# 4. 异或解密
plain_int = cipher ^ o ^ mod_pow_result
flag_bytes = long_to_bytes(plain_int)

print("flag 为:")
print(flag_bytes)

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐