CTF密碼學之RSA攻擊算法

合天網安實驗室 發佈 2024-04-08T08:10:23.712433+00:00

實驗推薦:本文涉及靶場知識點:RSA之小公鑰指數攻擊。希望大家在學習的過程中更多的去關注攻擊算法實現的原理,而不僅僅只在於 copy 攻擊代碼。

實驗推薦:

本文涉及靶場知識點:RSA之小公鑰指數攻擊

https://www.hetianlab.com/expc.do?ec=ECIDea39-a4f3-4e24-8cb6-37556c183e43&pk_campaign=weixin-wemedia

通過該實驗了解CTF中常見和以前奇葩題型,有助於我們學習更多的內容。本次實驗我們將學習RSA中小公鑰指數的情況,例如在e特別小的情況下如何去生成私鑰。

前言:


學習完基本數論後,我們開始學習 RSA 的各種攻擊算法及其數學原理。希望大家在學習的過程中更多的去關注攻擊算法實現的原理,而不僅僅只在於 copy 攻擊代碼。

工具準備:


工具和第三方庫的安裝教程請自行百度

  • python3.8環境:https://www.python.org/downloads/windows/
  • 大素數分解工具:
    • factordb在線分解:http://factordb.com/
    • win10 yafu-x64:https://sourceforge.net/projects/yafu/
  • python第三方庫:
    • gmpy2
    • pycryptodome
    • libnum
    • sympy
    • rsa


RSA加密類型:


  • 公鑰解析,簽名加密
  • 利用公約數求解
  • 分解 N 得到多個相同的 P
  • dp、dq 泄露
  • dp 泄露
  • Roll 按行加密
  • 共模攻擊
  • 低加密指數攻擊
  • 低加密指數廣播攻擊
  • 低解密指數攻擊



1.公鑰解析,簽名加密


如果題目給了pem或者key後綴結尾的文件,用工具解析出n和e。或者可以用kali自帶的Openssl從公鑰文件中提取出n和e。

命令:openssl rsa -pubin -text -modulus -in key.pem

例題:1

BUURSA: https://buuoj.cn/challenges#RSA

公鑰文件

-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----


在線網站解析公鑰:http://ctf.ssleye.com/



得到n和e之後,用factordb:http://factordb.com/

分解模n,得到p,q的值。


import rsa            #rsa模塊
from gmpy2 import*    #gmpy2模塊

e= 65537
n= 86934482296048119190666062003494800588905656017203025617216654058378322103517
p= 285960468890451637935629440372639283459
q= 304008741604601924494328155975272418463

#求私鑰d
'''
phi = (p-1)*(q-1)
d = invert(e,phi)     #gmpy2.invert(),用來求模逆的方法
print(d)
'''
d= 81176168860169991027846870170527607562179635470395365333547868786951080991441


key = rsa.PrivateKey(n,e,d,q,p)         #在pkcs標準中,pkcs#1規定,私鑰包含(n,e,d,p,q)

with open("C:\\Users\\MIKEWYW\\Desktop\\flag.txt","rb") as f:  #以二進位讀模式,讀取密文  
    f = f.read()
    print(rsa.decrypt(f,key))           # f:公鑰加密結果  key:私鑰


例題:2020西湖論劍BrokenSystems

題目

BrokenSystems.py

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from secret import flag
import os
rsa = RSA.generate(2048)
public_key = rsa.publickey().exportKey()
f=open("public.key","w")
f.write(public_key.decode())
f.close()

rsakey=RSA.importKey(open("public.key","r").read())
rsa = PKCS1_OAEP.new(rsakey)
msg=rsa.encrypt(flag.encode())
f=open("message","wb")
f.write(msg)
f.close()

public.txt

-----BEGIN PUBLIC KEY-----
MIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAQEAwgdFIj/1uUss2EEhZvco
iiHyGH4aQhRTkYyrA8gCU0USM+sb3CNjdEIoqoaUqMLLyDP4Dd9AgxpokBsjC4Pz
8P7Uty0LlCteld7ayNzABHoq+5DIHtctOtSbcvyL0NMWfd2qarUWfAWN82rxkLIW
CFu9nWIfm9I6CT5OPZzDh7YnTywznIjhstkIrLM/TiDmR6vuBxSjzORkbolilLeB
A9zJpNt+1oEWTG5sx/0zR24XSmxwcDeyUEkTZfnw63auq6B9svZi2IBIr5jIjHbG
cQ25ZY1J/KDK8fXNmdwH8YhDK0j4VXEWitEPyCS3toK61sql0S/28EySeGtzirGb
twKCAQAdLS8fFz+BzzaP7AbUDUf9kvhhXBLuwUFo8ohCeVK4z1pTj3C6M0G2oXOu
gDdalrDThNlyKxkUn3iUc3Xgoz315pPtq9Xk1Ez/qeUl6gFPP6SZtfeymyGdkLiN
pVquOghjczjXvtBW467Fdb5Wu95TSzVaLndX23rsqW541n8hUwt8PsJKxh+bR0qy
gyIN2VRRNdBlpyTOL49E4y5GDu9fmVgAnFivWVGT135ywl8MsBUFuZPBNTKLEbUA
3KvJVckXf4Od0ENYbiWjEzXn1UN9yebNbU6+yyk34WAmwnkuF0X0Tu1UEb6qtV7Q
kF25GYy9QxERvodGL0Y2njHRpGE/
-----END PUBLIC KEY-----

message.txt

'Ω?奟?ypG睉晜< U,.
W?盔敲m銖?.嗘7?s來薶 
只Z???'D?夞%莰}?~a,妄姷槢諫v}玊??#ad??$ 爝湆鄃 
0遀; 
#繕刜2?顪娪k+需?捨HD篹枒筡婌 輛 賅?跌婊 CD瓦?3?h¬?V?p琙|
黶UU沯?酟詎分b澾硲€}?~QJ?綾摪 偑鱈塖
?I騸?費JB_?O0&?髀
SxN岑y?


解題思路

首先進行公鑰解析得到 n,e的值:

n = 24493816160588971749455534346389861269947121809901305744877671102517333076424951483888863597563544011725032585417200878377314372325231470164799594965293350352923195632229495874587039720317200655351788887974047948082357232348155828924230567816817425104960545706688263839042183224681231800805037117758927837949941052360649778743187012198508745207332696876463490071925421229447425456903529626946628855874075846839745388326224970202749994059533831664092151570836853681204646481502222112116971464211748086292930029540995987019610460396057955900244074999111267618452967579699626655472948383601391620012180211885979095636919
e = 3683191938452247871641914583009119792552938079110383367782698429399084083048335018186915282465581498846777124014232879019914546010406868697694661244001972931366227108140590201194336470785929194895915077935083045957890179080332615291089360169761324533970721460473221959270664692795701362942487885620152952927112838769014944652059440137350285198702402612151501564899791870051001152984815689187374906618917967106000628810361686645504356294175173529719443860140795170776862320812544438211122891112138748710073230404456268507750721647637959502454394140328030018450883598342764577147457231373121223878829298942493059211583

我們可以看出,e的值特別大。嘗試winner攻擊,解得 d。(winner攻擊在後面低解密指數攻擊會詳細介紹)

這時發現我們已知了n, e , d;但N不能直接分解,這裡涉及到一個解密算法
已知n, e , d,求P,Q
https://www.di-mgt.com.au/rsa_factorize_n.html


得到n,e,d,p,q的值後,通過分析加密代碼我們可以知道這裡 涉及Crypto.Cipher.PKCS1_OAEPCrypto.PublicKey.RSA 的加密協議

Crypto的官方學習源文件https://pythonhosted.org/pycrypto/Crypto-module.html


Python3解密腳本:

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

n = 24493816160588971749455534346389861269947121809901305744877671102517333076424951483888863597563544011725032585417200878377314372325231470164799594965293350352923195632229495874587039720317200655351788887974047948082357232348155828924230567816817425104960545706688263839042183224681231800805037117758927837949941052360649778743187012198508745207332696876463490071925421229447425456903529626946628855874075846839745388326224970202749994059533831664092151570836853681204646481502222112116971464211748086292930029540995987019610460396057955900244074999111267618452967579699626655472948383601391620012180211885979095636919
e = 3683191938452247871641914583009119792552938079110383367782698429399084083048335018186915282465581498846777124014232879019914546010406868697694661244001972931366227108140590201194336470785929194895915077935083045957890179080332615291089360169761324533970721460473221959270664692795701362942487885620152952927112838769014944652059440137350285198702402612151501564899791870051001152984815689187374906618917967106000628810361686645504356294175173529719443860140795170776862320812544438211122891112138748710073230404456268507750721647637959502454394140328030018450883598342764577147457231373121223878829298942493059211583
d = 1779217788383673416690068487595062922771414230914791138743960472798057054853883175313487137767631446949382388070798609545617543049566741624609996040273727
p = 149604112324264915811376746906108325951188179904814259006959765070266946659481820938211689946210254302179197289522748397160602946376246768419310765669852537378426700376878745285639531531077237124655345323906476180103106894642043615024716862503414785057646920410083538192951872861366496901158348770066798098371
q = 163724217068973025857079545677048587508164102644298632911494474022224582218067057349189211462632427829087720476013052665037199232658015194718500750961261016558605363103092187533086949903145449057015220561698195502163792192055762108803714387175594231859738263839090338762578040513451585421537323416472060788989

key=RSA.construct((n, e, d, p, q))
cipher = PKCS1_OAEP.new(key)

with open("C:\\Users\\MIKEWYW\\Desktop\\message.txt","rb") as f:  #以二進位讀模式,讀取密文  
    f = f.read()
    flag = cipher.decrypt(f)
    print(flag)


代碼中有看不懂的地方,如果是關於第三方庫模塊的,請認真學習一下上面的Crypto的官方學習源文件

2. 利用公約數求解


如果兩次公鑰的加密過程中使用的 n1 和 n2 具有相同的素因子,則可以利用歐幾里得算法直接將 n1 和 n2 分解

p = gmpy2.gcd(n1,n2)   #gmpy2庫函數gcd(),用於求最大公約數。

自定義函數gcd()歐幾里得算法

def gcd(a,b):
    if a<b:
        a,b = b,a
    while(b!=0):
        temp = a%b
        a = b
        b = temp
    return a


對於歐幾里得算法的時間複雜度,即便是4096bit級別的也是秒破級別。

3. 分解 N 得到多個相同的 P


知識點:

1.歐拉函數的性質:

p為素數,所以 φ


2.RSA加密公式:

n=p*q,φ

mod φ, mod

mod

例題:

由於暫時未找到這個考點的題目,下面的這個例題用的是一個博主發的

import gmpy2  
import random  
from Crypto.Util.number import *  
from flag import flag  
  
def generate_key(1024):  
    p = getPrime(1024)  
    r = random.randint(2, 10)  
    s = random.randint(r, 1024)  
     while True:  
         e = random.randint(3, p**r*(p-1))  
         if gmpy2.gcd(e, p**s*(p-1)) == 1:  
             break  
     pubkey = (long(e), long(p**r))   #返回e  和p^r  
     return pubkey  
   
def crypt(msg, pubkey):  
    e, n = pubkey                            #e  n=p^r  
    m = bytes_to_long(msg)      
    assert m < n - 1  
    enc = pow(m, e, n)         
    return long_to_bytes(enc)  
  
nbit = 1024  
pubkey = generate_key(1024)  
print 'pubkey =', pubkey                    #輸出e  和p^r  
msg = flag值     
enc = crypt(msg, pubkey)    
  
print 'enc =\n', enc.encode('base64') 


解題思路:

通過分析加密腳本,我們可以知道:

已知e, , enc的值了。

由歐拉函數的性質可以得到:phi=φ

  1. 要求得 mod ,則先求d。
  2. 由於 mod φ,求得d,則先求φ(n)
  3. 題目給的是 ,所以先要分解n以獲得p和r的值。


4. dp、dq 泄露


攻擊條件:

已知p,q,dp,dq,c

關係公式:


解密公式:

  1. mod
  2. mod

  3. I:乘法逆元,I=invert(q,p)

解密數學原理:

利用中國剩餘定理可得: mod , mod

證明:

由 mod ,得

因為 ,所以

上述公式中,同時取余p和q,可分別得到: mod , mod

所以 ,代入 mod 可得: mod

等式兩邊同時減去 ,可以得到: mod

這裡因為gcd(p,q)=1 ,所以可以得到p的逆元,得: mod ( 表示p的逆元,可用gmpy2.invert(q,p)函數求得)

即: mod

由 mod 和




可得到:

mod


代入 mod 得:
mod mod

例題:

BUURSA1

p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852

解題代碼:

from gmpy2 import*
from libnum import*

p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852
#n=p*q

I = invert(q,p)            #求p的逆元
mp = pow(c,dp,p)           #求冪取模運算
mq = pow(c,dq,q)           #求冪取模運算

m = (((mp-mq)*I)%p)*q+mq   #求明文公式
#m = m%n(可以加上,不加也沒事,這裡數值不大)
print(n2s(m))              #n2s()函數,用於數值轉字符串


5. dp 泄露


攻擊條件:

已知e,n,dp,c

關係公式:

dp≡d mod (p-1)
φ
mod φ
mod

解密數學原理:

思路:

1.破解m的關鍵在於獲取到d
利用gmpy2庫,d=gmpy2.invert(e,φ(n))
2.由φ ,dp≡d mod (p-1)

可得到(p-1),進而得到p,q因為n已知,n=p*q
證明:

mod
推導:
為整數

由 mod 得

所以:
推導得:

令:,即

因為

所以

所以

3.求出p後即可求出q,進而求得φ(n),得到d
通過遍歷x,可求出存在p,使得n % p=0

關鍵代碼:

for i in range(1,e):                   #在範圍(1,e)之間進行遍歷
    if(dp*e-1)%i == 0:
        if n%(((dp*e-1)//i)+1) == 0:   #存在p,使得n能被p整除
            p=((dp*e-1)//i)+1
            q=n//(((dp*e-1)//i)+1)
            phi=(q-1)*(p-1)            #歐拉定理
            d=gmpy2.invert(e,phi)         #求模逆
            m=pow(c,d,n)               #快速求冪取模運算


例題:

BUURSA2

題目

e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751


解題腳本:

from gmpy2 import*
from libnum import*

e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

for i in range(1,e):                   #在範圍(1,e)之間進行遍歷
    if(dp*e-1)%i == 0:
        if n%(((dp*e-1)//i)+1) == 0:   #存在p,使得n能被p整除
            p=((dp*e-1)//i)+1
            q=n//(((dp*e-1)//i)+1)
            phi=(q-1)*(p-1)            #歐拉定理
            d=invert(e,phi)         #求模逆
            m=pow(c,d,n)               #快速求冪取模運算
print(n2s(m))       #16進位轉文本


6. Roll 按行加密


例題:

BUU RSAROLL https://buuoj.cn/challenges#RSAROLL

題目:



解題思路:

由圖二可知 N 和 e 的值。把圖二中的每行數據進行解密:

from gmpy2 import*
from libnum import*

n=920139713
p=18443
q=49891
e=19

phi = (q-1)*(p-1)
d=invert(e,phi)

m=""
with open("C:\\Users\\MIKEWYW\\Desktop\\BUURSA題目\\ROLL\\Data.txt","r")as f:
    for i in f.readlines():                #讀取每一行
        m+=n2s(pow(int(i),d,n))            

print(m)


注意讀取的密文數據要新建一個文本:只保留捲軸數據


7. 共模攻擊


背景:

共模攻擊,Common Modulus Attack,也稱為同模攻擊。同模攻擊利用的大前提就是,RSA體系在生成密鑰的過程中使用了相同的模數n。

對於同一條明文m,新手小白A和B對其進行加密:
A: mod
B: mod

如果,此時有一個攻擊者,同時監聽了A和B接收到的密文。因為模數不變,以及所有的公鑰都是公開的,那麼利用同模攻擊,就可以在不知道的條件下破解明文M

攻擊條件:

已知

解密數學原理:

當n一定時,已知

假設 互質,即
此時有:
(其中為整數,且一正一負)

通過擴展歐幾里得算法,我們可以得到上式的一組解()

假設為正數,為負數

因為 mod , mod
所以:

mod
=(( mod ) *( mod )) mod

(由)

可得到:
mod

即:
mod


例題:

BUU RSA3

c1=22322035275663237041646893770451933509324701913484303338076210603542612758956262869640822486470121149424485571361007421293675516338822195280313794991136048140918842471219840263536338886250492682739436410013436651161720725855484866690084788721349555662019879081501113222996123305533009325964377798892703161521852805956811219563883312896330156298621674684353919547558127920925706842808914762199011054955816534977675267395009575347820387073483928425066536361482774892370969520740304287456555508933372782327506569010772537497541764311429052216291198932092617792645253901478910801592878203564861118912045464959832566051361
n=22708078815885011462462049064339185898712439277226831073457888403129378547350292420267016551819052430779004755846649044001024141485283286483130702616057274698473611149508798869706347501931583117632710700787228016480127677393649929530416598686027354216422565934459015161927613607902831542857977859612596282353679327773303727004407262197231586324599181983572622404590354084541788062262164510140605868122410388090174420147752408554129789760902300898046273909007852818474030770699647647363015102118956737673941354217692696044969695308506436573142565573487583507037356944848039864382339216266670673567488871508925311154801
e1=11187289
c2=18702010045187015556548691642394982835669262147230212731309938675226458555210425972429418449273410535387985931036711854265623905066805665751803269106880746769003478900791099590239513925449748814075904017471585572848473556490565450062664706449128415834787961947266259789785962922238701134079720414228414066193071495304612341052987455615930023536823801499269773357186087452747500840640419365011554421183037505653461286732740983702740822671148045619497667184586123657285604061875653909567822328914065337797733444640351518775487649819978262363617265797982843179630888729407238496650987720428708217115257989007867331698397
e2=9647291


解題腳本:

from libnum import*   #python第三方庫
from gmpy2 import*    #python第三方庫

n = 22708078815885011462462049064339185898712439277226831073457888403129378547350292420267016551819052430779004755846649044001024141485283286483130702616057274698473611149508798869706347501931583117632710700787228016480127677393649929530416598686027354216422565934459015161927613607902831542857977859612596282353679327773303727004407262197231586324599181983572622404590354084541788062262164510140605868122410388090174420147752408554129789760902300898046273909007852818474030770699647647363015102118956737673941354217692696044969695308506436573142565573487583507037356944848039864382339216266670673567488871508925311154801
c1 = 22322035275663237041646893770451933509324701913484303338076210603542612758956262869640822486470121149424485571361007421293675516338822195280313794991136048140918842471219840263536338886250492682739436410013436651161720725855484866690084788721349555662019879081501113222996123305533009325964377798892703161521852805956811219563883312896330156298621674684353919547558127920925706842808914762199011054955816534977675267395009575347820387073483928425066536361482774892370969520740304287456555508933372782327506569010772537497541764311429052216291198932092617792645253901478910801592878203564861118912045464959832566051361
c2 = 18702010045187015556548691642394982835669262147230212731309938675226458555210425972429418449273410535387985931036711854265623905066805665751803269106880746769003478900791099590239513925449748814075904017471585572848473556490565450062664706449128415834787961947266259789785962922238701134079720414228414066193071495304612341052987455615930023536823801499269773357186087452747500840640419365011554421183037505653461286732740983702740822671148045619497667184586123657285604061875653909567822328914065337797733444640351518775487649819978262363617265797982843179630888729407238496650987720428708217115257989007867331698397
e1 = 11187289
e2 = 9647291

s = gcdext(e1,e2)    #gmpy2.gcdext(),擴展歐幾里得算法,返回tuple元組,滿足s[1]*e1+s[2]*e2=1

m = pow(c1,s[1],n)*pow(c2,s[2],n)%n   #獲取明文m

print(n2s(m))


8. 低加密指數攻擊


e=3時的小明文攻擊:

特點:e=3,m很小,n很大

  1. 當 e=3 時,如果明文過小,導致明文的三次方仍然小於n,那麼通過直接對密文開三次方即可得到明文。

即: mod ,如果e=3,且 ,則:,

2.如果明文的三次方比n大,但不是足夠大,那麼設k有:

爆破,如果 或者 能開三次根式,那麼就可以直接得到明文。

關鍵代碼

i=0
while 1:
    if(iroot(c+i*n,3)[1]==1):           #或者 iroot(c-i*n,3)
        print(iroot(c+i*n,3)[0])
        break
    i=i+1

例題:

BUU Dangerous RSA

https://buuoj.cn/challenges#Dangerous%20RSA

題目:

#n:  0x52d483c27cd806550fbe0e37a61af2e7cf5e0efb723dfc81174c918a27627779b21fa3c851e9e94188eaee3d5cd6f752406a43fbecb53e80836ff1e185d3ccd7782ea846c2e91a7b0808986666e0bdadbfb7bdd65670a589a4d2478e9adcafe97c6ee23614bcb2ecc23580f4d2e3cc1ecfec25c50da4bc754dde6c8bfd8d1fc16956c74d8e9196046a01dc9f3024e11461c294f29d7421140732fedacac97b8fe50999117d27943c953f18c4ff4f8c258d839764078d4b6ef6e8591e0ff5563b31a39e6374d0d41c8c46921c25e5904a817ef8e39e5c9b71225a83269693e0b7e3218fc5e5a1e8412ba16e588b3d6ac536dce39fcdfce81eec79979ea6872793L
#e:  0x3
#c:0x10652cdfaa6b63f6d7bd1109da08181e500e5643f5b240a9024bfa84d5f2cac9310562978347bb232d63e7289283871efab83d84ff5a7b64a94a79d34cfbd4ef121723ba1f663e514f83f6f01492b4e13e1bb4296d96ea5a353d3bf2edd2f449c03c4a3e995237985a596908adc741f32365
so,how to get the message?

解題思路:

假設我們 M / n 商 k 餘數為c,

所以M = + C,對K進行爆破,只要k滿足 k*n + C能夠開方就可以

解題腳本:

from libnum import*   #python第三方庫
from gmpy2 import*    #python第三方庫

n = 0x52d483c27cd806550fbe0e37a61af2e7cf5e0efb723dfc81174c918a27627779b21fa3c851e9e94188eaee3d5cd6f752406a43fbecb53e80836ff1e185d3ccd7782ea846c2e91a7b0808986666e0bdadbfb7bdd65670a589a4d2478e9adcafe97c6ee23614bcb2ecc23580f4d2e3cc1ecfec25c50da4bc754dde6c8bfd8d1fc16956c74d8e9196046a01dc9f3024e11461c294f29d7421140732fedacac97b8fe50999117d27943c953f18c4ff4f8c258d839764078d4b6ef6e8591e0ff5563b31a39e6374d0d41c8c46921c25e5904a817ef8e39e5c9b71225a83269693e0b7e3218fc5e5a1e8412ba16e588b3d6ac536dce39fcdfce81eec79979ea6872793
c = 0x10652cdfaa6b63f6d7bd1109da08181e500e5643f5b240a9024bfa84d5f2cac9310562978347bb232d63e7289283871efab83d84ff5a7b64a94a79d34cfbd4ef121723ba1f663e514f83f6f01492b4e13e1bb4296d96ea5a353d3bf2edd2f449c03c4a3e995237985a596908adc741f32365

i=0
while 1:
    if(iroot(c+i*n,3)[1]==1):           #或者 iroot(c-i*n,3)
        print(n2s(iroot(c+i*n,3)[0]))
        break
    i=i+1


e=2時的小明文攻擊:

e=2時,直接將密文C開平方獲得解

由於e只有2,相當於把明文m平方而已,得到的C也比n小很多。嘗試直接將C開根號看能否得到明文。

from libnum import*   #python第三方庫
from gmpy2 import*    #python第三方庫

c=......              #C的值
m=isqrt(c)            #開平方根
#m=iroot(c,2)[0]      #開C的二次方根

print(n2s(m))

e=1時的小明文攻擊:

加密過程:

C≡m mod n ,明文與密文同模

所以有:m=C+n*k,爆破k

from libnum import*

n=....
c=....
max_num = 7   #設置遍歷上限

for k in range(max_num):
    m = c + n*k
    print(n2s(m))    


9. 低加密指數廣播攻擊


背景:

如果選取的加密指數較低,並且使用相同的加密指數給一個接受者的群發送相同的信息,那麼可以進行廣播攻擊得到明文

適用條件:

模數n,密文C不同,明文m,加密指數e相同。(一般的話e=k,k是題目給出的n和c的組數)

例如:e=k=3

同餘式組:


由中國剩餘定理:
設 是兩兩互素的正整數,

則同餘式組:

有唯一解:
其中 mod ,


攻擊代碼

#python3,在兩兩互質的情況下

from gmpy2 import*
n1=...
n2=...
n3=...
c1=...
c2=...
c3=...
e=3

def CRT(a,n):
    sum = 0
    N = reduce(lambda x,y:x*y,n)   # ni 的乘積,N=n1*n2*n3

    for n_i, a_i in zip(n,a):    # zip()將對象打包成元組
        N_i = N // n_i           #Mi=M/ni
        sum += a_i*N_i*invert(N_i,n_i)   #sum=C1M1y1+C2M2y2+C3M3y3
    return sum % N 

n =[n1,n2,n3] 
c =[c1,c2,c3]

x = CRT(c,n)

m = iroot(x,e)[0]
print(n2s(m))


例題:

BUURSA4
https://buuoj.cn/challenges#RSA4

N = 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004 
c = 310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243

N = 302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114 
c = 112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344

N = 332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323 
c = 10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242


解題腳本:

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

# 將5進位數轉換為10進位數  int('',5)
N1 = int('331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101331214303223312402430402404413033243132101010422240133122211400434023222214231402403403200012221023341333340042343122302113410210110221233241303024431330001303404020104442443120130000334110042432010203401440404010003442001223042211442001413004',5)
c1 = int('310020004234033304244200421414413320341301002123030311202340222410301423440312412440240244110200112141140201224032402232131204213012303204422003300004011434102141321223311243242010014140422411342304322201241112402132203101131221223004022003120002110230023341143201404311340311134230140231412201333333142402423134333211302102413111111424430032440123340034044314223400401224111323000242234420441240411021023100222003123214343030122032301042243',5)

N2 = int('302240000040421410144422133334143140011011044322223144412002220243001141141114123223331331304421113021231204322233120121444434210041232214144413244434424302311222143224402302432102242132244032010020113224011121043232143221203424243134044314022212024343100042342002432331144300214212414033414120004344211330224020301223033334324244031204240122301242232011303211220044222411134403012132420311110302442344021122101224411230002203344140143044114',5)
c2 = int('112200203404013430330214124004404423210041321043000303233141423344144222343401042200334033203124030011440014210112103234440312134032123400444344144233020130110134042102220302002413321102022414130443041144240310121020100310104334204234412411424420321211112232031121330310333414423433343322024400121200333330432223421433344122023012440013041401423202210124024431040013414313121123433424113113414422043330422002314144111134142044333404112240344',5)

N3 = int('332200324410041111434222123043121331442103233332422341041340412034230003314420311333101344231212130200312041044324431141033004333110021013020140020011222012300020041342040004002220210223122111314112124333211132230332124022423141214031303144444134403024420111423244424030030003340213032121303213343020401304243330001314023030121034113334404440421242240113103203013341231330004332040302440011324004130324034323430143102401440130242321424020323',5)
c3 = int('10013444120141130322433204124002242224332334011124210012440241402342100410331131441303242011002101323040403311120421304422222200324402244243322422444414043342130111111330022213203030324422101133032212042042243101434342203204121042113212104212423330331134311311114143200011240002111312122234340003403312040401043021433112031334324322123304112340014030132021432101130211241134422413442312013042141212003102211300321404043012124332013240431242',5)

e=3

n = [N1,N2,N3]
c = [c1,c2,c3]


def CRT(a,n):
    sum = 0
    N = reduce(lambda x,y:x*y,n)   # ni 的乘積,N=n1*n2*n3

    for n_i, a_i in zip(n,a):    # zip()將對象打包成元組
        N_i = N // n_i           #Mi=M/ni
        sum += a_i*N_i*invert(N_i,n_i)   #sum=C1M1y1+C2M2y2+C3M3y3
    return sum % N 

x = CRT(c,n)

m = iroot(x,e)[0]           #開e次方根
print(n2s(m))               #數值轉字符串


10. 低解密指數攻擊


背景:

與低加密指數相同,低解密指數可以加快解密的過程,但同時也帶來了安全問題。Wiener表示如果滿足:

那麼一種基於連分數(數論中的問題)的特殊攻擊類型,就可以危害RSA的安全,此時需要滿足:


如果滿足上述條件,通過Wiener Attack 可以在多項式時間中分解n。

下載工具:rsa-wiener-attack

github上有公開的攻擊代碼。

將解密的代碼放入wiener-attack的目錄下即可。

下載網址: https://github.com/pablocelayes/rsa-wiener-attack

低解密指數攻擊的特點:

e看起來特別大就行,且n分解無望

例題:

BUU rsa2
https://buuoj.cn/challenges#rsa2

題目:

N = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170646906557242832893914902053581087502512787303322747780420210884852166586717636559058152544979471
e = 46731919563265721307105180410302518676676135509737992912625092976849075262192092549323082367518264378630543338219025744820916471913696072050291990620486581719410354385121760761374229374847695148230596005409978383369740305816082770283909611956355972181848077519920922059268376958811713365106925235218265173085

import hashlib
flag = "flag{" + hashlib.md5(hex(d)).hexdigest() + "}"

解題步驟:

wiener攻擊腳本用於求出d的值
(注意,這裡要將攻擊腳本和rsa-wiener-attack的py文件放在同一個目錄下)


攻擊腳本:

import  RSAwienerHacker
n = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170646906557242832893914902053581087502512787303322747780420210884852166586717636559058152544979471
e = 46731919563265721307105180410302518676676135509737992912625092976849075262192092549323082367518264378630543338219025744820916471913696072050291990620486581719410354385121760761374229374847695148230596005409978383369740305816082770283909611956355972181848077519920922059268376958811713365106925235218265173085

d =  RSAwienerHacker.hack_RSA(e,n)
if d:
    print(d)

得到d後在python2的環境下對其進行MD5哈希即可得到flag

後記:

以上分享了一些基本的RSA加密算法,如果有錯誤的地方,歡迎大家留言指正,我們一起學習進步。後面我會給大家分享更高階的加密算法,和我個人認為很好的一些題目,感謝大家的閱讀。

文章中可能有因為不同平台間編碼格式不同的緣故,而導致部分公式或者圖片顯示不出來或者是影響閱讀。有問題可以在下面留言

關鍵字: