meitoumeinao

欢迎来到槑头槑脑的博客!
什么都不会的小菜鸡
  1. 首页
  2. Crypto
  3. 正文

easy_factor系列

2026年2月22日 298点热度 0人点赞 0条评论

本文记录 NSS 靶场 tangcuxiaojkuai 的 easy_factor 系列题解/学习笔记。该系列主要围绕 费马小定理 展开,核心收获是:当已知 φ(n),或者已知形如 k·φ(n) 的信息时,可以利用这些条件对 n 进行分解,从而还原 RSA 的关键参数。

这个假期整体状态不算太好——毕竟过年嘛,比赛也比较少,刷题节奏自然就慢了些。靶场里一些相对简单的密码题我基本都做得差不多了(/(ㄒoㄒ)/~~),接下来打算把重心放到更进阶的方向:二元 Coppersmith、广义 RSA,以及 LWE 相关问题上。

[tangcuxiaojkuai]easy_factor1

from Crypto.Util.number import *
from Crypto.Util.Padding import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import *
from secret import flag
​
p,q,r = getPrime(256),getPrime(256),getPrime(256)
n = p*q*r
phi = (p-1)*(q-1)*(r-1)
​
key = sha256(str(p+q+r).encode()).digest()
enc = AES.new(key, AES.MODE_ECB)
c = enc.encrypt(pad(flag,16))
​
print("n =",n)
print("hint =",getrandbits(256)*phi**3)
print("c =",c)
​
'''
n = 343127312894441264623060100705188723106648253383902349620699412384677995734576572885137280031507308915752070128528949423639735964709160841591038148069185325450544546735392923674211031016035209702254447128968565740534765322198664691
hint = 3802744632475774666777934738986183209966233570124815804333822490240409933768208822899072601181527365734196352249978937639454658680559993507805820991037544059215540360338084909833242583087617315128513337647913472696515770688338805196215328080662137260951972365100322795737835152857750114216709340410268143017180826135339564387228460663261697814425298725805568817218360964967025967384766127098203664964210047103829182895016532403825215903779806760754721373523135367007867453212189953817229696304611549977864533229540971457717668560698088917340909962348110683581294453903261530189579223087858081200349343639420534779115290433982968345085704202494045885911950427043282588446343291558819683037970053828479057449781943479407877748772895179095205885377333120540311815022381056
c = b';#\x1b\xa6R\xe2\x1d\x9dpf\x8e\xda\xe4\x14\x9a\xfb\tr\x99\x8a\xc9r\x03C\xb58Zb\x97\x0b\xc7S\x0fa\x88\xb4\xe4\x16.M\x92\x94\x94\x8b\xa9Ki\x9b\xe4\xe9d5\xa3~\x1a\x9cx\x03\xdc\x1f\x87\x14E\x90'
'''

本题用到了费马小定理(做题的时候还是经常用到的,但是经常"差一点"),是一种已知phi进行分解n的思路

费马小定理:

条件:p是素数, gcd⁡(a,p)=1结论:ap−1≡1(modp)\begin{aligned} \text{条件:} & p\text{是素数},\ \gcd(a,p)=1 \\ \text{结论:} & a^{p-1}\equiv 1 \pmod p \end{aligned}

其实我们可以扩展一下,得到下面的两个式子

afai(n)=1(mod n)ak∗fai(n)=1(mod n)a^{fai(n)}=1(mod \ n)\\ a^{k*fai(n)}=1(mod \ n)

回归题目

我们尝试先将hint分解

hint=k*(fai^3)

那么这里面的三次大概率就是fai的

而fai=(p-1)(q-1)(r-1)

那么例如7,如果是fai分解得到的因子,必定是其中一个p-1分解得到的

那么当我们fai//(7^3)之后,相当于破坏了fai(p),即fai !=k*fai(p)

我们得到式子

ahint//i≠1(mod n)a^{hint//i}\ne1(mod \ n)

但由于fai = k*fai (qr)

ahint//i=1(mod q∗r)a^{hint//i}=1(mod \ q*r)

那么我们此时a^(hint//r)(mod qr)-1和n进行gcd得到的是qr

逐个这样我们就可以分解到所有的素数

学会了这个就学会利用fai进行分解n了

其实走到这里可以感觉到和p-1光滑的思路是一样的收集fai(p)的因子,得到k*fai(p)就可以gcd出来p

解码代码

from gmpy2 import gmpy2
from Crypto.Util.number import *
from Crypto.Util.Padding import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import *
n = 343127312894441264623060100705188723106648253383902349620699412384677995734576572885137280031507308915752070128528949423639735964709160841591038148069185325450544546735392923674211031016035209702254447128968565740534765322198664691
hint = 3802744632475774666777934738986183209966233570124815804333822490240409933768208822899072601181527365734196352249978937639454658680559993507805820991037544059215540360338084909833242583087617315128513337647913472696515770688338805196215328080662137260951972365100322795737835152857750114216709340410268143017180826135339564387228460663261697814425298725805568817218360964967025967384766127098203664964210047103829182895016532403825215903779806760754721373523135367007867453212189953817229696304611549977864533229540971457717668560698088917340909962348110683581294453903261530189579223087858081200349343639420534779115290433982968345085704202494045885911950427043282588446343291558819683037970053828479057449781943479407877748772895179095205885377333120540311815022381056
c = b';#\x1b\xa6R\xe2\x1d\x9dpf\x8e\xda\xe4\x14\x9a\xfb\tr\x99\x8a\xc9r\x03C\xb58Zb\x97\x0b\xc7S\x0fa\x88\xb4\xe4\x16.M\x92\x94\x94\x8b\xa9Ki\x9b\xe4\xe9d5\xa3~\x1a\x9cx\x03\xdc\x1f\x87\x14E\x90'
​
# 2^11 · 3^6 · 7^3 · 13^6 · 41^3 · 79^3 · 83^3 · 277^3 · 248701^3
​
list_=[2,4,8,3,9,7,13,13^2,41,79,83,277,248701]
primes=[]
for i in list_:
   # print(gcd(n,pow(2,hint//i,n)-1))
   # print(i)
   if gcd(n,pow(2,hint//(i**3),n)-1)==n:
       continue
   else:
       prime=n//gcd(n,pow(2,hint//(i**3),n)-1)
       if gmpy2.is_prime(prime) and len(bin(prime))-2==256:
           primes.append(prime)
           # print(prime)
primes = list(set(primes))
# print(primes)
p,q,r=primes
key = sha256(str(p+q+r).encode()).digest()
enc = AES.new(key, AES.MODE_ECB)
flag = enc.decrypt(c)
print(flag)

[tangcuxiaojkuai]easy_factor2

还不是很熟悉,之后会补齐

[tangcuxiaojkuai]easy_factor3

题目代码

from Crypto.Util.number import *
from secret import flag
​
def gen_noisy_sum_of_base(m,p):
   sum = 0
   while(m):
       sum += m % p
       m //= p
   return sum//1000
​
flag = bytes_to_long(flag)
e = 65537
p = getPrime(256)
q = getPrime(256)
n = p*q
​
m1 = getRandomNBitInteger(2048)
m2 = getRandomNBitInteger(2048)
print("m1 =",m1)
print("m2 =",m2)
print("sum1 =",gen_noisy_sum_of_base(m1,p))
print("sum2 =",gen_noisy_sum_of_base(m2,p))
print("n =",n)
print("c =",pow(flag,e,n))
​
'''
m1 = 23145761572719481962762273155673006162798724771853359777738044204075205506442533110957905454673168677138390288946164925146182350082798412822843805544411533748092944111577005586562560198883223125408349637392132331590745338744632420471550117436081738053152425051777196723492578868061454261995047266710226954140246577840642938899700421187651113304598644654895965391847939886431779910020514811403672972939220544348355199254228516702386597854501038639792622830084538278039854948584633614251281566284373340450838609257716124253976669362880920166668588411500606044047589369585384869618488029661584962261850614005626269748136
m2 = 21293043264185301689671141081477381397341096454508291834869907694578437286574195450398858995081655892976217341587431170279280993193619462282509529429783481444479483042173879669051228851679105028954444823160427758701176787431760859579559910604299900563680491964215291720468360933456681005593307187729279478018539532102837247060040450789168837047742882484655150731188613373706854145363872001885815654186972492841075619196485090216542847074922791386068648687399184582403554320117303153178588095463812872354300214532980928150374681897550358290689615020883772588218387143725124660254095748926982159934321361143271090861833
sum1 = 309575642078438773208947649750793560438038690144069550000470706236111082406
sum2 = 303394719183577651416751448350927044928060280972644968966068528268042222965
n = 4597063839057338886607228486569583368669829061896475991448013970518668754752831268343529061846220181652766402988715484221563478749446497476462877699249731
c = 3253873276452081483545152055347615580632252871708666807881332670645532929747667442194685757039215506084199053032613562932819745309368748317106660561209205
'''

简单测试函数gen_noisy_sum_of_base(m,p)

其功能就是将m转换成p进制下的数字,对其系数求和,然后除以1000,那么我们爆破1000以内就可以了

m1=a0⋅p0+a1⋅p1+a2⋅p2+⋯+an−1⋅pn−1sum1=⌊a0+a1+a2+⋯+an−11000⌋\begin{aligned} m_1 &= a_0\cdot p^0 + a_1\cdot p^1 + a_2\cdot p^2 + \cdots + a_{n-1}\cdot p^{\,n-1} \\ \mathrm{sum}_1 &= \left\lfloor \frac{a_0 + a_1 + a_2 + \cdots + a_{n-1}}{1000} \right\rfloor \end{aligned}

我们将sum1乘以1000并进行爆破,得到

sum1 =(a0+a1+a2+……+an−1)sum1 \ =(a_0+a_1+a_2+……+a_{n-1})

此时m1减去sum1可以得到

m1−sum1=a0∗(p0−1)+a1∗(p1−1)+a2∗(p2−1)+……+an−1∗(pn−1−1)m1-sum1=a_0*(p^0-1)+a_1*(p^1-1)+a_2*(p^2-1)+……+a_{n-1}*(p^{n-1}-1)

其实m1-sum1是整除p-1的

第一项a_0*(p^0-1)显然是0

对应后面的项

我这几天看EZ_Fermat的题目时候看到这个性质了

m1-sum1=k*fai(p)

那么,根据费马小定理

GCD(2m1−sum1(mod n)−1,n)==GCD(2k∗fai(p)(mod n)−1,n)==pGCD(2^{m1-sum1} (mod \ n) -1,n)==GCD(2^{k*fai(p)} (mod \ n) -1,n)==p

本题不需要m2和hint2即可分解

from Crypto.Util.number import *
m1 = 23145761572719481962762273155673006162798724771853359777738044204075205506442533110957905454673168677138390288946164925146182350082798412822843805544411533748092944111577005586562560198883223125408349637392132331590745338744632420471550117436081738053152425051777196723492578868061454261995047266710226954140246577840642938899700421187651113304598644654895965391847939886431779910020514811403672972939220544348355199254228516702386597854501038639792622830084538278039854948584633614251281566284373340450838609257716124253976669362880920166668588411500606044047589369585384869618488029661584962261850614005626269748136
m2 = 21293043264185301689671141081477381397341096454508291834869907694578437286574195450398858995081655892976217341587431170279280993193619462282509529429783481444479483042173879669051228851679105028954444823160427758701176787431760859579559910604299900563680491964215291720468360933456681005593307187729279478018539532102837247060040450789168837047742882484655150731188613373706854145363872001885815654186972492841075619196485090216542847074922791386068648687399184582403554320117303153178588095463812872354300214532980928150374681897550358290689615020883772588218387143725124660254095748926982159934321361143271090861833
sum1 = 309575642078438773208947649750793560438038690144069550000470706236111082406
sum2 = 303394719183577651416751448350927044928060280972644968966068528268042222965
n = 4597063839057338886607228486569583368669829061896475991448013970518668754752831268343529061846220181652766402988715484221563478749446497476462877699249731
c = 3253873276452081483545152055347615580632252871708666807881332670645532929747667442194685757039215506084199053032613562932819745309368748317106660561209205
e=65537
sum1=sum1*1000
for i in range(1000):
   fai1=m1-(sum1+i)
   a=pow(2,fai1,n)
   # print(gcd(a-1,n))
   if gcd(a-1,n)==1:
       continue
   else:
       p=gcd(a-1,n)
       q=n//p
       d=pow(e,-1,(p-1)*(q-1))
       m=pow(c,d,n)
       print(long_to_bytes(int(m)))

[tangcuxiaojkuai]easy_factor4

题目代码

from Crypto.Util.number import *
from Crypto.Util.Padding import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import *
from secret import flag
​
p = getPrime(256)
q = getPrime(256)
n = p*q
phi = (p-1)*(q-1)
e = 65537
d = inverse(e,phi)
​
key = sha256(str(p+q).encode()).digest()
enc = AES.new(key, AES.MODE_ECB)
c = enc.encrypt(pad(flag,16))
hint = getPrime(20)*d**3 + getPrime(128)*phi**2
​
print("n =",n)
print("c =",c)
print("hint =",hint)
​
​
'''
n = 8218998145909849489767589224752145194323996231101223014114062788439896662892324765430227087699807011312680357974547103427747626031176593986204926098978521
c = b'\x9a \x8f\x96y-\xb4\tM\x1f\xe6\xcc\xef\xd5\x19\xf26`|B\x10N\xd7\xd0u\xafH\x8d&\xe3\xdbG\x13\x8e\xea\xc0N\n\r\x91\xdc\x95\x9b\xb1Ny\xc1\xc4'
hint = 1860336365742538749239400340012599905091601221664081527583387276567734082070898348249407548568429668674672914754714801138206452116493106389151588267356258514501364109988967005351164279942136862087633991319071449095868845225164481135177941404709110974226338184970874613912364483762845606151111467768789248446875083250614540611690257121725792701375153027230580334095192816413366949340923355547691884448377941160689781707403607778943438589193122334667641037672649189861
'''

我们主要观察hint这个式子

hint = getPrime(20)*d**3 + getPrime(128)*phi**2
hint=a∗d3+b∗ϕ2两边同时乘 e3hint∗e3=a∗(k∗ϕ+1)+b∗ϕ2移项得到: hint∗e3−a=a∗k∗ϕ2+b∗ϕ3=t∗ϕ\begin{array}{l} \text{hint} = a*d^3 + b*\phi^2 \\ \text{两边同时乘 } e^3 \\ \text{hint}*e^3 = a*(k*\phi + 1) + b*\phi^2 \\ \text{移项得到:}\ \text{hint}*e^3 - a = a*k*\phi^2 + b*\phi^3 = t*\phi \end{array}

又是熟悉的费马小定理的形式了,a是20位,完全可以爆破,然后思路和easy_factor1一样了

解码代码

from Crypto.Util.number import *
from Crypto.Util.Padding import *
from Crypto.Cipher import AES
from hashlib import sha256
from gmpy2 import *
from tqdm import *
n = 8218998145909849489767589224752145194323996231101223014114062788439896662892324765430227087699807011312680357974547103427747626031176593986204926098978521
c = b'\x9a \x8f\x96y-\xb4\tM\x1f\xe6\xcc\xef\xd5\x19\xf26`|B\x10N\xd7\xd0u\xafH\x8d&\xe3\xdbG\x13\x8e\xea\xc0N\n\r\x91\xdc\x95\x9b\xb1Ny\xc1\xc4'
hint = 1860336365742538749239400340012599905091601221664081527583387276567734082070898348249407548568429668674672914754714801138206452116493106389151588267356258514501364109988967005351164279942136862087633991319071449095868845225164481135177941404709110974226338184970874613912364483762845606151111467768789248446875083250614540611690257121725792701375153027230580334095192816413366949340923355547691884448377941160689781707403607778943438589193122334667641037672649189861
e = 65537
hint=hint*(e**3)
for a in tqdm(range(2**20)):
   if not gmpy2.is_prime(a):
       continue
   if pow(2,hint-a,n)==1:
       hint=hint-a
       print('found a=',i)
       break
print(hint)
list_=[2,4,8,16,3,3^2,3^3,3^4,11,31,73,101,137,179,397,1871,6113,74713,1050887,106031326409,1081244969177,7836595938569,9491217938233]
for i in list_:
   k_fai=hint//i
   if GCD(pow(2,k_fai,n)-1,n)==1 or GCD(pow(2,k_fai,n)-1,n)==n:
       continue
   else:
       print(GCD(pow(2,k_fai,n)-1,n))
       p=GCD(pow(2,k_fai,n)-1,n)
       q=n//p
       print(gmpy2.is_prime(p),gmpy2.is_prime(q))
       key = sha256(str(p+q).encode()).digest()
       enc = AES.new(key, AES.MODE_ECB)
       flag = enc.decrypt(c)
       print(flag)
       break
标签: RSA
最后更新:2026年2月23日

meitoumeinao

做点简单的文章

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

标签聚合
Coppersmith 格级规约 背包密码 efai不互素 RSA dp部分泄露 LLL ECDSA
文章目录
  • [tangcuxiaojkuai]easy_factor1
  • [tangcuxiaojkuai]easy_factor2
  • [tangcuxiaojkuai]easy_factor3
  • [tangcuxiaojkuai]easy_factor4

COPYRIGHT © 2026 wordpress. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang