Twisted Hessian曲线(求a)

news/2025/3/12 0:06:27/文章来源:https://www.cnblogs.com/SevensNight/p/18766343

题目:

from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from random import randint
import hashlib
from secrets import flagdef add_THCurve(P, Q):if P == (0, 0):return Qif Q == (0, 0):return Px1, y1 = Px2, y2 = Qx3 = (x1 - y1 ** 2 * x2 * y2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % py3 = (y1 * y2 ** 2 - a * x1 ** 2 * x2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % preturn x3, y3def mul_THCurve(n, P):R = (0, 0)while n > 0:if n % 2 == 1:R = add_THCurve(R, P)P = add_THCurve(P, P)n = n // 2return Rp = getPrime(96)
a = randint(1, p)
G = (randint(1,p), randint(1,p))
d = (a*G[0]^3+G[1]^3+1)%p*inverse(G[0]*G[1],p)%p
x = randint(1, p)
Q = mul_THCurve(x, G)
print(f"p = {p}")
print(f"G = {G}")
print(f"Q = {Q}")key = hashlib.sha256(str(x).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = pad(flag,16)
ciphertext = cipher.encrypt(flag)
print(f"ciphertext={ciphertext}")"""
p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
ciphertext=b"k\xe8\xbe\x94\x9e\xfc\xe2\x9e\x97\xe5\xf3\x04'\x8f\xb2\x01T\x06\x88\x04\xeb3Jl\xdd Pk$\x00:\xf5"
"""

解题思路:

分析Twisted Hessian曲线结构求参数a

  • 题目给出了TH曲线的点加法和标量乘法定义以及关键参数<font style="color:rgb(6, 6, 7);">p,G,Q</font>点,目的是求出<font style="color:rgb(6, 6, 7);">x</font>解这个AES
  • 但是我们不知道<font style="color:rgb(6, 6, 7);">a</font>就要想办法求出<font style="color:rgb(6, 6, 7);">a</font>,这里我们可以用Gröbner basis或多元多项式方程组来尝试求a
  • 分析一下Twisted Hessian曲线结构以此构造多项式

  • 已知点<font style="color:rgb(6, 6, 7);">G=(Gx,Gy)</font><font style="color:rgb(6, 6, 7);">Q=(Qx,Qy)</font>,且<font style="color:rgb(6, 6, 7);">Q=x⋅G</font>,可以通过以下步骤求解<font style="color:rgb(6, 6, 7);">a</font>

这是一个关于<font style="color:rgb(6, 6, 7);">a</font>线性方程,可以通过代数方法求解

代码实现:

p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
# 计算 a
Gx, Gy = G
Qx, Qy = Q
GxGy = (Gx * Gy) % p
QxQy = (Qx * Qy) % p
K = (QxQy * pow(GxGy, -1, p)) % p
C2 = (pow(Gy, 3, p) + 1) % p
C1 = (pow(Qy, 3, p) + 1) % p
numerator = (C2 * K - C1) % p
denominator = (pow(Qx, 3, p) - pow(Gx, 3, p) * K) % p
a = (numerator * pow(denominator, -1, p)) % p
print(f'a =', a)
# 计算 d
d = (a * pow(Gx, 3, p) + pow(Gy, 3, p) + 1) * pow(GxGy, -1, p) % p
print(f'd =', d)
'''
a = 39081810733380615260725035189
d = 8569490478014112404683314361
'''

或者直接Gröbner求参数(本质上还是多项式方程组)

代码实现:

p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
# 定义变量
R.<a, d> = PolynomialRing(GF(p))
# 计算 G 和 Q 的相关值
G0, G1 = G
Q0, Q1 = Q
# 构建方程组
eq1 = a * G0^3 + G1^3 + 1 - d * G0 * G1
eq2 = a * Q0^3 + Q1^3 + 1 - d * Q0 * Q1
# 计算 Gröbner 基
I = R.ideal([eq1, eq2])
G = I.groebner_basis()
# 输出 Gröbner 基
print("Gröbner Basis:", G)
# 求解方程组
solutions = I.variety()
print("Solutions:", solutions)
'''
Gröbner Basis: [a + 16017244634673333349551751112, d + 46529564890039836205593471940]
Solutions: [{a: 39081810733380615260725035189, d: 8569490478014112404683314361}]
'''

曲线映射+DLP求解分析

  • a,d知道了,然后就可以曲线映射构建出椭圆曲线并使用Pohlig-Hellman算法解决DLP(离散对数)问题求解出<font style="color:rgb(6, 6, 7);">Q=x⋅G</font>中的这个<font style="color:rgb(6, 6, 7);">x</font>
  • Twisted Herssian上的点映射到Weierstrass上,再求解即可

法1?:首先检查曲线是否奇异,然后将点映射到乘法群并计算离散对数

p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
Gx, Gy = G
Qx, Qy = Q
a = 39081810733380615260725035189
d = 8569490478014112404683314361
##################################################################
# 检查奇异点
rhs = (pow(d, 3, p) * pow(27 * pow(a, 2, p), -1, p)) % p
# 寻找x0的立方根,这里假设存在解
x0 = pow(rhs, (2 * p - 1) // 3, p)
y0 = (3 * a * pow(x0, 2, p) * pow(d, -1, p)) % p
# 映射到乘法群并计算离散对数
t_G = (Gx - x0) * pow(Gy - y0, -1, p) % p
t_Q = (Qx - x0) * pow(Qy - y0, -1, p) % p
x = discrete_log(t_Q, t_G, p)  # 使用离散对数算法求解
print(x)

法2:更方便的是直接通过转为三次齐次方程的方式,再用sage自带的EllipticCurve_from_cubic来做映射

2024-羊城杯-wp-crypto

a = 39081810733380615260725035189
p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
########################################################### part1 get d
d = (a*G[0]^3 + G[1]^3 + 1) * inverse_mod(G[0]*G[1], p) % p
########################################################### part2 dlp
R.<x,y,z> = Zmod(p)[]
cubic = a*x^3 + y^3 + z^3 - d*x*y*z
E = EllipticCurve_from_cubic(cubic,morphism=True)
G = E(G)
Q = E(Q)
r = 60869967041981
m = (r*Q).discrete_log(r*G)
print(m)
#14119952000444809975678010351

这个方法和上面那个其实没什么区别,无非上面是sage自动映射的,下面这个是手动映射的

import gmpy2
p = 55099055368053948610276786301
a = 39081810733380615260725035189
G = (19663446762962927633037926740,35074412430915656071777015320)
d = (a*G[0]^3+G[1]^3+1)*gmpy2.invert(G[1]*G[0], p)%p
Q = (26805137673536635825884330180,26376833112609309475951186883)def calculate_coefficients(a, d):d_3 = d*gmpy2.invert(3, p)%p             # d / 3tmp = a - d_3**3                    # a - d^3/27a0 = 1a1 = (-3 * d_3 * gmpy2.invert(tmp, p))%pa3 = (-9 * gmpy2.invert(tmp**2, p)) % pa2 = (-9 * d_3**2 * gmpy2.invert(tmp**2, p))%pa4 = (-27 * d_3 * gmpy2.invert(tmp**3, p))%pa6 = (-27 * gmpy2.invert(tmp**4, p))%preturn [a1, a2, a3, a4, a6]aa = calculate_coefficients(a, d)
E = EllipticCurve(GF(p), aa)
def Herssian_to_Weierstrass(Point):x, y = Pointu = ((-3 * gmpy2.invert((a - d^3*gmpy2.invert(27, p)), p)*x * gmpy2.invert(d*x*gmpy2.invert(3,p) - (-y) + 1, p))) % pv = ((-9 * gmpy2.invert((a - d^3*gmpy2.invert(27, p))^2, p) ) * (-y) * gmpy2.invert(d*x*gmpy2.invert(3,p) - (-y) + 1, p))%preturn (u, v)G = E(Herssian_to_Weierstrass(G))
Q = E(Herssian_to_Weierstrass(Q))
x = Q.discrete_log(G)
print(x)
#14119952000444809975678010351
  • 但是这时候就出现问题了,为什么得到的<font style="color:#DF2A3F;">x</font>解不出那个密文
  • 找了很多脚本发现可能是~~discrete_log~~~~log~~解离散对数的问题
为什么discrete_loglog的结果不同?
  • **discrete_log**函数:这是一个通用的离散对数求解器,适用于多种数学结构;它可能会返回满足条件的任意解,而不一定是最小的解

  • **log**方法:这是椭圆曲线点对象的内置方法,通常会返回最小的标量倍数,因为它针对椭圆曲线的结构进行了优化

  • 但是我怎么不能用~~**log**~~(AttributeError: 'EllipticCurvePoint_finite_field' object has no attribute 'log')

  • 那就用**discrete_log**吧……

  • 欸!?**x = Q.discrete_log(G)****x = discrete_log(Q, G, operation='+')**

  • 似乎真正的问题在这里

分析<font style="color:rgb(6, 6, 7);">discrete_log</font>函数和椭圆曲线点对象的<font style="color:rgb(6, 6, 7);">discrete_log</font>方法之间的区别
discrete_log函数:

**discrete_log**是一个通用的离散对数求解器,可以用于多种数学结构,包括有限域,椭圆曲线等;它的语法如下:x = discrete_log(Q, G, operation='+')

  • 参数:
    • Q:目标点或目标群元素
    • G:基点或生成元
    • operation:指定群操作的类型,对于椭圆曲线上的点,操作通常是加法('+');对于有限域中的元素,操作通常是乘法('*')
  • 适用范围:
    • 适用于多种数学结构,包括椭圆曲线和有限域
    • 需要显式指定操作类型(加法或乘法)
椭圆曲线点对象的discrete_log方法:

**discrete_log**方法是专门为椭圆曲线上的点设计的离散对数求解器;它的语法如下:x=Q.discrete_log(G)

  • 参数:
    • Q:目标点
    • G:基点或生成元
  • 适用范围:
    • 仅适用于椭圆曲线上的点
    • 不需要显式指定操作类型,因为椭圆曲线上的操作默认是加法

再次进行曲线映射和DLP求解

  • 如果这里的两个阶倍数相差太大算起来会非常慢,那么就可以用Pohlig_Hellman算(参考ECC圆锥曲线-Twisted Hessian曲线-2024年"羊城杯"粤港澳大湾区网络安全大赛-TH_Curve)
  • 不过这里不适用Pohlig_Hellman求解x不知道为什么
  • 只好使用x = discrete_log(Q, G, operation='+')
  • 具体原理不是太懂
from sage.all import *# 定义参数
a = 39081810733380615260725035189
p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)# 计算 d
G0, G1 = G
d = (a * G0^3 + G1^3 + 1) * inverse_mod(G0 * G1, p) % p# 定义椭圆曲线
R = Zmod(p)['x, y, z']; (x, y, z) = R._first_ngens(3)
cubic = a * x^3 + y^3 + z^3 - d * x * y * z
E = EllipticCurve_from_cubic(cubic, morphism=True)# 将点 G 和 Q 映射到椭圆曲线上
G = E(G)
Q = E(Q)# 检查点的阶
order_G = G.order()
order_Q = Q.order()
#18366351789351220439989164171
#18366351789351220439989164171# 验证 Q 的阶是否能整除 G 的阶
if order_Q.divides(order_G):print("Q 的阶能整除 G 的阶,离散对数问题可能有解。")x = discrete_log(Q, G, operation='+')print("离散对数结果:", x)
else:print("Q 的阶不能整除 G 的阶,离散对数问题无解。")
'''
Q 的阶能整除 G 的阶,离散对数问题可能有解。
离散对数结果: 2633177798829352921583206736
'''
  • 这次得到的结果就是对的,x的值为2633177798829352921583206736
  • 最后AES求解……

解答:

from Crypto.Cipher import AES
import hashlib
from Crypto.Util.Padding import unpadx = 2633177798829352921583206736
ciphertext=b"k\xe8\xbe\x94\x9e\xfc\xe2\x9e\x97\xe5\xf3\x04'\x8f\xb2\x01T\x06\x88\x04\xeb3Jl\xdd Pk$\x00:\xf5"
key = hashlib.sha256(str(x).encode()).digest()
Cipher = AES.new(key, AES.MODE_ECB)
padded_message = Cipher.decrypt(ciphertext)
message = unpad(padded_message, AES.block_size)
print(message)
#hgame{N0th1ng_bu7_up_Up_UP!}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/897489.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于双PI控制器结构的六步逆变器供电无刷直流电机调速simulink仿真

1.课题概述基于双PI控制器结构的六步逆变器供电无刷直流电机调速simulink仿真。双PI控制器是一种结合了两个独立的PI控制器的控制策略,用于提高系统的稳定性和动态性能。2.系统仿真结果 (完整程序运行后无水印) 3.核心程序与模型 版本:MATLAB2022a 4.系统原理简介 4.1 无…

第十课 从人类反馈中引导强化学习

GPT-1GPT-2(至少要三个支持是因为网络上的垃圾信息很多,有了支持能够显著减少垃圾信息的量)GPT-2首次实现了零样本学习。零样本学习是指模型在从未接触过特定任务的训练数据 、无需额外示例 、无需调整参数(梯度更新)的情况下,直接完成任务的能力。例如,用户只需给模型一…

Olive直播管理系统

在校园教学与在线教育场景中,师生对实时音视频传输的需求日益增长。传统直播工具往往缺乏定制化功能,且难以满足多平台流分发、低延迟交互等教育场景的特殊需求。因此,本软件旨在打造一款轻量级、高稳定性的直播管理工具,专注于解决以下问题:简化直播流程:教师可快速搭建…

Redis--Lesson05--Redis进阶

一.Redis中的事务 在Redis中,单条命令依旧保持原子性,但是对于事务来说(命令集)不保证原子性 Redis事务的本质:一组命令的集合,一个事务中所有的命令都会被序列化,在事务的执行过程中,会按照顺序执行,一次性,顺序性,排他性!执行一些命令 如:--- 队列 set1,set2,…

基于入侵野草算法的KNN分类优化matlab仿真

1.程序功能描述 基于入侵野草算法的KNN分类优化。其中,入侵野草算法是一种启发式优化算法,它模拟了自然界中野草的扩散与竞争过程。该算法通过一系列的步骤来寻找样板的最优特征,参与KNN的分类训练和测试。 2.测试软件版本以及运行结果展示MATLAB2022A版本运行 (完…

PowerShell实现全屏七彩渐变 呼吸 屏保

引言 想做一下屏幕保护程序的效果-----全屏颜色渐变,类似呼吸灯的效果。就用Windows自带的PowerShell脚本。脚本预设好了七彩颜色,然后循环变化。首先 我们先实现七彩循环切换的全屏效果,也就是不带渐变。 要想实现全屏颜色填充,必须借助"窗口"。对于PowerShell而…

三剑客与正则系列-awk勇闯天下

1.awk概述四剑客 特点 擅长find 查找文件 查找文件,与其他命令配合.grep/egrep 过滤 过滤速度最快.sed 过滤,取行,替换,删除 替换,修改文件内容,取行.awk 过滤,取行,取列,统计计算,判断,循环 ... 取列,取行,统计计算awk是一个语言,叫做单行脚本.2.概述 2.1.格式 取出/etc/passw…

实验楼-Linux(ubuntu)

实验楼-Linux(ubuntu) 1. Linux的桌面系统2. 命令 --help显示更为简单的内容软/硬连接:ln硬连接ln 目的地 硬连接名称硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,因为对应该目录的索引节点有一…

Day10_强制类型转换

VHDL强制类型转换1、STD_LOGIC_VECTOR 转 INTEGER 先将STD_LOGIC_VECTOR根据需求使用signed()转为 SIGNED 或者 使用 unsigned() 转为 UNSIGNED (signed() 和 unsigned() 在 numeric_std 中),然后使用 conv_integer() 或者 to_integer() 转为整数。 conv_integer() 和 to_in…

安装新系统的基础环境

安装新系统的基础环境 ubuntu从阿里云镜像上下载服务器版本系统,安装的时候出现curtin command in-target,需要把apt网址改为http://mirrors.163.com/ubuntu/下载man命令:apt install man看onenote笔记在~/.zshrc中最后一行加上这两行LANG=zh_CN.UTF-8 LANGUAGE=zh_CN.UTF-8cen…

Android Studio初使用

下载是困难,下载速度慢,了解了外网的知识,头一次知道。

第五章 用户身份与文件权限

第五章 用户身份与文件权限 用户身份与能力身份分类管理员UID为0:系统的管理员用户。 系统用户UID为1~999: Linux系统为了避免因某个服务程序出现漏洞而被黑客提权至整台服务器,默认服务程序会有独立的系统用户负责运行,进而有效控制被破坏范围。 普通用户UID从1000开始:…