NSSCTF_crypto_[GKCTF 2021]RRRRsa
提示:费马小定理 二项式定理
题目:
from Crypto.Util.number import *
from gmpy2 import gcd
flag = b'xxxxxxxxxxxxx'
p = getPrime(512)
q = getPrime(512)
m = bytes_to_long(flag)
n = p*q
e = 65537
c = pow(m,e,n)
print('c={}'.format(c))
p1 = getPrime(512)
q1 = getPrime(512)
n1 = p1*q1
e1 = 65537
assert gcd(e1,(p1-1)*(q1-1)) == 1
c1 = pow(p,e1,n1)
print('n1={}'.format(n1))
print('c1={}'.format(c1))
hint1 = pow(2020 * p1 + q1, 202020, n1)
hint2 = pow(2021 * p1 + 212121, q1, n1)
print('hint1={}'.format(hint1))
print('hint2={}'.format(hint2))
p2 = getPrime(512)
q2 = getPrime(512)
n2 = p2*q2
e2 = 65537
assert gcd(e1,(p2-1)*(q2-1)) == 1
c2 = pow(q,e2,n2)
hint3 = pow(2020 * p2 + 2021 * q2, 202020, n2)
hint4 = pow(2021 * p2 + 2020 * q2, 212121, n2)
print('n2={}'.format(n2))
print('c2={}'.format(c2))
print('hint3={}'.format(hint3))
print('hint4={}'.format(hint4))
#c=13492392717469817866883431475453770951837476241371989714683737558395769731416522300851917887957945766132864151382877462142018129852703437240533684604508379950293643294877725773675505912622208813435625177696614781601216465807569201380151669942605208425645258372134465547452376467465833013387018542999562042758
#n1=75003557379080252219517825998990183226659117019770735080523409561757225883651040882547519748107588719498261922816865626714101556207649929655822889945870341168644508079317582220034374613066751916750036253423990673764234066999306874078424803774652754587494762629397701664706287999727238636073466137405374927829
#c1=68111901092027813007099627893896838517426971082877204047110404787823279211508183783468891474661365139933325981191524511345219830693064573462115529345012970089065201176142417462299650761299758078141504126185921304526414911455395289228444974516503526507906721378965227166653195076209418852399008741560796631569
#hint1=23552090716381769484990784116875558895715552896983313406764042416318710076256166472426553520240265023978449945974218435787929202289208329156594838420190890104226497263852461928474756025539394996288951828172126419569993301524866753797584032740426259804002564701319538183190684075289055345581960776903740881951
#hint2=52723229698530767897979433914470831153268827008372307239630387100752226850798023362444499211944996778363894528759290565718266340188582253307004810850030833752132728256929572703630431232622151200855160886614350000115704689605102500273815157636476901150408355565958834764444192860513855376978491299658773170270
#n2=114535923043375970380117920548097404729043079895540320742847840364455024050473125998926311644172960176471193602850427607899191810616953021324742137492746159921284982146320175356395325890407704697018412456350862990849606200323084717352630282539156670636025924425865741196506478163922312894384285889848355244489
#c2=67054203666901691181215262587447180910225473339143260100831118313521471029889304176235434129632237116993910316978096018724911531011857469325115308802162172965564951703583450817489247675458024801774590728726471567407812572210421642171456850352167810755440990035255967091145950569246426544351461548548423025004
#hint3=25590923416756813543880554963887576960707333607377889401033718419301278802157204881039116350321872162118977797069089653428121479486603744700519830597186045931412652681572060953439655868476311798368015878628002547540835719870081007505735499581449077950263721606955524302365518362434928190394924399683131242077
#hint4=104100726926923869566862741238876132366916970864374562947844669556403268955625670105641264367038885706425427864941392601593437305258297198111819227915453081797889565662276003122901139755153002219126366611021736066016741562232998047253335141676203376521742965365133597943669838076210444485458296240951668402513
本题为多层RSA加密系统,需通过两组RSA参数解密得到中间值,最终组合解密获得flag。题目核心在于利用GCD攻击分解模数,突破双层加密结构。
数学关系构建
通过hint的构造关系,建立模运算方程:
hint1≡2020^202020modp
hint2≡2021^202020modp
构造差值触发GCD分解:
gcd(2021^202020*hint1−[2020*(hint2−212121)]^202020,n1)=p
# 计算因子q
q = gcd(pow(2021,202020)*hint1 - pow(2020*(hint2-212121),202020,n1), n1)
p = n1 // q
# 标准RSA解密
d = invert(0x10001, (p-1)*(q-1))
pp = pow(c1, d, n1) # 得到中间值pp
数学关系构建
利用hint3/hint4的指数关系:
hint3≡202020^2020modp
hint4≡202121^2121modp
构造复合差值:
gcd((202120^2020*hint3)^212121−(2020^212121*hint4)^202020,n2)=p
# 计算因子q
q = gcd(pow(pow(2021,202020)*hint3,212121,n2) - pow(pow(2020,212121)*hint4,202020,n2), n2)
p = n2 // q
# 标准RSA解密
d = invert(0x10001, (p-1)*(q-1))
qq = pow(c2, d, n2) # 得到中间值qq
组合新RSA参数
nfinal=pp×qq,ϕ=(pp−1)(qq−1)d = invert(0x10001, phi)
flag = pow(c, d, n_final)
print(long_to_bytes(flag)) # 输出flag
GCD攻击原理
当 x≡ymod px≡ymodp 且 x≢ y mod qx≡ymodq 时,gcd(x−y,n)=pgcd(x−y,n)=p
利用题目设计的hint关系构造满足条件的差值
模运算性质
abmod p=(a mod p)^b mod p允许在模数分解前进行大数运算优化
多层RSA特性
每层RSA的解密结果为下一层的参数
需保持参数传递的完整性
完整代码
from gmpy2 import *
from Crypto.Util.number import *
# 题目给出的加密数据
c = 13492392717469817866883431475453770951837476241371989714683737558395769731416522300851917887957945766132864151382877462142018129852703437240533684604508379950293643294877725773675505912622208813435625177696614781601216465807569201380151669942605208425645258372134465547452376467465833013387018542999562042758
# 第一组RSA参数
n1 = 75003557379080252219517825998990183226659117019770735080523409561757225883651040882547519748107588719498261922816865626714101556207649929655822889945870341168644508079317582220034374613066751916750036253423990673764234066999306874078424803774652754587494762629397701664706287999727238636073466137405374927829
c1 = 68111901092027813007099627893896838517426971082877204047110404787823279211508183783468891474661365139933325981191524511345219830693064573462115529345012970089065201176142417462299650761299758078141504126185921304526414911455395289228444974516503526507906721378965227166653195076209418852399008741560796631569
hint1 = 23552090716381769484990784116875558895715552896983313406764042416318710076256166472426553520240265023978449945974218435787929202289208329156594838420190890104226497263852461928474756025539394996288951828172126419569993301524866753797584032740426259804002564701319538183190684075289055345581960776903740881951
hint2 = 52723229698530767897979433914470831153268827008372307239630387100752226850798023362444499211944996778363894528759290565718266340188582253307004810850030833752132728256929572703630431232622151200855160886614350000115704689605102500273815157636476901150408355565958834764444192860513855376978491299658773170270
# 第二组RSA参数
n2 = 114535923043375970380117920548097404729043079895540320742847840364455024050473125998926311644172960176471193602850427607899191810616953021324742137492746159921284982146320175356395325890407704697018412456350862990849606200323084717352630282539156670636025924425865741196506478163922312894384285889848355244489
c2 = 67054203666901691181215262587447180910225473339143260100831118313521471029889304176235434129632237116993910316978096018724911531011857469325115308802162172965564951703583450817489247675458024801774590728726471567407812572210421642171456850352167810755440990035255967091145950569246426544351461548548423025004
hint3 = 25590923416756813543880554963887576960707333607377889401033718419301278802157204881039116350321872162118977797069089653428121479486603744700519830597186045931412652681572060953439655868476311798368015878628002547540835719870081007505735499581449077950263721606955524302365518362434928190394924399683131242077
hint4 = 104100726926923869566862741238876132366916970864374562947844669556403268955625670105641264367038885706425427864941392601593437305258297198111819227915453081797889565662276003122901139755153002219126366611021736066016741562232998047253335141676203376521742965365133597943669838076210444485458296240951668402513
# 第一组解密过程
# 通过hint1和hint2的关系找到n1的因子q
q = gmpy2.gcd(
pow(2021, 202020) * hint1 - pow(2020 * (hint2 - 212121), 202020, n1),
n1
)
p = n1 // q # 计算另一个因子p
d = gmpy2.invert(0x10001, (p-1)*(q-1)) # 计算私钥d
pp = pow(c1, d, n1) # 解密c1得到中间值pp
# 第二组解密过程
# 通过hint3和hint4的关系找到n2的因子q
q = gmpy2.gcd(
pow(pow(2021, 202020) * hint3, 212121, n2) - pow(pow(2020, 212121) * hint4, 202020, n2),
n2
)
p = n2 // q # 计算另一个因子p
d = gmpy2.invert(0x10001, (p-1)*(q-1)) # 计算私钥d
qq = pow(c2, d, n2) # 解密c2得到中间值qq
# 最终解密
d = gmpy2.invert(0x10001, (pp-1)*(qq-1)) # 计算最终私钥
flag = pow(c, d, pp*qq) # 解密密文c
print(long_to_bytes(flag)) # 转换为字节输出flag
运行后flag为
GKCTF{f64310b5-d5e6-45cb-ae69-c86600cdf8d8}
修改一下
NSSCTF{f64310b5-d5e6-45cb-ae69-c86600cdf8d8}