RSA大礼包

虚假的本科教学奖项:👍👍👍

真实的本科教学奖项:https://www.tr0y.wang/2017/11/06/CTFRSA/

关于RSA

https://zhuanlan.zhihu.com/p/315747015

https://zhuanlan.zhihu.com/p/21858074

先看了博客最后附的知乎链接,跟着思路走了一下

咱们要做的只是分解模数n

但是将两个足够大的素数的乘积再次分解成为了问题

如果 n 比较小,那么可以通过工具进行直接 n 分解,从而得到私钥。如果 n 的大小小于 256bit,那么我们通过本地工具即可爆破成功。例如采用 windows 平台的 RSATool 2v17,可以在几分钟内完成 256bit 的 n 的分解。

素数分解问题是困难的,但是可以通过计算机进行暴力分解。通常意义上来说,一般认为 2048bit 以上的 n 是安全的。现在一般的公钥证书都是 4096bit 的证书

如果两个n直接使用了相同的素数

gcd(n1,n2)

import gmpy2
# import math
import time
n1 = 9051013965404084482870087864821455535159008696042953021965631089095795348830954383127323853272528967729311045179605407693592665683311660581204886571146327720288455874927281128121117323579691204792399913106627543274457036172455814805715668293705603675386878220947722186914112990452722174363713630297685159669328951520891938403452797650685849523658191947411429068829734053745180460758604283051344339641429819373112365211739216160420494167071996438506850526168389386850499796102003625404245645796271690310748804327
n2 = 13225948396179603816062046418717214792668512413625091569997524364243995991961018894150059207824093837420451375240550310050209398964506318518991620142575926623780411532257230701985821629425722030608722035570690474171259238153947095310303522831971664666067542649034461621725656234869005501293423975184701929729170077280251436216167293058560030089006140224375425679571181787206982712477261432579537981278055755344573767076951793312062480275004564657590263719816033564139497109942073701755011873153205366238585665743
# t1=time.time()
p = gmpy2.gcd(n1, n2)
print ('gcd(n1, n2):\n', p)

q1 = n1 / p
q2 = n2 / p

print ('q1 is:\n', q1)
print ('q2 is:\n', q2)
# t2=time.time()
# print(t2-t1)

gmpy2的gcd要快很多。。

大数分解

https://zhuanlan.zhihu.com/p/267884783

https://blog.csdn.net/weixin_42251364/article/details/95462358

Pollard-Rho算法

rho算法其实是一种概率上的算法,虽然是靠概率,但是其准确率非常高(99.9%),更重要的是,该算法效率极高。其主要基于密码学当中的一个“生日悖论“来进行算法的设计。简单来讲就是,我们将N的两个因子x和y(就假设它有两个)从一大堆数里挑出来的概率非常小,但是如果我们挑满足x-y等于某个数的话,概率就要大很多。更进一步,如果我们找gcd(|x-y| ,N)呢?那么概率就会更大,就是这么个道理。

关于Rho算法,要注意有可能会进入死循环,也就是说我们要在算法中对其进行判圈,具体的做法是,每次a=f(a),再找一个b=f(f(b)),如果有一个时刻a=b那么就退出循环,因为b是以两倍的速度走得,当b追上了a,那么b至少已经走完一圈了。
原文链接:https://blog.csdn.net/The__Apollo/article/details/80279716

令p为n的最小素因子,存在x,x',x=x'(mod p),使得|x-x'|整除于n(),gcd(|x-x'|,n)

xi形成一个序列,而序列的优化则是Rho名字的来源

import math
from random import randint
from gmpy2 import *

n = 0x4333AF6B43F36028D8D9650EC3EED3238541EE5C15E626C58C9EC33674A6D08D5B1F2580A1A0B07E9D853536CD994E197889D122701A62BB2A9E79559F3D5281014535F6C54F83CA8D9700EEB67D99AF318D20A5150AD46D622A6A12DE0A758EE7DF75F5D10F2FE2585F2348537787063321FFDAC91BB3C3D1D88CBD04A824ED
x2 = 1
c = 7

while 1:
    x1 = randint(1, n)
    x2 = pow(x2, 2, n) + c % n

    fac = gcd(abs(x1 - x2), n)

    if fac > 1 and is_prime(fac):
        print (fac)
        break

print(n / fac)

Poland's p-1

需要分解n,则思想是需要n的因数。如果不能直接求因数则需要找一个不和n互质的数字num(暂定)从而通过gcd(n,num)求得n的因数之一

通过费马定理我们可以得知2^p-1=1(mod p),可以写作(2^p-1)-1=p*s,那么num=gcd(n,p)=gcd(n,p*s)

但是p的值未知,p-1的值未知,我们可以分析p-1可能有的最大素因数B(开方之后筛选最大素数?),则B!是p-1的倍数,2B!是2p-1的倍数(指数幂)

from gmpy2 import *

def PollardRho_p_1(Q,N):
    a = i = 2
    while 1:
        a = pow(a, i, N)//a^i(mod N)
        d = gcd(a - 1, N)
        if d != 1:
            return d
        
        i += 1

低加密指数攻击

低加密指数攻击:
假设e=3, 公钥中的加密指数e很小,但是模数n很大
有RSA加密公式: C=M^e % n (C密文,M明文)
则:
当M^e < n 时,
C = M^e ,所以对C开方就能得到M

当M^e > n 时,此时用爆破的方法
假设我们  M^e / n 的商为 k 余数为C,
则M^e = kn + C,对K进行爆破,只要k满足 kn + C能够开e次方就可以得明文

# -*- coding: cp936 -*-
import gmpy2

e = 3
# 读入 n, 密文
n= 22885480907469109159947272333565375109310485067211461543881386718201442106967914852474989176175269612229966461160065872310916096148216253429849921988412342732706875998100337754561586600637594798877898552625378551427864501926224989873772743227733285336042475675299391051376624685754547818835551263597996620383338263448888107691240136257201191331617560711786674975909597833383395574686942099700631002290836152972352041024137872983284691831292216787307841877839674258086005814225532597955826353796634417780156185485054141684249037538570742860026295194559710972266059844824388916869414355952432189722465103299013237588737
c= 15685364647213619014219110070569189770745535885901269792039052046431067708991036961644224230125219358149236447900927116989931929305133870392430610563331490276096858863490412102016758082433435355613099047001069687409209484751075897343335693872741

print ('n=', n)
print ('c=', c)

print '[+]Detecting m...'
result = gmpy2.iroot(c, 3)

print '  [-]The c has cubic root?', result[1]
if result[1]: print '  [-]The m is:', '{:x}'.format(result[0]).decode('hex')

print '[!]All Done!'

M^e足够小即可以直接爆破

低加密指数广播攻击

https://blog.csdn.net/ChaoYue_miku/article/details/12576796

所谓广播,就是发送方将一份明文进行多份加密,但是每份使用不同的密钥,即密钥中的模数n不同,但是指数e相同且很小,因此我们只要得到多份密文和对应的模数n就可以利用中国剩余定理进行解密。

CRT

# 信安数基CRT代码
import sys

def Get_Mi(m_list, M):  # 获取所有的Mi
    M_list = []
    for mi in m_list:
        M_list.append(M // mi)
    return M_list


def Get_ei_list(M_list, m_list):  # 取所有的Mi的逆元
    ei_list = []
    for i in range(len(M_list)):
        ei_list.append(Get_ei(M_list[i], m_list[i])[0])
    return ei_list


def Get_ei(a, b):
    # 计算ei

    if 0 == b:
        x = 1;
        y = 0;
        q = a
        return x, y, q
    xyq = Get_ei(b, a % b)
    x = xyq[0];
    y = xyq[1];
    q = xyq[2]
    temp = x;
    x = y;
    y = temp - a // b * y
    return x, y, q


def crt(a_list, m_list):
    # 计算中国剩余定理,返回计算结果
    M = 1  # M是所有mi的乘积
    for mi in m_list:
        M *= mi
    Mi_list = Get_Mi(m_list, M)
    Mi_inverse = Get_ei_list(Mi_list, m_list)
    x = 0
    for i in range(len(a_list)):  # 开始计算x
        x += Mi_list[i] * Mi_inverse[i] * a_list[i]
        x %= M
    return x

if __name__ == '__main__':
    filename = input()
    f = open(filename)
    lines = f.readlines()
    num = []
    a_list = []
    m_list = []
    i = 0
    for line in lines:
        num.append(line.strip())
a_list = num[:3]
m_list = num[3:6]
m_list = [i for i in m_list if(len(str(i))!=0)]

a_list = list(map(int,a_list))
print(a_list)
m_list = list(map(int,m_list))
print(m_list)
print(crt(a_list, m_list))
import gmpy2
from functools import reduce
from Crypto.Util.number import long_to_bytes


# 中国剩余定理
def CRT(cipher, n):
    N = reduce(lambda x, y: x * y, (i for i in n))
    result = 0
    data = zip(cipher, n)
    for ci, ni in data:
        Ni = N // ni
        di = gmpy2.invert(Ni, ni)
        result += ci * Ni * di
    return result % N, N

x, N = CRT(c, n)

m = gmpy2.iroot(gmpy2.mpz(x), e)[0]

print(m)
print(long_to_bytes(m))
# 读入 e, n, c e = 10 c = [ 7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042, 21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461, 6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983, 4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052, 22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672, 17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087, 1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639, 15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352, 8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797, 13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247] n = [ 25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803, 23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193, 18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623, 23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723, 31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493, 22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949, 25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043, 32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047, 52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553, 30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621]
代码运行需要details中具体的e,n,c的值,因篇幅过大进行收起

m,e相同,e和模数n已知,通过CRT求得m^e

iroot(m^e,e)得到m

Coppersmith’s Method

https://www.anquanke.com/post/id/211028

格基规约算法

https://blog.csdn.net/qq_42667481/article/details/118332181

coppersmith 定理指出在一个 e 阶的 mod n 多项式 f(x)中,如果有一个根小于 n^(1/e),就可以运用一个 O(log n)的算法求出这些根。

共模攻击(使用相同的n)

如果在 RSA 的使用中使用了相同的模 n 对相同的明文 m 进行了加密,那么就可以在不分解 n 的情况下还原出明文 m 的值。即:

c1≡m^e1 mod n

c2≡m^e2 mod n

gcd(e1,e2)=1,存在s1e1+s2e2=1

https://zhuanlan.zhihu.com/p/451050633

对于不都为零的整数 a 和 b,gcd(a,b) 表示 a 和 b 的最大公约数。那么一定存在整数 x,y使得以下等式成立:

Gcd(a,b)=ax+by

则c1=m^e1 mod n,c2=m^e2 mod n

c1s1*c2s2=m^(s1e1+s2e2)=m (mod n)

n = 158052722013789461456896900244510199169216575693048895162538548356466884311543740968048825149608833390255268602486435690724338965409521812963337715301197225841194835534751041470231293288252951274190599189716955573428884560130364021535005115652592074445852835422027406556727605302404510264249211145063332337043
e = [665213, 368273]
c = [16698617641888248664694980135332125531792692516788088682722832061393117609508765284473236240256421599515450690670639565968165473479697383505401285976148490839526672808730165847471005704945978274496508928460578173068717106075169723401049489389383596761956301440156581021583368058047939083755488885694261340425L, 59192887933967939708054321952273893559113509451228797382728687616356609407020086787061368452871936378934964292805289941535766263083244529814852043063188312786173717046316177403357053871483983775362121186037776932260378728059531236711960979620603784044468207000654149190295060179235411429700710154759043236436L]
求 m

# -*- coding: cp936 -*-
import time
import gmpy2

n = 158052722013789461456896900244510199169216575693048895162538548356466884311543740968048825149608833390255268602486435690724338965409521812963337715301197225841194835534751041470231293288252951274190599189716955573428884560130364021535005115652592074445852835422027406556727605302404510264249211145063332337043
e = [665213, 368273]
c = [16698617641888248664694980135332125531792692516788088682722832061393117609508765284473236240256421599515450690670639565968165473479697383505401285976148490839526672808730165847471005704945978274496508928460578173068717106075169723401049489389383596761956301440156581021583368058047939083755488885694261340425L, 59192887933967939708054321952273893559113509451228797382728687616356609407020086787061368452871936378934964292805289941535766263083244529814852043063188312786173717046316177403357053871483983775362121186037776932260378728059531236711960979620603784044468207000654149190295060179235411429700710154759043236436L]

print '[+]Detecting m...'
time.clock()

c1 = c[0]
c2 = c[1]

e1 = e[0]
e2 = e[1]

s = gmpy2.gcdext(e1, e2)

s1 = s[1]
s2 = s[2]

# 求模反元素
if s1 < 0:
    s1 = -s1
    c1 = gmpy2.invert(c1, n)

elif s2 < 0:
    s2 = -s2
    c2 = gmpy2.invert(c2, n)

m = pow(c1, s1, n) * pow(c2, s2, n) % n
print '  [-]m is:' + '{:x}'.format(int(m)).decode('hex')
print '\n[!]Timer:', round(time.clock(),2), 's'
print '[!]All Done!'

低解密指数攻击

image

# 展开为连分数
def continuedFra(x, y):
    cF = []
    while y:
        cF += [x / y]
        x, y = y, x % y
    return cF

def Simplify(ctnf):
    numerator = 0
    denominator = 1
    for x in ctnf[::-1]:
        numerator, denominator = denominator, x * denominator + numerator
    return (numerator, denominator)

# 连分数化简
def calculateFrac(x, y):
    cF = continuedFra(x, y)
    cF = map(Simplify, (cF[0:i] for i in xrange(1, len(cF))))
    return cF
# 连分数求解和化简

最终实现wiener‘s attack的部分为

def wienerAttack(e, n):
    for (d, k) in calculateFrac(e, n):
        if k == 0: continue
        if (e * d - 1) % k != 0: continue

        phi = (e * d - 1) / k
        p, q = solve_pq(1, n - phi + 1, n) #根据韦达定理求解出来的p,q值
        if p * q == n:
            return abs(int(p)), abs(int(q))
    print 'not find!'

关于赛题

赛题 https://blog.csdn.net/xiewenbonb/article/details/122396997

实现(直系白毛学姐博客) https://blog.csdn.net/m0_63571390/article/details/122375466

posted @ 2022-11-10 12:33  noobwei  阅读(122)  评论(0编辑  收藏  举报