buu(前三页第二弹) RSA习题与相关知识总结
创始人
2025-05-30 03:29:13

buu [ACTF新生赛2020]crypto-rsa3 1

题目描述:

from flag import FLAG
from Cryptodome.Util.number import *
import gmpy2
import random
e=65537
p = getPrime(512)
q = int(gmpy2.next_prime§)
n = p*q
m = bytes_to_long(FLAG)
c = pow(m,e,n)
print(n)
print( c )
n = 177606504836499246970959030226871608885969321778211051080524634084516973331441644993898029573612290095853069264036530459253652875586267946877831055147546910227100566496658148381834683037366134553848011903251252726474047661274223137727688689535823533046778793131902143444408735610821167838717488859902242863683
c = 1457390378511382354771000540945361168984775052693073641682375071407490851289703070905749525830483035988737117653971428424612332020925926617395558868160380601912498299922825914229510166957910451841730028919883807634489834128830801407228447221775264711349928156290102782374379406719292116047581560530382210049

题目分析:

  • 这题已知量:n,c,e
  • 利用 分解n得p,q的在线网站 即可得到 p 与 q
  • 此时便可得到 d = gmpy2.invert(e,(p-1)*(q-1))
  • 然后便可得到明文 m = pow(c,d,n)
  • 最后在转化为字符串即可
  • 代码如下:
import gmpy2
import libnum
n = 177606504836499246970959030226871608885969321778211051080524634084516973331441644993898029573612290095853069264036530459253652875586267946877831055147546910227100566496658148381834683037366134553848011903251252726474047661274223137727688689535823533046778793131902143444408735610821167838717488859902242863683
c = 1457390378511382354771000540945361168984775052693073641682375071407490851289703070905749525830483035988737117653971428424612332020925926617395558868160380601912498299922825914229510166957910451841730028919883807634489834128830801407228447221775264711349928156290102782374379406719292116047581560530382210049
e = 65537
p = 13326909050357447643526585836833969378078147057723054701432842192988717649385731430095055622303549577233495793715580004801634268505725255565021519817179231
q = 13326909050357447643526585836833969378078147057723054701432842192988717649385731430095055622303549577233495793715580004801634268505725255565021519817179293
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(libnum.n2s(int(m)))

收获与体会:

这是很基础也很简单的一道题,但重点是要记得公式 (我一开始便有个字母记错了,然后怎么也找不到正确的答案)

buu [WUSTCTF2020]情书 1

题目描述:

在这里插入图片描述

题目分析:

  • 翻译一下可知:

前提:用0、1、2、……枚举字母表25
使用RSA系统
加密:0156 0821 1616 0041 0140 2130 1616 0793
公钥:2537和13
私钥:2537和937

  • 从提示可以得知 n = 2537 , e = 13 , d = 937
  • 分解 n ,可知 p = 43 , q = 59
  • 做过 buu RSAROLL 1 便可知道此题大致考的什么
  • 里面的 “ 0156 0821 1616 0041 0140 2130 1616 0793 ” 即是 c ,只不过是多个 c ,将解出来的明文拼接在一起便可得到 flag
  • 代码如下:
a = 'abcdefghigklmnopqrstuvwxyz'
p = 43
q = 59
e = 13
d = 937
c = '0156 0821 1616 0041 0140 2130 1616 0793'.split(' ')
flag = ''
n = p*q
for i in c:flag += a[pow(int(i),d,n)]
print(flag)
  • 得到 flag{iloveyou}

收获与体会:

  • 此题有一个特殊之处,即里面的 c , e , n 都很小,很反常!
  • 如果按 buu RSAROLL 1 这道题来写的话,得不到答案,因为打印 pow(int(i),d,n) 后会得到

8
11
14
21
4
24
14
20

一串很小的数字,对应ascii码后会得到一些 特别的东西,没有字母也没有数字

  • 所以就会想到可能是按照26个字母表进行转换,位置一一对应即可转化成功得到 flag
  • 所以数字在1~26之间就转字母便,大于26就转 ascii 码

buu [NCTF2019]babyRSA 1

题目描述:

在这里插入图片描述

题目分析:

  • 首先明确两个公式:
e*d = 1 mod (p-1)(q-1)
ed1 = e*d - 1 = k(p-1)(q-1)
  • 想要解出此题,我们必须知道n,而要知道n,我们要知道p和q的值
  • 通过 e*d 的计算,我们知道其长度为2064位,而生成p的条件为 getPrime(1024),所以(p-1)(q-1)应该为2048位

此处所说的位数长度是以Bit为单位,加一减一都不影响位数,相乘的话即为位数相加,这些性质记住就好,以下是计算代码:

from Crypto.Util.number import *
e = 65537 # 转二进 e = 0b10000000000000001,直接数得到长度为17
d = 19275778946037899718035455438175509175723911466127462154506916564101519923603308900331427601983476886255849200332374081996442976307058597390881168155862238533018621944733299208108185814179466844504468163200369996564265921022888670062554504758512453217434777820468049494313818291727050400752551716550403647148197148884408264686846693842118387217753516963449753809860354047619256787869400297858568139700396567519469825398575103885487624463424429913017729585620877168171603444111464692841379661112075123399343270610272287865200880398193573260848268633461983435015031227070217852728240847398084414687146397303110709214913
print(gmpy2.bit_length(e*d))
# 2064
p = getPrime(1024)
print(gmpy2.bit_length(p))
# 1024
print(gmpy2.bit_length(p-1))
# 1024
  • 又 ed1 = e*d - 1 = k(p-1)(q-1),2064-2048 = 16,所以k值必在 pow(2,15)至pow(2,16)之间 (想知道为什么看结尾的知识总结,此处专注解题,不深层探究)
  • 所以,我们可以利用此条件暴力求解k值,从而求出(p-1)*(q-1),间接求出 p 和 q 的值
  • 那如何间接法呢?
  • 首先我们求得了(p-1)(q-1),而p和q是两个相邻的质数,所以我们可以使用sympy库对p,q进行求解。思路为先对(p-1)(q-1)开方,再求得大于开方所得数和小于开方所得数的质数
p = sympy.prevprime(gmpy2.iroot((e*d-1)//i,2)[0])
q = sympy.nextprime(p)
  • 其中 sympy.prevprime(x)是求大于x最近的质数,sympy.nextprime(x)是求小于x最近的质数。
  • 解题代码如下:
import gmpy2
from Crypto.Util.number import long_to_bytes
import sympy
# e = 0x10001
e = 65537
d = 19275778946037899718035455438175509175723911466127462154506916564101519923603308900331427601983476886255849200332374081996442976307058597390881168155862238533018621944733299208108185814179466844504468163200369996564265921022888670062554504758512453217434777820468049494313818291727050400752551716550403647148197148884408264686846693842118387217753516963449753809860354047619256787869400297858568139700396567519469825398575103885487624463424429913017729585620877168171603444111464692841379661112075123399343270610272287865200880398193573260848268633461983435015031227070217852728240847398084414687146397303110709214913
c = 5382723168073828110696168558294206681757991149022777821127563301413483223874527233300721180839298617076705685041174247415826157096583055069337393987892262764211225227035880754417457056723909135525244957935906902665679777101130111392780237502928656225705262431431953003520093932924375902111280077255205118217436744112064069429678632923259898627997145803892753989255615273140300021040654505901442787810653626524305706316663169341797205752938755590056568986738227803487467274114398257187962140796551136220532809687606867385639367743705527511680719955380746377631156468689844150878381460560990755652899449340045313521804
p = 0
q = 0for k in range(pow(2,15),pow(2,16)):#  pow(x,y) ---> x 的 y 次方#  pow(x,y,z) ---> x 的 y 次方后,取余 zif (e*d-1)%k == 0:p = sympy.prevprime(gmpy2.iroot((e*d-1)//k,2)[0])# sympy.prevprime(x)是求大于x最近的质数# iroot(x,n) ---> x开n次根 ,返回值有两个,前一个是开方出来的整数部分,后一个是能否开出来,若能则为true,不能则为flaseq = sympy.nextprime(p)# sympy.nextprime(x)是求小于x最近的质数if (p-1)*(q-1) == (e*d-1)//k:breakn = p*q
m = pow(c,d,n)
m1 = long_to_bytes(m)
print(m1)
  • 最终得出 flag{70u2_nn47h_14_v3ry_gOO0000000d}

收获与体会:

  • 了解了一些字节的相关知识
  • 知道了函数 sympy.prevprime(x)和sympy.nextprime(x)的相关知识

sympy.prevprime(x)是求大于x最近的质数
sympy.nextprime(x)是求小于x最近的质数

  • 回顾了iroot(x,n) 和 pow(x,y) 的相关知识

iroot(x,n) —> x开n次根,返回值有两个,前一个是开方出来的整数部分,后一个是能否开出来,若能则为true,不能则为flase
pow(x,y) —> x 的 y 次方
pow(x,y,z) —> x 的 y 次方后,取余 z

buu [RoarCTF2019]babyRSA 1

题目描述:

import sympy
import randomdef myGetPrime():A= getPrime(513)print(A)B=A-random.randint(1e3,1e5)print(B)return sympy.nextPrime((B!)%A)
p=myGetPrime()
#A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
#B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596q=myGetPrime()
#A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
#B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026r=myGetPrime()n=p*q*r
#n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
c=pow(flag,e,n)
#e=0x1001
#c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
#so,what is the flag?

题目分析:

  • 首先我们先看到 n = p * q * r (n 分解成了三个素数) ,而 e,c 都知道,所以要求明文 m = pow(c,d,n) 先要求出 d 来
  • 而 d = gmpy2.invert(e,phi)
  • 其中欧拉函数 phi = (p-1) * (q-1) * (r-1)
  • 所以要求 d ,那么要求出 p 与 q
  • 代码中 p = myGetPrime() = sympy.nextPrime((B!)%A)

sympy.nextprime(x) 是求小于x最近的质数

  • 所以最终要求 (B!)%A,即B的阶乘模A,其中 A,B 都知道,那么B!(B的阶乘)怎么求呢?
  • 有一个定理可以解决这个问题,即 威尔逊定理

威尔逊定理

当且仅当p为素数时:( p -1 ) ! ≡ -1 ( mod p ) —> (p-1) ! +1=0 (mod p)

  • A = getPrime(513),可知A为素数,又 B=A-random.randint(1e3,1e5),通过威尔逊定理,可知(A-1) ! +1≡0 (mod A),故B!(B+1)(B+2)…(A-1) ≡ -1 (mod A),即B ! * C = ≡ -1 ( mod A ),其中C = (A - 1)! / (B) !,也就是B之后的数字之积
    两边同时乘上C的逆元C1(C * C1 = 1),B ! = -1 * C1(mod A1)
  • B ! 求出来了,那么 p = myGetPrime() = sympy.nextPrime((B!)%A) 也就求出来了
  • 如此,p,q 都求出来了,r = n // (p * q) ,自此p,q,r,都求出来了,最终flag也就出来了
  • 代码如下:
import libnum
import sympy
import gmpy2A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
# e=0x1001,转十进制
e = 4097
c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
def mydecryp(A,B):C1 = 1temp = pow(-1,1,A) # temp=-1 mod Afor i in range(B+1,A):C1 = (C1*gmpy2.invert(i,A))%A # C1是从B+1~A中每个数对A的逆元的乘积return sympy.nextprime((C1*temp)%A) # (C1*temp) = B!, (C1*temp)%A = (B!)%Ap = mydecryp(A1,B1)
q = mydecryp(A2,B2)
r = n//p//q
phi = (p-1)*(q-1)*(r-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(libnum.n2s(int(m)))
  • 最终flag{wm-CongrAtu1ation4-1t4-ju4t-A-bAby-R4A}

收获与体会:

  • 知道了如何利用代码求阶乘
  • 又了解了一种RSA题型

buu [RoarCTF2019]RSA 1

题目描述:

A=(((y%x)**5)%(x%y))**2019+y**316+(y+1)/x
p=next_prime(z*x*y)
q=next_prime(z)
A =  2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
n =  117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c =  41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128

题目分析:

  • 这题看了大佬的,知道了两种不同的解题方法
  • 第一种是契合题目所给字母,先通过爆破求出x,y,但奇怪的是我用pycharm重写了一遍他们的代码,都出现了报错:在这里插入图片描述在这里插入图片描述
  • 上面两种一个是报错,一个是直接结束程序,反正都求不出x,y(我也求不出)
  • 所以尝试了另外一种方法:直接爆破求e,(p,q可以通过n分解得到),所以字母都求出来了,那么最后答案也就差不多了,代码如下:
from Crypto.Util.number import *
A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128
p = 842868045681390934539739959201847552284980179958879667933078453950968566151662147267006293571765463137270594151138695778986165111380428806545593588078365331313084230014618714412959584843421586674162688321942889369912392031882620994944241987153078156389470370195514285850736541078623854327959382156753458569
q = 139916095583110895133596833227506693679306709873174024876891023355860781981175916446323044732913066880786918629089023499311703408489151181886568535621008644997971982182426706592551291084007983387911006261442519635405457077292515085160744169867410973960652081452455371451222265819051559818441257438021073941183for i in range(2,100000): # 此时的i即为eif isPrime(i): # 判断i是否为素数try:d = gmpy2.invert(i,(p-1)*(q-1))m = pow(c,d,n)flag = libnum.n2s(int(m)) # 此时 type(flag) = ,所以下面要转字符串,一开始没转字符串报错,所以才会想到这里if 'CTF' in str(flag) or 'flag' in str(flag):print(flag,'\n',i)except ZeroDivisionError:continue
  • 最终得到flag{wm-l1l1ll1l1l1l111ll},e = 65537

收获与体会:

  • 真是巧了,e = 65537
  • 所以如果以后要求e来求flag的,我们可以先大胆令e = 65537来试一下,没准就瞎猫碰上死耗子,答案就出来了,省时还省力(但遇上这种题的可能性确实挺小的)
  • 为什么会把e的范围定在1~100000之间?题做多了便知大部分的e的值都处于此范围内。(不排除有特殊情况,到时候有特殊情况再说吧)

buu [MRCTF2020]babyRSA 1

题目描述:

import sympy
import random
from gmpy2 import gcd, invert
from Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytes
from z3 import *
flag = b"MRCTF{xxxx}"
base = 65537def GCD(A):B = 1for i in range(1, len(A)):B = gcd(A[i-1], A[i])return Bdef gen_p():P = [0 for i in range(17)]P[0] = getPrime(128)for i in range(1, 17):P[i] = sympy.nextprime(P[i-1])print("P_p :", P[9])n = 1for i in range(17):n *= P[i]p = getPrime(1024)factor = pow(p, base, n)print("P_factor :", factor)return sympy.nextprime(p)def gen_q():sub_Q = getPrime(1024)Q_1 = getPrime(1024)Q_2 = getPrime(1024)Q = sub_Q ** Q_2 % Q_1print("Q_1: ", Q_1)print("Q_2: ", Q_2)print("sub_Q: ", sub_Q)return sympy.nextprime(Q)if __name__ == "__main__":_E = base_P = gen_p()_Q = gen_q()assert (gcd(_E, (_P - 1) * (_Q - 1)) == 1)_M = bytes_to_long(flag)_C = pow(_M, _E, _P * _Q)print("Ciphertext = ", _C)
'''
P_p : 206027926847308612719677572554991143421
P_factor : 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1:  103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2:  151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q:  168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
Ciphertext =  1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832

题目分析:

  • 首先我们分析代码,代码可以说分为3个模块,第一个模块(GCD模块)个人觉得这里不需要看,后面解题并没有用它,重点是下面两模块,即gen_p和gen_q模块(生成p和生成q模块)
  • 生成q模块还好说:
def gen_q():sub_Q = getPrime(1024)Q_1 = getPrime(1024)Q_2 = getPrime(1024)Q = sub_Q ** Q_2 % Q_1return sympy.nextprime(p)
 其中Q = sympy.nextprime(pow(sub_Q,Q_2,Q_1)),而sub_Q , Q_2 , Q_1都为已知数,那么Q便求出来了
  • 重点是生成p模块,我们先来看生成p的过程:先生成P,P里面有17个质数,且每一个质数之间都有关系
def gen_p():P = [0 for i in range(17)]P[0] = getPrime(128)for i in range(1, 17):P[i] = sympy.nextprime(P[i-1])print("P_p :", P[9])n = 1for i in range(17):n *= P[i]p = getPrime(1024)factor = pow(p, base, n)print("P_factor :", factor)return sympy.nextprime(p)

做此题 必备知识
sympy.prevprime(x)是求大于x最近的质数
sympy.nextprime(x)是求小于x最近的质数

  • 由必备知识可知P中有17个质数,后一个数是大于前一个数最近的质数,并且具有唯一性,这16个质数相乘得到n,然后通过factor = pow(p,base,n)求得factor , (其中base即为e = 65537)。这是一个典型的欧拉函数,我们需要求出的便是这17个(P[i]-1)的乘积,其中P[9]是已知的,然而我在上面也说了,每个质数之间都是相联系的,且每个质数都是唯一的,所以知道其中一个,那么其他的都能知道,然后通过invert求出d1,之后求出p 。以下是求解p的代码:
P = [0 for i in range(17)]
P[9] = 206027926847308612719677572554991143421
for i in range(9,0,-1): # 9 8 7 6 5 4 3 2 1P[i-1] = sympy.prevprime(P[i])
for i in range(9,16):P[i+1] = sympy.nextprime(P[i]) # i = 16 时,i+1=17
n = 1
phi_n = 1
for i in range(17):n *= P[i]phi_n *= (P[i]-1)
d1 = gmpy2.invert(base,phi_n)
p = sympy.nextprime(pow(P_factor,d1,n))
  • 完整代码如下:
import libnum
import sympy
import gmpy2
base = 65537
P_p = 206027926847308612719677572554991143421
P_factor = 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1 = 103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2 = 151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q = 168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
c = 1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832P = [0 for i in range(17)]
P[9] = 206027926847308612719677572554991143421
for i in range(9,0,-1): # 9 8 7 6 5 4 3 2 1P[i-1] = sympy.prevprime(P[i])
for i in range(9,16):P[i+1] = sympy.nextprime(P[i]) # i = 16 时,i+1=17
n = 1
phi_n = 1
for i in range(17):n *= P[i]phi_n *= (P[i]-1)
d1 = gmpy2.invert(base,phi_n)
p = sympy.nextprime(pow(P_factor,d1,n))
q = sympy.nextprime(pow(sub_Q,Q_2,Q_1))
phi = (p-1)*(q-1)
n = p * q
d = gmpy2.invert(base,phi)
m = pow(c,d,n)
print(libnum.n2s(int(m)))
  • 最后得到flag{sti11_@_b@by_qu3st10n}

题目描述:

import hashlib
import sympy
from Crypto.Util.number import *flag = 'GWHT{******}'
secret = '******'assert(len(flag) == 38)half = len(flag) / 2flag1 = flag[:half]
flag2 = flag[half:]secret_num = getPrime(1024) * bytes_to_long(secret)p = sympy.nextprime(secret_num)
q = sympy.nextprime(p)N = p * qe = 0x10001F1 = bytes_to_long(flag1)
F2 = bytes_to_long(flag2)c1 = F1 + F2
c2 = pow(F1, 3) + pow(F2, 3)
assert(c2 < N)m1 = pow(c1, e, N)
m2 = pow(c2, e, N)output = open('secret', 'w')
output.write('N=' + str(N) + '\n')
output.write('m1=' + str(m1) + '\n')
output.write('m2=' + str(m2) + '\n')
output.close()
N=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163
m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239
m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546

题目分析:

对代码进行分析可得大致加密过程为:

  • 首先给了字符串明文flag和secret,然后对flag对半切得到flag1和flag2
  • 随机生成一个1024位(2进制)的素数,并将secret(字符串)类型转化为整数类型,然后将这两个结果相乘得到secret_num

拓展:
bytes_to_long(x) —> 字节转整数 (会将字节x转化为它的ascii码)
long_to_bytes(x) —> 整数转字节
在这里插入图片描述

  • 取secret_num的下一个素数作为p,取p的下一个素数作为q,得到N=p*q

必备知识:
sympy.prevprime(x)是求大于x最近的质数
sympy.nextprime(x)是求小于x最近的质数

  • 将flag1和flag2通过bytes_to_long转化为整数得到F1和F2
  • 将F1,F2设计成方程组得到c1,c2,进一步加密得到m1,m2
  • 最后给出运行结果得到 N,m1,m2

decrypt(解密)

  • 题中给出了N,通过以上分析可以得知p,q是两个相邻的素数,所以对N进行开方运算(iroot(N,2))后可以得到一个值x,并且pq
  • 通过sympy.prevprime(x),sympy.nextprime(x) 函数可以得到p,q,从而可以求得d
  • 然后进行RSA解密得出c1和c2

c1 = pow(m1,d,N)
c2 = pow(m2,d,N)

  • 至此,我们得到一个方程组:

c1=F1+F2
c2=F13+F23

  • 利用sympy库进行方程组求解:
from sympy import *
F1 = Symbol('F1')
F2 = Symbol('F2')
F1,F2 = solve([F1+F2-c1,(F1)**3+(F2)**3-c2])
print(F1,F2)

得到:

{F1: 1141553212031156130619789508463772513350070909, F2: 1590956290598033029862556611630426044507841845},
{F1: 1590956290598033029862556611630426044507841845, F2: 1141553212031156130619789508463772513350070909} 
  • 得到两组解,但仔细看只是调换的位置而已,两组都试一下,便可得到最终flag
  • 完整代码:
N=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163
m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239
m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546
e = 65537
import gmpy2
import libnum
import sympy.crypto.crypto
x = gmpy2.iroot(N,2)[0]
p = sympy.nextprime(x)
q = N//p
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
# m1 = pow(c1, e, N)
# m2 = pow(c2, e, N)
c1 = pow(m1,d,N)
c2 = pow(m2,d,N)
from sympy import *
F1 = Symbol('F1')
F2 = Symbol('F2')
print(solve([F1+F2-c1,(F1)**3+(F2)**3-c2]),F1,F2)
F1,F2 = solve([F1+F2-c1,(F1)**3+(F2)**3-c2])
F2 = 1141553212031156130619789508463772513350070909
F1 = 1590956290598033029862556611630426044507841845
print(libnum.n2s(int(F1))+libnum.n2s(int(F2)))
  • 最后得到flag{f709e0e2cfe7e530ca8972959a1033b2}

buu [GUET-CTF2019]BabyRSA 1

题目描述:

p+q : 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
(p+1)(q+1) : 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
e : 0xe6b1bee47bd63f615c7d0a43c529d219
d : 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5
enc_flag : 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a

题目分析:

  • 知道了(p+1)(q+1)与p+q,那么n = p*q便可以知道了,n = (p+1)(q+1) - (p+q) - 1
  • enc_flag便是密文c
  • 所以明文m = pow(c,d,n) 便求出来了
  • 代码如下:
import libnum
a = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
b = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
e = 0xe6b1bee47bd63f615c7d0a43c529d219
d = 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5
enc_flag = 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a
n = b - a - 1
m = pow(enc_flag,d,n)
print(libnum.n2s(m))
  • 得到flag{cc7490e-78ab-11e9-b422-8ba97e5da1fd}

以上知识总结:

1.

当出现多个c(并没有多个n)则想到拼接法。若每个c相对偏小,那么就意味着求出的m相对偏小,若m <= 26 则想到对应26个字母表,若m > 26,则直接 flag += chr(m)

2.

sympy.prevprime(x)是求大于x最近的质数
sympy.nextprime(x)是求小于x最近的质数

3.

我们经常会遇到:

p = getPrime(1024)
q = getPrime(1024)

指的是获得1024长度(2进制)的素数p,q

此处所说的长度是以Bit为单位(二进制形式),加一减一都不影响位数,相乘的话即为位数相加,这些性质记住就行(数字逻辑第一章有此知识),以下是举例:

from Crypto.Util.number import *
e = 0x10001 # 转二进 e = 0b10000000000000001,直接数得到长度为17
d = 19275778946037899718035455438175509175723911466127462154506916564101519923603308900331427601983476886255849200332374081996442976307058597390881168155862238533018621944733299208108185814179466844504468163200369996564265921022888670062554504758512453217434777820468049494313818291727050400752551716550403647148197148884408264686846693842118387217753516963449753809860354047619256787869400297858568139700396567519469825398575103885487624463424429913017729585620877168171603444111464692841379661112075123399343270610272287865200880398193573260848268633461983435015031227070217852728240847398084414687146397303110709214913
print(gmpy2.bit_length(e*d))
# 2064
p = getPrime(1024)
print(gmpy2.bit_length(p))
# 1024
print(gmpy2.bit_length(p-1))
# 1024

留个小问题:pow(2,15)至pow(2,16)中的数 位数长度是多少?
解答:问的是处于 2^15 ~ 2^16 中的数的位数长度为多少,想要算位数长度,那么便要将数转为2进制形式,这里就要用到数字逻辑中学到的知识了(这些知识记住即可,方便下次做题):

2^15 转2进制即 1 后面加15个0
2^15 = 1000000000000000 ————>长度为16
同理 2^16 转2进制即 1 后面加16个0
2^16 = 10000000000000000 ————>长度为17
所以处于 2^15 ~ 2^16 中的数的位数长度为 16

4.

若:

p = sympy.nextprime(a_num) # 其中 a_num 未知
q = sympy.nextprime(p)
n = p * q 

n 已知,求 p,q
由代码可知,p,q 是相邻的两个素数,那么直接对 n 开方,求开方得到的数的整数部分,然后对该整数求上一个素数和下一个素数,即可得到 p,q 。如:

x = gmpy2.iroot(n,2)[0]
p = sympy.nextprime(x)
q = N//p

5.

bytes_to_long(x) 与 long_to_bytes(x) 相关知识:

bytes_to_long(x) —> 字节转整数 (会将字节x转化为它的ascii码)
long_to_bytes(x) —> 整数转字节
在这里插入图片描述

相关内容

热门资讯

在职的我竟然一次通过了注册测绘... 先上一波成绩吧!首先说一下我是万万没想到案例能过的😅,本...
Python:Pandas对象... 这里仅以DataFrame为例进行说明。 Pandas版本:1.5.3 1 问题描述...
【pytorch源码剖析系列】... 前言:本次内容不只是让你学会如何快速搭建网络骨架,还要深入理解pytor...
基于javaSpringboo... 基于javaSpringboot+mybatis+layui的装修验收管理系统设计和...
【Dockerfile相关问题... 文章目录Docker容器的作用docker安全性原则和docker最小化镜像大小原则docker镜像...
windows版的nacos下... 下载 csdn:https://download.csdn.net/download/...
【Git】 参考教程 Git官方文档廖雪峰的Git教程 Git作用 Git简介 Git诞生史 集中式VS分布式 ...
[iOS]ARC再学 文章目录@[TOC](文章目录)前言概念内存管理/引用计数概要内存管理的思考方式自己生成的对...
Android studio2... [软件名称]: Android studio2022 [软件大小]: 1.00 GB [安装环境]:...
表格的进阶 系列文章目录 前端系列文章——传送门 HTML系列文章——传送门 文章目录系列文章目录html 结...
Vivado device窗口... 目录 一、前言 二、时钟site介绍 三、时钟site分布 四、时钟site驱动逻辑 一、前言 ...
数模笔记——论文写作 论文写作 各模块写作要点 数学建模论文的重要性 数学建模论文的写作是数学建模中重要的一个环节。数学建...
IDEA打印项目执行最终执行s... 一、下载插件1、MyBatis Log Plugin随着IDEA 升级到 2020.2 版本之后开始...
Harmony(鸿蒙)开发手机... Harmony环境使用Bee入门向导 一、添加jar包 将bee相关的3个jar包复制到entry包...
到底线程要怎么去编程?线程类有... 上篇文章我们介绍了到底什么是线程,线程与进程的区别,线程怎么去创建的五种...
linux环境下利用rsync... 文章目录前言插曲根据时间段同步按时间过滤文件使用 mtime 参数查找使用 newermt 进行更精...
学习周报3.19 文章目录前言文献阅读摘要简介问题定义方法结论克里金插值法(Kriging法࿰...
Java设计模式 03-原型模... 原型模式 一、克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为࿱...
数据库select操作 插入数据时,一次插入多条数据,比多次插入多条同样的数据消耗时间少很多。 ...
搭建 Spring 源码阅读环... 1、下载gradle https://gradle.org/releases/ 解压到磁盘 2、配...
北斗星1.4排量百公里油耗(北... 本篇文章极速百科给大家谈谈北斗星1.4排量百公里油耗,以及北斗星14真实油耗72什么情况对应的知识点...
汽车安全性能排行榜(车辆安全性... 本篇文章极速百科给大家谈谈汽车安全性能排行榜,以及车辆安全性能排名对应的知识点,希望对各位有所帮助,...
门客是什么意思(君子不打上门客... 今天给各位分享门客是什么意思的知识,其中也会对君子不打上门客是什么意思进行解释,如果能碰巧解决你现在...
灶糖是啥(灶糖的功效和作用) ... 本篇文章极速百科给大家谈谈灶糖是啥,以及灶糖的功效和作用对应的知识点,希望对各位有所帮助,不要忘了收...
[CMake] CMake 进... CMake 进阶 代码生成 代码生成是指使用一些通用的描述文件,可以自动生成源代码&#...
文法的形式定义 一、序列的集合称为形式语言序列的集合称为形式语言二、形式语言的描述当语言是有穷集合时,...
人事部是干什么的(人力资源管理... 今天给各位分享人事部是干什么的的知识,其中也会对人力资源管理吃香吗进行解释,如果能碰巧解决你现在面临...
透明的反义词是什么(透明的反义... 本篇文章极速百科给大家谈谈透明的反义词是什么,以及透明的反义词是什么最佳答案对应的知识点,希望对各位...
清道夫鱼能吃吗(清道夫鱼能吃吗... 今天给各位分享清道夫鱼能吃吗的知识,其中也会对清道夫鱼能吃吗?有什么功效进行解释,如果能碰巧解决你现...
科研之友是什么(科研之友是干什... 本篇文章极速百科给大家谈谈科研之友是什么,以及科研之友是干什么的对应的知识点,希望对各位有所帮助,不...