题目编号:GFSJ1195
附件下载后是一个txt文件和一个sage文件(python):
1. 分析代码(.sage文件),已添加详细注释
# 从 secret 模块导入 flag 变量
from secret import flag
from Crypto.Util.number import bytes_to_long
from Crypto.Util.number import getRandomRange
# 确保 flag 符合特定格式,以 'CatCTF{' 开头并以 '}' 结尾
assert flag.startswith(b'CatCTF{')
assert flag.endswith(b'}')
# 定义使用自定义生成元 G 的 BLS-12-381 椭圆曲线
# p 是素数,定义了有限域 GF(p)
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
K = GF(p) # 定义有限域 GF(p)
a = K(0x00) # 椭圆曲线的参数 a
b = K(0x04) # 椭圆曲线的参数 b
E = EllipticCurve(K, (a, b)) # 使用参数 a 和 b 定义椭圆曲线 E
# 设置椭圆曲线的阶(曲线上的点的总数)
E.set_order(0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 * 0x396C8C005555E1568C00AAAB0000AAAB)
# 定义生成元 G 的坐标
G = E(
3745324820672390389968901155878445437664963280229755729082200523555105705468830220374025474630687037635107257976475,
2578846078515277795052385204310204126349387494123866919108681393764788346607753607675088305233984015170544920715533
)
n = G.order() # 生成元 G 的阶
# 定义曲线的嵌入度 k = 12
k = 12
# 将 flag(去掉前后标识部分)转为整数 m
m = Integer(bytes_to_long(flag[7:-1]))
# 获取 m 的位序列表示,用于生成 Diffie-Hellman 问题实例
sols = m.bits()
# 定义一个列表来存储 Diffie-Hellman 问题实例
DDH_instances = []
# 遍历位序列,生成 DDH 问题实例
for i in range(len(sols)):
a = getRandomRange(1, n) # 随机生成 a
b = getRandomRange(1, n) # 随机生成 b
c = 0 # 初始化 c
# 如果 sols[i] 为 True,将 c 设置为 a*b mod n
if sols[i] == True:
c = a * b % n
# 如果 sols[i] 为 False,将 c 设置为随机数,并确保 a*b*G ≠ c*G
elif sols[i] == False:
c = getRandomRange(1, n)
assert a * b * G != c * G # 验证生成的 (a, b, c) 满足非等式
# 将 (a*G, b*G, c*G) 的坐标对添加到 DDH 实例列表中
ins = ((a * G).xy(), (b * G).xy(), (c * G).xy())
DDH_instances.append(ins)
# 将生成的 DDH 实例写入文件 'DDH_instances.txt'
with open('DDH_instances.txt', 'w') as f:
f.write(str(DDH_instances))
2. 通过阅读源码及DDH的提示,求解椭圆曲线离散对数问题(ECDLP)
两个方案解决:
- 方案1:基于配对的方式,通过 Tate 配对计算点的相等性来验证每个实例。对 DDH 实例中的点进行 Tate 配对比较,如果配对结果相等,说明满足条件,输出为1,否则为0。
- 方案2:使用 Pohlig-Hellman 离散对数算法,通过计算每个点相对于生成元的离散对数,然后利用这些对数的乘积关系判断比特值。这种方式更依赖于离散对数计算,且适用于因数分解已知的阶数。
3. 方案1(Tate 配对)代码:
# 使用 SageMath 9.5
from Crypto.Util.number import long_to_bytes # 从 Crypto 库导入 long_to_bytes 函数,用于将长整数转换为字节形式
# 在运行前,修改文件名,并在文件开头添加 "DDH_instances = " ,以便加载 DDH 实例数据
load('../GFSJ/GFSJ1195/DDH_instances.sage') # 加载包含 DDH 实例的文件
# 定义椭圆曲线参数
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab # 大素数 p,用于有限域 GF(p)
K = GF(p) # 定义有限域 GF(p)
a = K(0x00) # 椭圆曲线的参数 a
b = K(0x04) # 椭圆曲线的参数 b
E = EllipticCurve(K, (a, b)) # 定义椭圆曲线 E,使用有限域 K 和参数 (a, b)
# 设置椭圆曲线的阶(曲线上所有点的数量)
E.set_order(0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 * 0x396C8C005555E1568C00AAAB0000AAAB)
# 定义生成元 G 的坐标
G = E(
37453248206723903899689011558784454376649632802297