2019UNCTF-CRYPTO-simple_rsa

大熊何在發表於2020-11-04


每天一題,只能多不能少

simple_rsa

題目分析

  1. Pollard’s rho algorithm,PollardRho_p_1演算法
  2. 小素數
  3. n降低

開始

1.題目

簡單粗暴的給了個原指令碼:

#!/usr/bin/env python2
# -*- coding:utf8 -*-
from Crypto.Util.number import *

flag='XXXXXXXXXX'
e=0x10001
n=3464115689260819392935656139231271022088014497600959975252672820761470484618617542699739764705620767566046150296286140279466041905437740736319886548924058066340624280173573039937440574809212831672936265975209972857747738693288788052694888593629820783280181774594890101819911390468376042288685444703477639361249422054925155575158181408046447773183467474182159096249846479461475003039637685547191529769071424947165685996675043741359728960138725130116665515880652680244470002603320184043266997163009799067135481330853926800023087208636366543210276325733789567957712475079676808820490428973148590780103404729397985019089646026534758042652163974037179260930147000267787012874887703048185189387666199961350969478997330352491403611551096779887936063702892671572230523920277869824082318417366635732798078805070773662305098133013800559413976855639167085996705265872418286939474978058429877355305699191892248323534097124680592084808397263288943661630283254265898940430505371463275516870915261799702701453110383723660477322192658118815861974573497885759332587457883589126213868868281682733732394640188383458580555618181208722172011645063817887462511925363883111475043389367021569982583145912277082528397480756465818166640691294267829613428532584923122279261412957652411789780285394451850006055483598427256129336822790446219260722224551892755568723667049099823707012236618539013908897459508493477299241358343681962043777720375898238069411747593247677719659288861028038609681592049271388766040068274682329498410270047730060645409396168652996740411436504098243588534151795927613112273405281530700440843961363083171583053608594479571127638861391879160062136043924515492933057094406001740725150570943724333872057035272515676895138632004436149126542560186729495087753846670118167613304943153665660470977150177815354160112481310498255965933157902965011317272734556307544837058247794721427834401390455487872367113056168812990496943458920406382650794656884209032284257748450399719067686010156664485086500184078244358783696803659745365860507822269113477617988541658390715640119076036723560146145256418191555730429
m=bytes_to_long(flag)
c=pow(m,e,n)
# print(c)
assert c==1348180992713820685594359831085361247035354818267759694375727771380213764105201303900290589048476671838784929302557807429509301123621642066527762448168417430350203900517746161928291953862336621873868684964993481406952303460424386080800907869577832154132021624995347121475139439850224598911049824567475034545196149320206620924509546294914370633958171840525667753751028800452370972967842349036965813468093121305475860652163573748880159896028384459277781803606279654121781761535513864212749202340439422384362197321739535686506006254445152569135807838677803047115947240251817017395748631234023225248868640103807357800695487118067385969130665294711887439861169737031598274672286881054564295019370600398079829687943670066246766386800967129670975899437309257181151390273864539453238400821713398980792443187238155205199387468000884390778225928491109565539772444103430764411852162036780535068932010631521096301305200494731040799554079996593223419379540630567412342494359961515157700054387356888773321804429041668331430841954949061238002355270616266853430676140296078177898764114420743905073496118755793091902224563802923183897542996809393707165837427396760691616506592877656939455806776333105152244073459704842848097376929745632888315642056267589901527329593161439752243318158600747713335265681764274061086952626629147275106502354039293870614872849851780761537660716667003562253735923584765118319171207551032289722689929226947535724389015974764265109970513715649126340709399701638880824570967389428525179746112494690443526404899052482884526335312491500994658519105204100875596292743155076199283666094556235485722975240358390560161706163569618302627055238860096406627340558428533728688904747040262153892623865784320600845613247625784683300197845026108394831724602330903266980995146046956218083954561639114586880305451066793209385702886944430548686040360906088479432852330611586273784509957389880104225534635731572089138568407411433675077699382999593384336070450058824669351046095205147266720901917218217564113964074957585348227506587531149811564371155522575778721899999227020238022970334707476977210019

2.分析

n如此之大,如此之大,直接分解是肯定不行的。雖然有wp說可以用yafu分解出56個素數,至少在我電腦上的yafu是沒有成功。
所以只能上高大上的Pollard’s ρ algorithm,波拉德的ρ 演算法。
簡單說起來就是這個牛人在幾十年前發現,分解一個大整數的時候,根據一個模n的多項式生產的“偽隨機”數列,這個數列節點不斷的移動,中間不斷的去檢查gcd,gcd(xi-xj,n)如果≠1,那麼gcd的結果便是p。
反正我是沒搞懂,數學學渣,直接上指令碼吧

def gcd(a, b):
    while b:
        a, b = b, a%b
    return a
 
def mapx(x):
    x=(x*x+1)%n
    return x
 
def pollard_rho (x1,x2):
    while True:
        x1=mapx(x1)
        x2=mapx(mapx(x2))
        p=gcd(x1-x2,n)
        if (p == n):
            print "fail"
            return
        elif (p!=1):
            print("p: "+str(p))
            print("q: "+str(n/p))
            break

3.分解n

n有2092位。。。
這麼大的n肯定是有若干個素數乘積而來。
那就直接上演算法了。

#!python2
# -*- coding: utf-8 -*-
# @Time : 2020/11/4 14:20
# @Author : A.James
# @FileName: exp.py
def gcd(a, b):
    while b:
        a, b = b, a % b
    return a


def mapx(x):
    x = (x * x + 1) % n
    return x


def pollard_rho (x1,x2):
    while True:
        x1=mapx(x1)
        x2=mapx(mapx(x2))
        p=gcd(x1-x2,n)
        if (p!=1):
            #print("p: "+str(p))
            #print("q: "+str(n/p))
            return p

n = 3464115689260819392935656139231271022088014497600959975252672820761470484618617542699739764705620767566046150296286140279466041905437740736319886548924058066340624280173573039937440574809212831672936265975209972857747738693288788052694888593629820783280181774594890101819911390468376042288685444703477639361249422054925155575158181408046447773183467474182159096249846479461475003039637685547191529769071424947165685996675043741359728960138725130116665515880652680244470002603320184043266997163009799067135481330853926800023087208636366543210276325733789567957712475079676808820490428973148590780103404729397985019089646026534758042652163974037179260930147000267787012874887703048185189387666199961350969478997330352491403611551096779887936063702892671572230523920277869824082318417366635732798078805070773662305098133013800559413976855639167085996705265872418286939474978058429877355305699191892248323534097124680592084808397263288943661630283254265898940430505371463275516870915261799702701453110383723660477322192658118815861974573497885759332587457883589126213868868281682733732394640188383458580555618181208722172011645063817887462511925363883111475043389367021569982583145912277082528397480756465818166640691294267829613428532584923122279261412957652411789780285394451850006055483598427256129336822790446219260722224551892755568723667049099823707012236618539013908897459508493477299241358343681962043777720375898238069411747593247677719659288861028038609681592049271388766040068274682329498410270047730060645409396168652996740411436504098243588534151795927613112273405281530700440843961363083171583053608594479571127638861391879160062136043924515492933057094406001740725150570943724333872057035272515676895138632004436149126542560186729495087753846670118167613304943153665660470977150177815354160112481310498255965933157902965011317272734556307544837058247794721427834401390455487872367113056168812990496943458920406382650794656884209032284257748450399719067686010156664485086500184078244358783696803659745365860507822269113477617988541658390715640119076036723560146145256418191555730429

while (n != 1):
    p = pollard_rho(2, 2)
    print p
    n = n / p

4.求素數

因為計算量依然非常大,所以執行了很久。。。大神說10分鐘就得到了7個。我3個小時,得到了5個。。

740160703366837
740160703366837
740160703366837
740160703366837
740160703366837

大神得到的結果是有連續6個740160703366837,然後是更大的素數。

5.改n攻擊

740160703366837的6次方大約是90位,相比於flag來說要應該足夠了。
因為
m = c d m o d n m=c^dmodn m=cdmodn
m < n
這裡我們把740160703366837的6次方命名為n_new。
由於n_new | n,且m < n,所以

							c%n_new == pow(m ,e ,n_new)

只要新的N滿足,m<N,
m e ≡ c ( m o d N ) , 並 且 g c d ( e , p h i ( N ) ) = 1 m^e ≡ c (mod N),並且gcd(e,phi(N))=1 mec(modN)gcd(e,phi(N))=1
即可逆向求出m來。

6.指令碼

#!python3
# -*- coding: utf-8 -*-
# @Time : 2020/11/4 17:31
# @Author : A.James
# @FileName: exp-1.py.py


from gmpy2 import *
e = 0x10001
c = 1348180992713820685594359831085361247035354818267759694375727771380213764105201303900290589048476671838784929302557807429509301123621642066527762448168417430350203900517746161928291953862336621873868684964993481406952303460424386080800907869577832154132021624995347121475139439850224598911049824567475034545196149320206620924509546294914370633958171840525667753751028800452370972967842349036965813468093121305475860652163573748880159896028384459277781803606279654121781761535513864212749202340439422384362197321739535686506006254445152569135807838677803047115947240251817017395748631234023225248868640103807357800695487118067385969130665294711887439861169737031598274672286881054564295019370600398079829687943670066246766386800967129670975899437309257181151390273864539453238400821713398980792443187238155205199387468000884390778225928491109565539772444103430764411852162036780535068932010631521096301305200494731040799554079996593223419379540630567412342494359961515157700054387356888773321804429041668331430841954949061238002355270616266853430676140296078177898764114420743905073496118755793091902224563802923183897542996809393707165837427396760691616506592877656939455806776333105152244073459704842848097376929745632888315642056267589901527329593161439752243318158600747713335265681764274061086952626629147275106502354039293870614872849851780761537660716667003562253735923584765118319171207551032289722689929226947535724389015974764265109970513715649126340709399701638880824570967389428525179746112494690443526404899052482884526335312491500994658519105204100875596292743155076199283666094556235485722975240358390560161706163569618302627055238860096406627340558428533728688904747040262153892623865784320600845613247625784683300197845026108394831724602330903266980995146046956218083954561639114586880305451066793209385702886944430548686040360906088479432852330611586273784509957389880104225534635731572089138568407411433675077699382999593384336070450058824669351046095205147266720901917218217564113964074957585348227506587531149811564371155522575778721899999227020238022970334707476977210019
p = 740160703366837
n = p**6
c = c % n
phi = (p-1)*(p**6)
d = invert(e,phi)
print(hex(pow(c,d,n))[2:].decode('hex'))

7.get flag

flag{G0oDJ0b_S0_SimPle_ChaMd5}

結語

數學不好影響解題啊。。

參考

密碼學學習筆記(一)淺析Pollard’s rho algorithm及其應用