RSA wp

密钥的产生

(1)选两个保密的大素数p和q;

(2)计算n=p*q\varphi \left ( n \right )=(p-1)(q-1),其中\varphi (n)是n的欧拉函数值,欧拉函数:小于n的正整数中与n互质的数的个数

当n=6,\varphi (n)=2;当n=7,\varphi (n)=6;即当n为质数,欧拉函数值=n-1;

(3)选一整数,满足1<e<\varphi (n),且gcd(\varphi (n),e)=1(互质);

(4)计算e对于\varphi (n)的模反元素d

一.共模攻击

from gmpy2 import *
from Crypto.Util.number import *


flag  = '***************'

p = getPrime(512)
q = getPrime(512)
m1 = bytes_to_long(bytes(flag.encode()))


n = p*q
e1 = getPrime(32)
e2 = getPrime(32)
print()

flag1 = pow(m1,e1,n)
flag2 = pow(m1,e2,n)
print('flag1= '+str(flag1))
print('flag2= '+str(flag2))
print('e1= ' +str(e1))
print('e2= '+str(e2))
print('n= '+str(n))


#flag1= 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
#flag2= 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
#e1= 3247473589
#e2= 3698409173
#n= 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313

在 RSA 加密算法里,假设使用两个不同的公钥指数 e1和 e2 对同一明文 m 进行加密,模数均为 n,那么会得到两个密文 c1 和 c2,

共模攻击是在 RSA 加密中,当两个不同的公钥指数 e1 和 e2 对同一明文 m 进行加密,且使用相同的模数 n 时,可以利用数学方法恢复出明文 m

扩展欧几里得算法(Extended Euclidean algorithm)是欧几里得算法(辗转相除法)的扩展,用于计算两个整数a和b的最大公约数d,同时还能找到整数x和y,使得ax+by=d。

在 RSA 共模攻击等场景中,计算两个公钥指数e1和e2的扩展欧几里得系数是很重要的步骤。扩展欧几里得算法可以帮助我们找到整数s1和s2,使得s1*e1+s2*e2=gcd(e1,e2)。当e1和e2互质时gcd(e1,e2)=1即s1*e1+s2*e2=1。

from Crypto.Util.number import *
import gmpy2

# 共模攻击函数
def attack(n, e1, e2, c1, c2):
    # 计算 e1 和 e2 的扩展欧几里得系数
    g, s1, s2 = gmpy2.gcdext(e1, e2)
    if g != 1:
        raise ValueError("e1 和 e2 不互质,无法进行共模攻击")
    if s1 < 0:
        s1 = -s1
        c1 = gmpy2.invert(c1, n)
    if s2 < 0:
        s2 = -s2
        c2 = gmpy2.invert(c2, n)
    # 计算明文 m
    m = pow(c1, s1, n) * pow(c2, s2, n) % n     #幂取模运算:c1的s1次幂对n取余
    return int(m)

flag1 = 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
flag2 = 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
e1 = 3247473589
e2 = 3698409173
n = 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313

# 调用共模攻击函数
m = attack(n, e1, e2, flag1, flag2)
print(long_to_bytes(m))

二.

from Cryptodome.Util.number import *
from flag import *

n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n1)
c = pow(c, e, n2)

print("c = %d" % c)

# output
# c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264

主要思路是利用两个 RSA 模数 n1 和 n2 存在相同素因子 p 的特点,通过计算最大公约数 GCD(n1, n2) 得到公因子 p,进而计算出各自的私钥指数 d1 和 d2,最后完成解密

from Crypto.Util.number import long_to_bytes, bytes_to_long, GCD

# 给定的密文和模数
c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264
n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537

# 计算两个模数的最大公约数,得到共享的素因子 p
p = GCD(n1, n2)
# 计算 n1 对应的另一个素因子 q1
q1 = n1 // p
# 计算 n2 对应的另一个素因子 q2
q2 = n2 // p
# 验证 p 和 q1 的乘积是否等于 n1
assert p * q1 == n1
# 验证 p 和 q2 的乘积是否等于 n2
assert p * q2 == n2

# 计算 n1 的欧拉函数值 phi1
phi1 = (p - 1) * (q1 - 1)
# 计算 e 模 phi1 的乘法逆元 d1
d1 = pow(e, -1, phi1)
# 使用私钥指数 d1 对密文 c 进行解密,得到明文 m
m = pow(c, d1, n1)
# 将解密得到的整数明文转换为字节串并打印
print(long_to_bytes(m))

三.认识RSA

from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
e = 65537
n = p*q
c = pow(m,e,n)
print(f'p = {p}')
print(f'q = {q}')
print(f'c = {c}')
'''
p = 12567387145159119014524309071236701639759988903138784984758783651292440613056150667165602473478042486784826835732833001151645545259394365039352263846276073
q = 12716692565364681652614824033831497167911028027478195947187437474380470205859949692107216740030921664273595734808349540612759651241456765149114895216695451
c = 108691165922055382844520116328228845767222921196922506468663428855093343772017986225285637996980678749662049989519029385165514816621011058462841314243727826941569954125384522233795629521155389745713798246071907492365062512521474965012924607857440577856404307124237116387085337087671914959900909379028727767057
'''
import gmpy2
from Crypto.Util.number import long_to_bytes

e=65537
p = 12567387145159119014524309071236701639759988903138784984758783651292440613056150667165602473478042486784826835732833001151645545259394365039352263846276073
q = 12716692565364681652614824033831497167911028027478195947187437474380470205859949692107216740030921664273595734808349540612759651241456765149114895216695451
c = 108691165922055382844520116328228845767222921196922506468663428855093343772017986225285637996980678749662049989519029385165514816621011058462841314243727826941569954125384522233795629521155389745713798246071907492365062512521474965012924607857440577856404307124237116387085337087671914959900909379028727767057
n=p*q
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

四.变相求解p,q

('c=', '0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9eL')
('e=', '0x872a335')
#q + q*p^3 =1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586
#qp + q *p^2 = 1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594

from Crypto.Util.number import *
c=0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9e
e=0x872a335
#q + qp^3=q(1p^3)=q(1+p)(p^2-q+1)=hint1
hint1=1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586
#qp + qp^2 =qp(1+p)=hint2
hint2=1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594
t=GCD(hint1,hint2)//最大公约数

p=hint2//t
q=t//(p+1)
n=p*q
phi=(p-1)*(q-1)
d=inverse(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

1. 提示信息的数学表达式

在 RSA 加密算法的这个特殊情境下,我们已知两个提示信息:

  • hint1 = q + q * p^3 = q(1 + p)(p^2 - p + 1)
  • hint2 = qp + q * p^2 = q * p*(p + 1)

可以看到,hint1 和 hint2 这两个表达式存在公因式 q(p + 1)

2. 最大公约数的作用

t = GCD(hint1, hint2)

通过计算 hint1 和 hint2 的最大公约数,我们能够提取出它们的公因式。因为最大公约数的定义就是能同时整除两个数的最大正整数,在这种情况下,GCD(hint1, hint2) 会得到 q(p + 1),也就是 t = q(p + 1)

3. 基于最大公约数求解素数

求解素数 p
p = hint2 // t

由于 hint2 = q * p*(p + 1),而 t = q(p + 1),那么 hint2 除以 t 时,公因式 q(p + 1) 会被消去,从而得到素数 p。即 hint2 // t = (q * p*(p + 1)) // (q(p + 1)) = p

求解素数 q
q = t // (p + 1)

已经得到 t = q(p + 1),那么 t 除以 (p + 1) 就可以得到素数 q,即 t // (p + 1) = q(p + 1) // (p + 1) = q

五.认识rsa

p=0x928fb6aa9d813b6c3270131818a7c54edb18e3806942b88670106c1821e0326364194a8c49392849432b37632f0abe3f3c52e909b939c91c50e41a7b8cd00c67d6743b4f

q=0xec301417ccdffa679a8dcc4027dd0d75baf9d441625ed8930472165717f4732884c33f25d4ee6a6c9ae6c44aedad039b0b72cf42cab7f80d32b74061

e=0x10001

c=0x70c9133e1647e95c3cb99bd998a9028b5bf492929725a9e8e6d2e277fa0f37205580b196e5f121a2e83bc80a8204c99f5036a07c8cf6f96c420369b4161d2654a7eccbdaf583204b645e137b3bd15c5ce865298416fd5831cba0d947113ed5be5426b708b89451934d11f9aed9085b48b729449e461ff0863552149b965ax

将p,q,e转换成十进制的数字

from Crypto.Util.number import *
from gmpy2 import *

p = 0x928fb6aa9d813b6c3270131818a7c54edb18e3806942b88670106c1821e0326364194a8c49392849432b37632f0abe3f3c52e909b939c91c50e41a7b8cd00c67d6743b4f

q = 0xec301417ccdffa679a8dcc4027dd0d75baf9d441625ed8930472165717f4732884c33f25d4ee6a6c9ae6c44aedad039b0b72cf42cab7f80d32b74061

e = 0x10001
p = int(p)
q = int(q)
e = int(e)
n = p * q
c = 0x70c9133e1647e95c3cb99bd998a9028b5bf492929725a9e8e6d2e277fa0f37205580b196e5f121a2e83bc80a8204c99f5036a07c8cf6f96c420369b4161d2654a7eccbdaf583204b645e137b3bd15c5ce865298416fd5831cba0d947113ed5be5426b708b89451934d11f9aed9085b48b729449e461ff0863552149b965e22b6
c = int(c)
#计算欧拉函数值
phi = (p - 1) * (q - 1)
#计算私钥指数 d:使用 invert 函数计算 e 模 phi 的乘法逆元 d。
d = invert(e, phi)
m = powmod(c, d, n)
print(long_to_bytes(m))

六.小明文加密

flag= 25166751653530941364839663846806543387720865339263370907985655775152187319464715737116599171477207047430065345882626259880756839094179627032623895330242655333
n= 134109481482703713214838023035418052567000870587160796935708584694132507394211363652420160931185332280406437290210512090663977634730864032370977407179731940068634536079284528020739988665713200815021342700369922518406968356455736393738946128013973643235228327971170711979683931964854563904980669850660628561419

 题目只有flag和n,试试低加密指数,小明文e的范围只有1-3,不断递增 e 的值,直至 flag 能够被 e 次开方得到一个整数结果,最后将开方结果转换为字节串并输出。

from Crypto.Util.number import *
from gmpy2 import *
flag= 25166751653530941364839663846806543387720865339263370907985655775152187319464715737116599171477207047430065345882626259880756839094179627032623895330242655333
n= 134109481482703713214838023035418052567000870587160796935708584694132507394211363652420160931185332280406437290210512090663977634730864032370977407179731940068634536079284528020739988665713200815021342700369922518406968356455736393738946128013973643235228327971170711979683931964854563904980669850660628561419
e=2

while iroot(flag,e)[1]==0:
    e=e+1
print(long_to_bytes(iroot(flag,e)[0]))
#小明文爆破出e的值

七.factordb素数分解

from Crypto.Util.number import *

flag = b'NSSCTF{******}'

p = getPrime(256)
q = getPrime(256)
n = p*q
e = 65537
phi = (p-1)*(q-1)

m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

'''
n = 7382582015733895208810490097582153009797420348201515356767397357174775587237553842395468027650317457503579404097373070312978350435795210286224491315941881
e = 65537
c = 6511001389892474870028836129813814173158254564777610289284056550272120510686249909340499673868720839756059423749304765055919251717618117507007046973023557
'''

已知n,求解p,q,可以使用yafu进行分解,一种是使用在线网站factordb进行分解,后者更快一些,factordb网址:factordb.com

import gmpy2
from Crypto.Util.number import long_to_bytes

e = 65537
p = 104660876276442216612517835199819767034152013287345576481899196023866133215633
q = 70538125404512947763739093348083497980212021962975762144416432920656660487657
c = 6511001389892474870028836129813814173158254564777610289284056550272120510686249909340499673868720839756059423749304765055919251717618117507007046973023557
n=p*q
phi=(p-1)*(q-1)#计算欧拉函数值
d=gmpy2.invert(e,phi)#该语句的主要功能是计算整数 e 在模 phi 意义下的乘法逆元,并将结果赋值给变量 d。在数论中,对于整数 e 和正整数 phi,如果存在整数 d 使得 (e * d) % phi == 1,那么就称 d 是 e 模 phi 的乘法逆元。
m=pow(c,d,n)#计算 c 的 d 次幂对 n 取模的结果
print(long_to_bytes(m))

八.相邻素数分解

from Crypto.Util.number import *
import gmpy2
flag = b'NSSCTF{******}'




p = getPrime(512)
q = gmpy2.next_prime(p)


n = p*q
e = 65537
phi = (p-1)*(q-1)

m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

'''
n = 115637000420176820831322601039129424406844427046456738651883381559357542765613732363445112111006849040385859313572091386802534464534403117787314180179562651607533039692795522388596550968316951090748054495960090527479954143448774136390568881020918710834542819900918984139672802889774720153267841255456602500057
e = 65537
c = 98161406745910866780822530171878255235776133393411573803496865047700715941955255328757920065032397556905095591171977170479344602512244671081108703687450560269408412671849929423399172588599903975793985819498354819305128607934552101433664794909855378636055525016664559476808490723554481335856183927702549281730
'''

1.素数分解范围确定

由于 p 和 q 是相邻的素数且 n = p * q,那么 p 和 q 应该比较接近\sqrt{n}。所以可以从\sqrt{n} 附近开始寻找可能的素数。

2.素数判断

需要一个函数来判断一个数是否为素数。

3.寻找相邻素数对

从 \sqrt{n}附近开始,分别向两边寻找素数,然后检查它们的乘积是否等于 n

import gmpy2
import sympy

from Crypto.Util.number import *
import binascii

n = 115637000420176820831322601039129424406844427046456738651883381559357542765613732363445112111006849040385859313572091386802534464534403117787314180179562651607533039692795522388596550968316951090748054495960090527479954143448774136390568881020918710834542819900918984139672802889774720153267841255456602500057
x = gmpy2.iroot(n, 2)[0]  # 取第0个元素,也就是第一个元素

p = sympy.nextprime(x)
q = n // p
e = 65537
d = gmpy2.invert(e, (p - 1) * (q - 1))//e对于phi(n)的模反元素d
print(p)
print(q)
print(d)
c = 98161406745910866780822530171878255235776133393411573803496865047700715941955255328757920065032397556905095591171977170479344602512244671081108703687450560269408412671849929423399172588599903975793985819498354819305128607934552101433664794909855378636055525016664559476808490723554481335856183927702549281730
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))

4.解释代码:x = gmpy2.iroot(n, 2)[0] 

1.gmpy2.iroot函数用于计算一个数的整数根。它的语法如下:

gmpy2.iroot(x, n)
  • 参数
    • x:要计算根的数,通常为一个大整数。
    • n:要计算的根的次数,是一个正整数。

2. gmpy2.iroot 函数的返回值

gmpy2.iroot(x, n) 函数会返回一个包含两个元素的元组,格式如下:

(root, is_exact)
  • root:是计算所得的整数根(向下取整)。也就是说,它是小于等于 x 的 n 次根的最大整数。
  • is_exact:是一个布尔类型的值,用来表明计算出的根是否精确。若 root 的 n 次幂恰好等于 x,则 is_exact 为 True;反之则为 False。

3. [0] 的作用

在 Python 中,元组和列表等序列类型的数据,可以通过方括号 [] 加索引值来访问其中的元素,索引是从 0 开始计数的。所以 [0] 表示取元组里的第一个元素。

在代码 x = gmpy2.iroot(n, 2)[0] 中,使用 [0] 就是要从 gmpy2.iroot(n, 2) 返回的元组里提取出整数根 root,并将其赋值给变量 x。而返回元组里的第二个元素 is_exact 则被忽略了。

 九、多/非素数

from Crypto.Util.number import *

flag = b'NSSCTF{******}' + b'1'*100

p = getPrime(256)
q = getPrime(256)
n = (p**3) * q
e = 65537
phi = (p-1)*(q-1)

m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'p = {p}')
print(f'q = {q}')
print(f'e = {e}')
print(f'c = {c}')

'''
p = 80505091208742938705306670241621545375764148093711243653439069254008824979403
q = 67599990875658931406915486208971556223245451500927259766683936131876689508521
e = 65537
c = 7958690969908064264211283192959937430539613460471121984649054121171267262097603091410178042319139582772142226087020110084551158367679146616732446561228522673699836019156243452069036383047309578614662564794584927846163157472211089368697387945469398750955336949678910159585015004994620777231073804301249774041
'''

 观察题目发现素数p实际为p**3,不是素数

根据欧拉函数的性质
当p是素数时,φ(p)=p-1。

当且只当n可以分解成两个互质的整数之积,n = p1 × p2,则φ(n) = φ(p1p2) = φ(p1)φ(p2)

特别的,对于两个素数p,q, φ(pq)=(p-1)(q-1)。(RSA算法应用)

若n是质数p的k次幂,\varphi (n)=p^{k}-p^{k-1}

from Crypto.Util.number import *
import gmpy2

flag = (b'NSSCTF{******}'+ b'1'*100)

p = 80505091208742938705306670241621545375764148093711243653439069254008824979403
q = 67599990875658931406915486208971556223245451500927259766683936131876689508521
n = (p**3) * q
e = 65537
c = 7958690969908064264211283192959937430539613460471121984649054121171267262097603091410178042319139582772142226087020110084551158367679146616732446561228522673699836019156243452069036383047309578614662564794584927846163157472211089368697387945469398750955336949678910159585015004994620777231073804301249774041
phi = (p**3-p**2)*(q-1)

d=gmpy2.invert(e,phi)
m = pow(c, d, n)

print( long_to_bytes(m))

十、逆元不存在/不止p,q

from Crypto.Util.number import *

flag = b'NSSCTF{******}'

p = getPrime(512)
q = getPrime(512)

e = 65537
while True:
    r = 2*getPrime(100)*e+1
    if isPrime(r):
        break

n = p*q*r

m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'p = {p}')
print(f'q = {q}')
print(f'r = {r}')
print(f'e = {e}')
print(f'c = {c}')

'''
p = 7478755670255767435237487693415479182290330775502792675052667363676831056436638619069277770540533350723045234676443621124912287506103439704868369839725279
q = 9232828888049557325429111621080998490274442347556398052322580869768941301413255711626092627273543579067597113958627672298942570149816938335701615759283713
r = 102909133680612532601801231903654039
e = 65537
c = 142893174944324070830219394465469685943669308818639857030565389839224452373848570577201378981080333784852764502832587008270072323948511579823852437852643609820245476634896477031076952735298279618952398460203032125853063235638358942643559551563899381032067185778629120272032518475352761100115057449043142848203976076694124978394099839339406197
'''

这道题多了个素数r,但是不需要用直接解码

from Crypto.Util.number import *
import gmpy2

flag = b'NSSCTF{******}'

p = getPrime(512)
q = getPrime(512)

e = 65537
while True:
    r = 2*getPrime(100)*e+1
    if isPrime(r):
        break

p = 7478755670255767435237487693415479182290330775502792675052667363676831056436638619069277770540533350723045234676443621124912287506103439704868369839725279
q = 9232828888049557325429111621080998490274442347556398052322580869768941301413255711626092627273543579067597113958627672298942570149816938335701615759283713
r = 102909133680612532601801231903654039
e = 65537
c = 142893174944324070830219394465469685943669308818639857030565389839224452373848570577201378981080333784852764502832587008270072323948511579823852437852643609820245476634896477031076952735298279618952398460203032125853063235638358942643559551563899381032067185778629120272032518475352761100115057449043142848203976076694124978394099839339406197
n = p*q
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

十一、yafu素数分解

from Crypto.Util.number import *

flag = b'NSSCTF{******}'

p = getPrime(128)
q = getPrime(128)
n = p*q
e = 65537
phi = (p-1)*(q-1)

m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

'''
n = 53690629441472827148854210396580805205350972614395425306316047967905824330731
e = 65537
c = 22130296334673852790451396673112575082637108306697684532954477845025885087040
'''

拿到之后只有n,如果还用factordb分解速度太慢,这时候就要引入一个新的分解工具yafu,这是安装教程:基于RSA解题时yafu的使用-优快云博客

from Crypto.Util.number import *
import gmpy2
p= 277349599849597463956171076348973750041
q= 193584665240506752994134779660255197091
c = 22130296334673852790451396673112575082637108306697684532954477845025885087040
n = 53690629441472827148854210396580805205350972614395425306316047967905824330731
phi = (p-1)*(q-1)
e = 65537
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

十二、费马分解

from Crypto.Util.number import *
import gmpy2
flag = b'NSSCTF{******}'

p = getPrime(512)
q = gmpy2.next_prime(p - getPrime(256))

n = p*q
e = 65537
phi = (p-1)*(q-1)
m = bytes_to_long(flag)
c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')
'''
n = 148841588941490812589697505975986386226158446072049530534135525236572105309550985274214825612079495930267744452266230141871521931612761645600600201983605957650711248808703757693378777706453580124982526368706977258199152469200838211055230241296139605912607613807871432800586045262879581100319519318390454452117
e = 65537
c = 69038543593219231496623016705860610154255535760819426453485115089535439537440188692852514795648297200067103841434646958466720891016026061658602312900242658759575613625726750416539176437174502082858413122020981274672260498423684555063381678387696096811975800995242962853092582362805345713900308205654744774932
'''

费马小定理是数论中的一个重要定理,它表述为:如果 p 是一个质数,a 是一个整数且 1≤a≤p,那么a^{^{p-1}}\equiv 1(mod p)。另外一种等价的表述是对于任意整数 a,都有 a^{p}\equiv amod p

from sympy.ntheory import factorint
from Crypto.Util.number import *
import gmpy2

def factorize_large_n(n):
    factors = factorint(n)
    if len(factors) == 2 and all(exp == 1 for exp in factors.values()):
        p, q = factors.keys()
        return p, q
    return None, None

n = 148841588941490812589697505975986386226158446072049530534135525236572105309550985274214825612079495930267744452266230141871521931612761645600600201983605957650711248808703757693378777706453580124982526368706977258199152469200838211055230241296139605912607613807871432800586045262879581100319519318390454452117
p, q = factorize_large_n(n)
if p and q:
    print(f"p = {p}, q = {q}")
else:
    print("未找到合适的 p 和 q 或 n 不符合要求")

e = 65537
c = 69038543593219231496623016705860610154255535760819426453485115089535439537440188692852514795648297200067103841434646958466720891016026061658602312900242658759575613625726750416539176437174502082858413122020981274672260498423684555063381678387696096811975800995242962853092582362805345713900308205654744774932
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

十三、dp泄露

from Crypto.Util.number import *
e=65537
m=bytes_to_long(b'xxxx')
p=getPrime(512)
q=getPrime(512)
n=p*q
phi=(p-1)*(q-1)
d=inverse(e,phi)
dp=d%(p-1)
c=pow(m,e,n)
print("dp=",dp)
print("n=",n)
print("c=",c)
#dp= 5892502924236878675675338970704766304539618343869489297045857272605067962848952532606770917225218534430490745895652561015493032055636004130931491316020329
#n= 50612159190225619689404794427464916374543237300894011803225784470008992781409447214236779975896311093686413491163221778479739252804271270231391599602217675895446538524670610623369953168412236472302812808639218392319634397138871387898452935081756580084070333246950840091192420542761507705395568904875746222477
#c= 39257649468514605476432946851710016346016992413796229928386230062780829495844059368939749930876895443279723032641876662714088329296631207594999580050131450251288839714711436117326769029649419789323982613380617840218087161435260837263996287628129307328857086987521821533565738409794866606381789730458247531619
  1. 明确已知条件:已知公钥中的加密指数e、模数n,密文c以及泄露的dp。其中dp=dmod(p-1)
  2. 推导计算p的式子:由dp=dmod(p-1),两边同乘e有dp*e=d*emod(p-1)。又因为d*e=1mod((p-1)*(q-1)),所以dp*e=k*(p-1)+1,其中k为某个整数。由于dp<p-1,所以k<e。
  3. 计算p的值
    • 遍历法(e较小时):可以遍历k的取值,范围是1到(e-1)。对于每个k,计算p=\frac{dp*e-1}{k}+1,并检查p是否能整除n。如果能整除,则找到了正确的p,然后通过q=\frac{n}{p}得到q。
  4. 恢复私钥d:计算出p和q后,根据\varphi (n)=(p-1)(q-1),再利用扩展欧几里得算法计算d,使得e*d=1mod \varphi (n)
  5. 解密消息:有了私钥d,就可以对密文c进行解密,得到明文m=c^{d}modn
import gmpy2
from Crypto.Util.number import *

e=65537
'''
m=bytes_to_long(b'xxxx')
p=getPrime(512)
q=getPrime(512)
n=p*q
phi=(p-1)*(q-1)
d=inverse(e,phi)
dp=d%(p-1)
c=pow(m,e,n)
print("dp=",dp)
print("n=",n)
print("c=",c)
'''
dp= 5892502924236878675675338970704766304539618343869489297045857272605067962848952532606770917225218534430490745895652561015493032055636004130931491316020329
n= 50612159190225619689404794427464916374543237300894011803225784470008992781409447214236779975896311093686413491163221778479739252804271270231391599602217675895446538524670610623369953168412236472302812808639218392319634397138871387898452935081756580084070333246950840091192420542761507705395568904875746222477
c= 39257649468514605476432946851710016346016992413796229928386230062780829495844059368939749930876895443279723032641876662714088329296631207594999580050131450251288839714711436117326769029649419789323982613380617840218087161435260837263996287628129307328857086987521821533565738409794866606381789730458247531619


for i in range(1,65538):
    if (dp*e-1)%i == 0:
        if n%(((dp*e-1)//i)+1)==0:
            p=((dp*e-1)//i)+1
            q=n//(((dp*e-1)//i)+1)
            phi = (p-1)*(q-1)
            break
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值