【密码学RSA】共模攻击+维纳攻击+进制转换的低指数广播攻击+dp,dq已知+n为p的r次方的脚本

本文深入探讨了RSA加密算法的几种破解方法,包括共模攻击、维纳攻击、低指数广播攻击以及利用中国剩余定理。通过实例展示了如何在不同情况下利用数学工具来解密RSA加密信息,如计算模逆元、欧拉函数和中国剩余定理的应用。同时,提到了当n由三个素数构成时的特殊情况及其处理方式。
摘要由CSDN通过智能技术生成

1.共模攻击:

import gmpy2
from Crypto.Util.number import *


def Commodulus(e1, e2, n, c1, c2):
    g, s, t = gmpy2.gcdext(e1, e2)  #g=e1*s+t*e2
    m = gmpy2.powmod(c1, s, n) * gmpy2.powmod(c2, t, n) % n #幂取模,结果是 x = (c^t) mod n
    print(long_to_bytes(m))


n = 16083214012638388663784521954622543045708903686589880528711880230698602817697997380543200768660883701383088153716426277227007488632840757171121370309401375874563915993808574166897288857497860302677982653939994860362835482720701397641826151564818523685533076796342606201005914811273943686796396237073344829728184519773946965610605096544342524362362461602653060886529901512437308424885213454571496693957407506264908554886708080545957821146720531872251855895768339549873719942212035943303966017435806880270694222061139516388747219293476787639922972482077360726936780982113094370207160279202403541678219198642190754621383
e1 = 2333
e2 = 23333
c1 = 4944405402225804339898252584518133767856406646249564382227685038047513515431245453943040701069968915476361792382122280755353274617424667793336796623723914559575269601832955753855993184244386734062811836260918753012696477615577988449692691314668133500013048312665481402135382287614750525215272490220938713668665692329719115647760562353429578730365840277086852860597005486082956680256590327407559949649584759812170174311526394806043211343044265907044168640909953661809811847927388079078303020542880557247053604834432185767108642131078127156691025192078511566714696010552401059130895526376490822816868319766073162568049
c2 = 11863581449110679506024274134666181367837473368100054843316578483117405767899134169014721870302871234881206143904730705290442330442439596377140286127278773898090404689672402351240966190856406939435251619065783216442053701246713535711655991342135264010287996212379191016108670983776732911762966210503499355546289551877817318255927731876830493191794531458129659943130330960702384582747657461399459306963037530735867297905149683168674083995472852266279410443295140541962184944033145678873265842380004922976892553624101873405742602120680775552886212919350450731408676621073336654797824300438267183415076998086836456080800
Commodulus(e1, e2, n, c1, c2)

2.维纳攻击:适用于e过大,n无法分解情况

from Crypto.Util.number import *
'''
Created on Dec 14, 2011

@author: pablocelayes
'''


def egcd(a, b):
    '''
    Extended Euclidean Algorithm
    returns x, y, gcd(a,b) such that ax + by = gcd(a,b)
    '''
    u, u1 = 1, 0
    v, v1 = 0, 1
    while b:
        q = a // b
        u, u1 = u1, u - q * u1
        v, v1 = v1, v - q * v1
        a, b = b, a - q * b
    return u, v, a


def gcd(a, b):
    '''
    2.8 times faster than egcd(a,b)[2]
    '''
    a, b = (b, a) if a < b else (a, b)
    while b:
        a, b = b, a % b
    return a


def modInverse(e, n):
    '''
    d such that de = 1 (mod n)
    e must be coprime to n
    this is assumed to be true
    '''
    return egcd(e, n)[0] % n


def totient(p, q):
    '''
    Calculates the totient of pq
    '''
    return (p - 1) * (q - 1)


def bitlength(x):
    '''
    Calculates the bitlength of x
    '''
    assert x >= 0
    n = 0
    while x > 0:
        n = n + 1
        x = x >> 1
    return n


def isqrt(n):
    '''
    Calculates the integer square root
    for arbitrary large nonnegative integers
    '''
    if n < 0:
        raise ValueError('square root not defined for negative numbers')

    if n == 0:
        return 0
    a, b = divmod(bitlength(n), 2)
    x = 2 ** (a + b)
    while True:
        y = (x + n // x) // 2
        if y >= x:
            return x
        x = y


def is_perfect_square(n):
    '''
    If n is a perfect square it returns sqrt(n),

    otherwise returns -1
    '''
    h = n & 0xF  # last hexadecimal "digit"

    if h > 9:
        return -1  # return immediately in 6 cases out of 16.

    # Take advantage of Boolean short-circuit evaluation
    if (h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8):
        # take square root if you must
        t = isqrt(n)
        if t * t == n:
            return t
        else:
            return -1

    return -1


def rational_to_contfrac(x, y):
    '''
    Converts a rational x/y fraction into
    a list of partial quotients [a0, ..., an]
    '''
    a = x // y
    pquotients = [a]
    while a * y != x:
        x, y = y, x - a * y
        a = x // y
        pquotients.append(a)
    return pquotients


# TODO: efficient method that calculates convergents on-the-go, without doing partial quotients first


def convergents_from_contfrac(frac):
    '''
    computes the list of convergents
    using the list of partial quotients
    '''
    convs = []
    for i in range(len(frac)):
        convs.append(contfrac_to_rational(frac[0:i]))
    return convs


def contfrac_to_rational(frac):
    '''Converts a finite continued fraction [a0, ..., an]
     to an x/y rational.
     '''
    if len(frac) == 0:
        return (0, 1)
    num = frac[-1]
    denom = 1
    for _ in range(-2, -len(frac) - 1, -1):
        num, denom = frac[_] * num + denom, num
    return (num, denom)


def hack_RSA(e, n):
    '''
    Finds d knowing (e,n)
    applying the Wiener continued fraction attack
    '''
    frac = rational_to_contfrac(e, n)
    convergents = convergents_from_contfrac(frac)

    for (k, d) in convergents:
        # check if d is actually the key
        if k != 0 and (e * d - 1) % k == 0:
            phi = (e * d - 1) // k
            s = n - phi + 1
            # check if the equation x^2 - s*x + n = 0
            # has integer roots
            discr = s * s - 4 * n
            if (discr >= 0):
                t = is_perfect_square(discr)
                if t != -1 and (s + t) % 2 == 0:
                    print("Hacked!")
                    return d


if __name__ == "__main__":
    N = 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
    e = 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619
    c = 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192
    d = hack_RSA(e, N)
    m = pow(c, d, N)
    # import hashlib
    # flag = "flag{" + hashlib.md5(hex(d)[:-1].encode()).hexdigest() + "}"
    #     # print(flag)
    print (d)
    print(long_to_bytes(m))

3.低指数广播攻击:利用中国剩余定理(py2的脚本)

# -*- coding: UTF-8 -*-
import gmpy2
import libnum

def CRT(data):
	sum = 0
	m = 1
	for n in data:
		m = m*n[0]
	for n,c in data:
		m1 = m/n
		mr = gmpy2.invert(m1,n)
		sum = sum+mr*m1*c
	return sum%m
#观察发现数字最大为4,所以需要先将5进制数字转化为10进制
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]
data = zip(n,c)
m_e = CRT(data)
m = gmpy2.iroot(m_e,e)[0]
print libnum.n2s(m)

4.已知dp,dq:

#coding:utf-8

from Crypto.Util.number import *

def RSA_dpdq(p,q,c,dp,dq):
    m1 = pow(c,dp,p)
    m2 = pow(c,dq,q)
    qinv = inverse(q,p)
    h = (qinv*(m1 - m2)) % p
    m = m2 + h * q
    print (long_to_bytes(m))
p= 179361074413263697829999005814546179096338251344605155492350917550408915635839919536158715514795196578473034682853650147697648138514548794413428404094860743787113850190924056019307495205914830488435938921721750461015019866101069038340890406381470474569514245532335549692911319669909660529671092887579254089841
q= 173835595299488471664720455055270783584907101280431946406552831195941371196026061249385544447021385360873734720942054760579124666786102164766159947255113097404541948119682544948561794690528398106216930762814472842260707467541709548511410564591303589518935143237786002751598606698519725781106792846894755964463
dq= 85420472573122461227866053292032597075977665893083760350284989789494421746445874490367457670810026308216393074953353548525109949634246824147114072072320402044888672005832685010352686821395189474840319793180604596062740486819860754997352118987722062298667735063088948725338076660804267040828282601300009476777
dp= 40173355681711061239399963476383163143798910409195707424389568010779444781093034146684678655441638930305105148383489181959103667016419148773894373311388389124479976302738517452849760015374884366689826318445360254775767530013543378760180207749417963840363452861271549413953114445803193721333627912427725876753
c= 9766441985129844560019248100335265224864673427740570851739663484929172951774608983863007909781231149939524112862707457126539070597704329598419487190548565088644236637208267519648456264153799758486217082215926007234828186809396123615231707592709578628053901648532553911011386785261328710958617957713754641724108641983981428692803380139764569751627517242442987987996276078388547228292107648936726531469395113308901910257869544546190203266474033877973975761458955817124112794966846072260497147758360059384239579835093759557643039752186121549033766866833574085918197046373876734103651933335070704951351790263619835894130

print (RSA_dpdq(p,q,c,dp,dq))

5.还有一类题型,n进行分解的时候,可以分解成3个素数p,q,r,此时只需要计算phi(n)时,让phi(n)=(p-1)*(q-1)*(r-1)即可

6.n分解出来的p相同,则n时p的r次方,原理:

欧拉函数φ(n)的定义是小于n的自然数中与n互质的数的个数。

p^r 质因数就只有p,那么不与它互质的数都含有p,
 
和它不互质的数的个数:p^r/p=p^r-1/p=p^{r-1} 
 
剩下就是互质的数,其个数就是:p^r-p^{r-1} 
 
则有 φ(n)=p^r-p^{r-1}

首先进行分解发现p相同,有4个:

所以脚本为:

import libnum
import gmpy2

n= 8728589998777982696703940018364436561769679950282731827002399945820519626630239261319979808404426258563397495169681599073815794013914620870334635363415860236091892304738823310165557915602091780358896749588269684770012690738058843365220895883269596248137195018693952271988305757700968804667123708093004971368530057417274917306936884549277317220129475657174220318156910434608983375960022033492495856119260793686742733850272256173907450229747656796655716934718664918221274680117850849415470788295824869164880840382356808898064880080213936002040667302618190824116124200896763471960023079024139735441967770305579426290561
e= 65537
c= 1465588858007680887950755019340127657311002100000046397447311397428442921759230618584011648408572671005139182825463405538111012102590465761751745664370670840392175162154595485471520075855504299902170889163643118381246916627503015519764730758098584564744019290491548278499257338223884379516365562400137688156919398735700425005486588919949594095827647523977040403331416767981921771152227523364146160326575910559036981829702510036555588506777191403921818438886116726068926492791242805894408776798336721989949917577680258986296019916893622187881181000328457760294312967378439822673204825874847498815102583233675832797900

#分解n
#yafu-x64.exe  factor()
p= 9665760358496789369385498497685947307023279674165117573518923758539132148704165168622034787978336928985555102380665909335419628100028226879863551889800991
phi_n=p**4-p**3
#求逆元
d=libnum.invmod(e,phi_n)
m=pow(c,d,n)
print(m)
#数字转字节,转字符串
print(libnum.n2s(int(m)).decode())
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值