RSA小笔记

呜呜呜我只是个会套jio本的菜只因

目录

主要定理

 1.欧拉定理

 2.费马小定理

一些题目:

unctf2022 - fermat

bugku-Double

Auroractf的一道题


主要定理

 1.欧拉定理

a 与 n 均为正整数,且gcd(a,n)=1,即a,n互质

则有:

a^φ(n)≡1(mod n)

欧拉函数的一些性质

1. n = 1,phi(n)=1。

2. n为质数时,phi(n)= n - 1。

3. 对于两个互素的正整数p, q,即gcd(p, q)= 1,有phi(p * q)=phi(p) * phi(q)

4 .若n = p^k, p为素数,那么有phi(n)=p^k-p^(k-1)

 2.费马小定理

实际上,费马小定理是欧拉定理的一个特例

当n为质数时,有phi(n)= n - 1

则由欧拉定理得=> a^(p-1)≡1(mod p) <=> a^k(p-1)≡1(mod p)(k为正整数)

一些算法优化的推导 # h=x(p-1)..... (参考unctf2022 fermat)

=> a^(p-1) mod p = 1 mod p,即a^(p-1) = 1 + k1*p

=> a^(p-1) % n = a^(p-1) - k2 * n = a^(p-1) - k1 * p * q

##令a^k(p-1) % n =x 则 a^k(p-1)=k2 * n+x => x= a^k(p-1) - k2*n

=> 两边同时去 mod p,有a^k(p-1) % n mod p = a^k(p-1) (mod p)

(因为k2*p*q是p的倍数所以mod p 的结果是0)

=> 所以同样有a^k(p-1)% n mod p = 1 ,即a^k(p-1) % n - 1 也是p的整数倍

=> 因此只需要计算p = gcd((a^k(p-1) % n)-1, n)即可,模幂计算会比直接幂计算快很多

一些题目:

unctf2022 - fermat

原题代码:

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

flag=b'UNCTF{}'
e=0x10001
p=getPrime(1024)
q=getPrime(1024)
n=p*q
m=bytes_to_long(flag)
c=pow(m,e,n)
x=getPrime(1024)
assert gift+x==x*p
print(n)
print(c)
print(gift)

# 19793392713544070457027688479915778034777978273001720422783377164900114996244094242708846944654400975309197274029725271852278868848866055341793968628630614866044892220651519906766987523723167772766264471738575578352385622923984300236873960423976260016266837752686791744352546924090533029391012155478169775768669029210298020072732213084681874537570149819864200486326715202569620771301183541168920293383480995205295027880564610382830236168192045808503329671954996275913950214212865497595508488636836591923116671959919150665452149128370999053882832187730559499602328396445739728918488554797208524455601679374538090229259
# 388040015421654529602726530745444492795380886347450760542380535829893454552342509717706633524047462519852647123869277281803838546899812555054346458364202308821287717358321436303133564356740604738982100359999571338136343563820284214462840345638397346674622692956703291932399421179143390021606803873010804742453728454041597734468711112843307879361621434484986414368504648335684946420377995426633388307499467425060702337163601268480035415645840678848175121483351171989659915143104037610965403453400778398233728478485618134227607237718738847749796204570919757202087150892548180370435537346442018275672130416574430694059
# 28493930909416220193248976348190268445371212704486248387964331415565449421099615661533797087163499951763570988748101165456730856835623237735728305577465527656655424601018192421625513978923509191087994899267887557104946667250073139087563975700714392158474439232535598303396614625803120915200062198119177012906806978497977522010955029535460948754300579519507100555238234886672451138350711195210839503633694262246536916073018376588368865238702811391960064511721322374269804663854748971378143510485102611920761475212154163275729116496865922237474172415758170527875090555223562882324599031402831107977696519982548567367160

当知道某一个数x是p-1的倍数时,就用gcd(2^x-1,n)=p,进一步gcd(pow(2,x,n)-1,n)=p。这里2可以换为其他数,只要不是p的倍数和0、1就行。

exp:(推导参考上面的费马小定理)

import libnum
import gmpy2

e=0x10001
n=19793392713544070457027688479915778034777978273001720422783377164900114996244094242708846944654400975309197274029725271852278868848866055341793968628630614866044892220651519906766987523723167772766264471738575578352385622923984300236873960423976260016266837752686791744352546924090533029391012155478169775768669029210298020072732213084681874537570149819864200486326715202569620771301183541168920293383480995205295027880564610382830236168192045808503329671954996275913950214212865497595508488636836591923116671959919150665452149128370999053882832187730559499602328396445739728918488554797208524455601679374538090229259
c=388040015421654529602726530745444492795380886347450760542380535829893454552342509717706633524047462519852647123869277281803838546899812555054346458364202308821287717358321436303133564356740604738982100359999571338136343563820284214462840345638397346674622692956703291932399421179143390021606803873010804742453728454041597734468711112843307879361621434484986414368504648335684946420377995426633388307499467425060702337163601268480035415645840678848175121483351171989659915143104037610965403453400778398233728478485618134227607237718738847749796204570919757202087150892548180370435537346442018275672130416574430694059
gift=28493930909416220193248976348190268445371212704486248387964331415565449421099615661533797087163499951763570988748101165456730856835623237735728305577465527656655424601018192421625513978923509191087994899267887557104946667250073139087563975700714392158474439232535598303396614625803120915200062198119177012906806978497977522010955029535460948754300579519507100555238234886672451138350711195210839503633694262246536916073018376588368865238702811391960064511721322374269804663854748971378143510485102611920761475212154163275729116496865922237474172415758170527875090555223562882324599031402831107977696519982548567367160

# gift+x=x*p
#gift=x(p-1)

p=libnum.gcd(pow(2,gift,n)-1,n)
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
flag=libnum.n2s(int(m))
print(flag)
# b'UNCTF{DO_y0u_Fermat_1ittle_theOrem}'

bugku-Double

原题代码:(看不懂sage,菜狗捏呜呜呜)

from Crypto.Util.number import bytes_to_long
from secrets import k, P, flag

E = EllipticCurve(QQ,[0,2021,0,310,-2783])
assert P.xy()[1] == E.lift_x(2)
Q = k * P
R = Q + P

p = Q[0].numerator()
q = R[0].numerator()
e = 0x10001
n = p * q

assert k < n.bit_length()
m = bytes_to_long(flag)
c = pow(m, e, n)

print(f'n = {n}')
print(f'c = {c}')
#n = 2627832721798532654645633759787364870195582649392807630554510880534973280751482201937816738488273589173932960856611147584617677312265144131447658399933331448791094639659769069406481681017795446858858181106274806005669388289349727511470680972
#c = 96830301447792999743877932210925094490214669785432172099311147672020980136112114653571739648595225131425493319224428213036136642899189859618195566355934768513439007527385261977662612094503054618556883356183687422846428828606638722387070581

抛开前面的sage语言不说,这题有一点对rsa原理理解的应用:

n=p*q实际上是n只有两个质因数p和q,不能错误的认为n只能分解出p,q两个质因数

当然也有类似的题目n=p*q*r*s 这种,最终求phi(n)就是phi=(q-1)*(q-1)*(r-1)*(s-1)

其实就是前面说过的,欧拉函数性质的2,3

所以回到这题,当n分解出很多个质因数时,同理,phi(n)为所有质因数减去1的乘积

所以写一个循环来求每一个质因数的欧拉函数(n的欧拉函数其实就是每一个n的质因子的欧拉函数的乘积)

用factordb分解出n所有的质因数

exp:

p_list = [2,2,3,3,13,101,443,1087,15527,47363,111309491243,5738160242986813,118881536167887307517887651928306109231371669715927208908931577713837,2067526976195544603847619621425435706797374170280528431947550231604621041865531599319428120598265860512130517815755608596553793]
phi= 1
for p in p_list:
    phi *= (p-1)

Auroractf的一道题

悄咪咪偷来学习的题目,勿喷

这题主要是对费马分解算法的理解

原题代码:

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

p = getPrime(1024)
q = gmpy2.next_prime(p + 1000000)
r = gmpy2.next_prime(q + 1000000)
s = gmpy2.next_prime(r + 1000000)

n = p * q * r * s
e = 0x10001

m = bytes_to_long(flag)

c = pow(m, e, n)

# n = 108299033965406365561943421701029190713946501560891630763244580970876141418060260848778356857818721003436668631051400046179714981563966629274135856263153393451778069603328236097645480852770563989641923335589213862076364231145680800763901480686502776051597843698725745250490425410650791537590877762849466754206792810298344723222757628527518527264424314398114603721700244387477600040173682904446101720469681389347684578169792444049955729491371539347527279510563843274956478643209577823959527009597138462178858908131459847477377873722809756286442989867841939264973938882747031165883664081728483968786444940130754090961440237029991537678198779446572379955612212432298032927533340075560342822842145491942842616840755357720456094746128021240483607459457623006697140665289210877036207570817593250015026853022025281118097723071897439283253998814746302023470665795337363626017807575053924858839475153327626709665036887169655539664145700068948907541640999554647851646028559453557061575683476442175156969842706373750319278039080406149444513435322207503611280827839170184405510258770955233545645043225793645367427485248583195703459681129854324595394957504455110811076379721049379749687264501324278652077596148357272587301352719972975920356014689
# e = 65537
# c = 66282640807724405518602152114651879396246399255101507349038984047328959352691526384322744768659223247334455265432088028572041267042739221831533163642845861607636601193315832251590920339394500463075340397307285539327999953887797257215690304189880652964252216730150032533125189722147047967308850948061617857067650084515935365816313305482220299962756712272432126983038693515098931341954074787185153265911930069239124196604571305060210229630878593348542829381366929767819633918796746367100098078605770730971792477677209132590933799007758134578199207989520721360808705952397752948494796730262506568874816001910275456823816338446048730520807309148166369726421371597405903017279967140423776263708058900596532049999358296071238547707056598409574824286805346221039445037989664132260965906540515127261405823017822082554131040927683563314789126862678639503366941046116526326931102784127218794970747035858802637234772860038892015022384208812143488934424907981571536806616031983586579576340972689776331101818627661035148519372288555606365821757056616114258213545574963383005835374672572357290479551752690678352298990065015686456011474166705064061262970654778008504711084690127162113691996060192655389528709191383408755044112132008663979770115918

可以看到,显然是n的质因数接近

 关键代码:

p = getPrime(1024)
q = gmpy2.next_prime(p + 1000000)
r = gmpy2.next_prime(q + 1000000)
s = gmpy2.next_prime(r + 1000000)

n = p * q * r * s

显然p,q,r,s接近,第一时间想到yafu爆拆n,发现要爆挺久的,但是也可以做出来(这是最笨的方法)

用费马分解滴算法,大大滴好(doge)

RSA-p和q挨得很近(费马分解)_OnlyForBetter的博客-CSDN博客_rsa next_prime ---这个师傅博客讲费马分解很详细

下面是俺滴拙见

下面是利用费马分解的算法原理来做(yafu其实也是类似费马分解的一个算法吧)

这里简单引入原理:

假设有这样的两个素数:

p = getPrime(512)

q = gmpy2.next_prime(p) #n=q*p q是p的下一个素数

p和q很接近,那么对n开平方的结果必然会落在q与p之间(而且一定不是素数,因为p,q就是紧邻的两个素数)那么我们找这个开方出来的数字的下一个素数,一定是q,因此我们再让n/q就可以得到两个素数p和q

 

当然,这一题在原理上也是一样的解法

exp及注释:

from Crypto.Util.number import *
import gmpy2
n = 108299033965406365561943421701029190713946501560891630763244580970876141418060260848778356857818721003436668631051400046179714981563966629274135856263153393451778069603328236097645480852770563989641923335589213862076364231145680800763901480686502776051597843698725745250490425410650791537590877762849466754206792810298344723222757628527518527264424314398114603721700244387477600040173682904446101720469681389347684578169792444049955729491371539347527279510563843274956478643209577823959527009597138462178858908131459847477377873722809756286442989867841939264973938882747031165883664081728483968786444940130754090961440237029991537678198779446572379955612212432298032927533340075560342822842145491942842616840755357720456094746128021240483607459457623006697140665289210877036207570817593250015026853022025281118097723071897439283253998814746302023470665795337363626017807575053924858839475153327626709665036887169655539664145700068948907541640999554647851646028559453557061575683476442175156969842706373750319278039080406149444513435322207503611280827839170184405510258770955233545645043225793645367427485248583195703459681129854324595394957504455110811076379721049379749687264501324278652077596148357272587301352719972975920356014689

p1=gmpy2.iroot(n,4)[0]    #对n开4次方得到的结果会在q和r之间
      
#p1在r和s之间,所以会有不等式 q=(p + 1500000) < p1 < r=(q + 1500000)  当然这里不一定是1500000,但是一定比1000000大
#所以p1-1600000 < p

p1 = p1-1600000   #这里不一定是1600000,可以更大,也可以更小,但更小可能不包含p在里面就求不出来
#所以p1在p的前面,逐个素数递增p1,当p1能被n整除时,此时p1就等于p

while n % p1 !=0:                       #判断当p1不能被n整除
    p1 = gmpy2.next_prime(p1)           #继续递增p1
p=p1
#得到p之后,后面的n的因子就可以直接求了
q = gmpy2.next_prime(p + 1000000)
r = gmpy2.next_prime(q + 1000000)
s = gmpy2.next_prime(r + 1000000)
e = 65537
c = 66282640807724405518602152114651879396246399255101507349038984047328959352691526384322744768659223247334455265432088028572041267042739221831533163642845861607636601193315832251590920339394500463075340397307285539327999953887797257215690304189880652964252216730150032533125189722147047967308850948061617857067650084515935365816313305482220299962756712272432126983038693515098931341954074787185153265911930069239124196604571305060210229630878593348542829381366929767819633918796746367100098078605770730971792477677209132590933799007758134578199207989520721360808705952397752948494796730262506568874816001910275456823816338446048730520807309148166369726421371597405903017279967140423776263708058900596532049999358296071238547707056598409574824286805346221039445037989664132260965906540515127261405823017822082554131040927683563314789126862678639503366941046116526326931102784127218794970747035858802637234772860038892015022384208812143488934424907981571536806616031983586579576340972689776331101818627661035148519372288555606365821757056616114258213545574963383005835374672572357290479551752690678352298990065015686456011474166705064061262970654778008504711084690127162113691996060192655389528709191383408755044112132008663979770115918

phi=(p-1)*(q-1)*(r-1)*(s-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))
#Aurora{Just_do_f3rm4t_f4ct0rizat1on_tw1c3}

密码真的太难了呜呜呜,我太菜了捏

 每日emo:

多情仅有春庭月,犹为离人照落花。—— 张泌《寄人》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值