研究a*p^n + b*q^n问题
我在打H&NCTF比赛时遇到了这个问题,现在来深究一下。
一:主要原理
首先我们会得到关系式:
\[a*p^n + b*q^n = \text{hint}
\]
可以推到:
\[a*p^n + b*q^n \equiv 0 \pmod{\text{hint}}
\]
\[\left(\frac{p}{q}\right)^n \equiv -\frac{b}{a} \pmod{\text{hint}}
\]
设x:
\[x = \frac{p}{q}
\]
则:
\[a*x^n + b \equiv 0 \pmod{\text{hint}}
\]
通过有限域求根得
\[x \equiv k \pmod{\text{hint}}
\]
即:
\[p \equiv kq \pmod{\text{hint}}
\]
构造矩阵
\[M = \begin{bmatrix}
1 & k \\
0 & \text{hint}
\end{bmatrix}
\]
最终表达式:
\[p = kq + t \cdot \text{hint} \quad (p, q \in K,\ \text{hint} \mid kq)
\]
代码实现:
from sage.all import Zmod, ZZ, matrix, PolynomialRing
from functools import reduce
from Crypto.Util.number import inverse, isPrime, long_to_bytes
hint=
a=
b=
n=
R = Zmod(hint)
x = PolynomialRing(R, 'x').gen()
f = a*x**n + b
root = f.roots()[0][0]
# Build lattice
M = matrix(ZZ, [[1, root], [0, hint]])
# LLL reduction
L = M.LLL()
p, q = map(abs, L[0])
p, q = int(p), int(q)
print(f"p = {p}\nq = {q}")
print(f"isPrime(p) = {isPrime(p)}, isPrime(q) = {isPrime(q)}")
二:例题
题目1:H&NCTF Three vertical lines
from Crypto.Util.number import *
from secret import flag
from rsa.prime import getprime
while(1):
p=getprime(256)
q=getprime(256)
if isPrime(3*p**5+4*q**5):
print(3*p**5+4*q**5)
break
e = 65537
print(pow(bytes_to_long(flag), e, p * q))
#72063558451087451183203801132459543552092564094711815404066471440396765744526854383117910805713050240067432476705168314622044706081669935956972031037827580519320550326077291392722314265758802332280697884744792689996718961355845963752788234205565249205191648439412084543163083032775054018324646541875754706761793307667356964825613429368358849530455220484128264690354330356861777561511117
#2864901454060087890623075705953001126417241189889895476561381971868301515757296100356013797346138819690091860054965586977737630238293536281745826901578223
给定关系式:
\[3p^5 + 4q^5 = \text{hint}
\]
推导:
\[3p^5 + 4q^5 \equiv 0 \pmod{\text{hint}}
\]
\[\left(\frac{p}{q}\right)^5 \equiv -\frac{4}{3} \pmod{\text{hint}}
\]
设x:
\[x = \frac{p}{q}
\]
则:
\[3x^5 + 4 \equiv 0 \pmod{\text{hint}}
\]
通过有限域求根得
\[x \equiv k \pmod{\text{hint}}
\]
即:
\[p \equiv kq \pmod{\text{hint}}
\]
构造矩阵
\[M = \begin{bmatrix}
1 & k \\
0 & \text{hint}
\end{bmatrix}
\]
最终表达式:
\[p = kq + t \cdot \text{hint} \quad (p, q \in K,\ \text{hint} \mid kq)
\]
由于 p 和 q 是 512 位,hint是1282位,p,q远小于 hint,因此 (p,q) 是格中的短向量。
exp:
from sage.all import Zmod, ZZ, matrix, PolynomialRing
from functools import reduce
from Crypto.Util.number import inverse, isPrime, long_to_bytes
hint=72063558451087451183203801132459543552092564094711815404066471440396765744526854383117910805713050240067432476705168314622044706081669935956972031037827580519320550326077291392722314265758802332280697884744792689996718961355845963752788234205565249205191648439412084543163083032775054018324646541875754706761793307667356964825613429368358849530455220484128264690354330356861777561511117
c=2864901454060087890623075705953001126417241189889895476561381971868301515757296100356013797346138819690091860054965586977737630238293536281745826901578223
e = 65537
R = Zmod(hint)
x = PolynomialRing(R, 'x').gen()
f = 3*x**5 + 4
root = f.roots()[0][0]
# Build lattice
M = matrix(ZZ, [[1, root], [0, hint]])
# LLL reduction
L = M.LLL()
p, q = map(abs, L[0])
p, q = int(p), int(q)
print(f"p = {p}\nq = {q}")
print(f"isPrime(p) = {isPrime(p)}, isPrime(q) = {isPrime(q)}")
"""
p = 106939296519048296066609095791824433210081775149307042159537637081687455851889
q = 88318396054969634676003916964315749322940927962528304238128738629965788358867
isPrime(p) = True, isPrime(q) = True
"""
from Crypto.Util.number import long_to_bytes
import gmpy2
c=2864901454060087890623075705953001126417241189889895476561381971868301515757296100356013797346138819690091860054965586977737630238293536281745826901578223
p = 106939296519048296066609095791824433210081775149307042159537637081687455851889
q = 88318396054969634676003916964315749322940927962528304238128738629965788358867
n = p * q
phi_n = (p - 1) * (q - 1)
e = 65537
d = gmpy2.invert(e, phi_n)
m = pow(c, d, n)
print(long_to_bytes(m))
#b'H&NCTF{You_learned_the_code_well}'
题目2:niteCTF2024 R Stands Alone
from Crypto.Util.number import *
def gen_keys():
while True:
a = getPrime(128)
b = getPrime(128)
A = a+b
B = a-b
p = ((17*A*A*A) - (15*B*B*B) - (45*A*A*B) + (51*A*B*B)) // 8
if isPrime(p) :
return a, b, p
p, q, r = gen_keys()
e = 65537
n = p*q*r
flag = b"nite{REDACTED}"
ct = pow(bytes_to_long(flag), e, n)
print(f"{r =}")
print(f"{ct =}")
"""OUTPUT :
r = 17089720847522532186100904495372954796086523439343401190123572243129905753474678094845069878902485935983903151003792259885100719816542256646921114782358850654669422154056281086124314106159053995410679203972646861293990837092569959353563829625357193304859110289832087486433404114502776367901058316568043039359702726129176232071380909102959487599545443427656477659826199871583221432635475944633756787715120625352578949312795012083097635951710463898749012187679742033
ct = 583923134770560329725969597854974954817875793223201855918544947864454662723867635785399659016709076642873878052382188776671557362982072671970362761186980877612369359390225243415378728776179883524295537607691571827283702387054497203051018081864728864347679606523298343320899830775463739426749812898275755128789910670953110189932506526059469355433776101712047677552367319451519452937737920833262802366767252338882535122186363375773646527797807010023406069837153015954208184298026280412545487298238972141277859462877659870292921806358086551087265080944696281740241711972141761164084554737925380675988550525333416462830465453346649622004827486255797343201397171878952840759670675361040051881542149839523371605515944524102331865520667005772313885253113470374005334182380501000
"""
这道题,先看gen_keys的生成方式,设p, q, r=a, b, p,然后根据 A = a+b,B = a-b 解原方程,得到:
\[p^3 + 16*q^3 = \text{r}
\]
就可以转化为解决a*p^n + b*q^n的问题,直接可以套模板了,如下:
from sage.all import Zmod, ZZ, matrix, PolynomialRing
from functools import reduce
from Crypto.Util.number import inverse, isPrime, long_to_bytes
import gmpy2
r = 17089720847522532186100904495372954796086523439343401190123572243129905753474678094845069878902485935983903151003792259885100719816542256646921114782358850654669422154056281086124314106159053995410679203972646861293990837092569959353563829625357193304859110289832087486433404114502776367901058316568043039359702726129176232071380909102959487599545443427656477659826199871583221432635475944633756787715120625352578949312795012083097635951710463898749012187679742033
a=1
b=16
n=3
R = Zmod(r)
x = PolynomialRing(R, 'x').gen()
f = a*x**n + b
root = f.roots()[0][0]
# Build lattice
M = matrix(ZZ, [[1, root], [0, r]])
# LLL reduction
L = M.LLL()
p, q = map(abs, L[0])
p, q = int(p), int(q)
print(f"p = {p}\nq = {q}")
print(f"isPrime(p) = {isPrime(p)}, isPrime(q) = {isPrime(q)}")
p = 10072783682149096496560021303116377805854549188797262439950559674169510967907458008084848733118235190641349698455196677635952366670230109231872222236754559
q = 9036110971390653235054772621128562083119528851536791839942998633782706649988009159574634878901931842244724499813215803519063457860914973719080269319085089
n = p * q
ct = 583923134770560329725969597854974954817875793223201855918544947864454662723867635785399659016709076642873878052382188776671557362982072671970362761186980877612369359390225243415378728776179883524295537607691571827283702387054497203051018081864728864347679606523298343320899830775463739426749812898275755128789910670953110189932506526059469355433776101712047677552367319451519452937737920833262802366767252338882535122186363375773646527797807010023406069837153015954208184298026280412545487298238972141277859462877659870292921806358086551087265080944696281740241711972141761164084554737925380675988550525333416462830465453346649622004827486255797343201397171878952840759670675361040051881542149839523371605515944524102331865520667005772313885253113470374005334182380501000
phi_n = (p - 1) * (q - 1)
e = 65537
d = gmpy2.invert(e, phi_n)
m = pow(ct, d, n)
print(long_to_bytes(int(m)))
"""
p = 10072783682149096496560021303116377805854549188797262439950559674169510967907458008084848733118235190641349698455196677635952366670230109231872222236754559
q = 9036110971390653235054772621128562083119528851536791839942998633782706649988009159574634878901931842244724499813215803519063457860914973719080269319085089
isPrime(p) = True, isPrime(q) = True
b'nite{7h3_Latt1c3_kn0ws_Ur_Pr1m3s_very_vvery_v3Ry_w3LLL}'
"""
菜鸟一枚,要是有错误欢迎各路大佬指正

浙公网安备 33010602011771号