羊城杯2021 Crypto wp

本文介绍了RSA加密算法的原理及其在解密过程中的应用。针对给定的两道RSA题目,详细阐述了解题思路和步骤,包括利用两个模数的公约数分解大素数,以及通过数学公式推导解密密文的方法。通过对题目中加密过程的分析,展示了如何利用Rho算法快速找到大数的因子,从而完成解密。这些案例揭示了RSA算法在信息安全中的重要性和实际应用。
摘要由CSDN通过智能技术生成

1.bigrsa

题目

from Crypto.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

解题

大致意思是题目给出两个模数,对一个明文进行两次加密。

我们可以利用这两个模数来求出他们的公约数,这样就可以分解模数。
之后只要对密文进行两次解密就行了!

代码:

from Crypto.Util.number import *
import gmpy2

n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264
p1 = p2 = gmpy2.gcd(n1,n2)

q1 = n1 // p1
q2 = n2 // p2
d1 = gmpy2.invert(e,(p1-1)*(q1-1))
d2 = gmpy2.invert(e,(p2-1)*(q2-1))

m1 = pow(c,d2,n2)
m2 = long_to_bytes(pow(m1,d1,n1))

print(m2)
#b'SangFor{qSccmm1WrgvIg2Uq_cZhmqNfEGTz2GV8}'

2. RSA?

题目

import os
from Crypto.Util.number import *
'''
flag = "GWHT{xxxxxxxxx}"
p = getPrime(256)
q = getPrime(256)
n = p*q
N = (p-1)*(q-1)
e = 65537
Mx = bytes_to_long(os.urandom(30))
My = bytes_to_long(flag)
Z1 = (Mx*My)%n
inv_Z1 = inverse_mod(Z1, n)
inv_2 = inverse_mod(2, n)
X = ((Z1+inv_Z1)*inv_2)%n
Y = My
inv_Y = inverse_mod(Y, n)
a = ((inv_Z1-X)*inv_Y)%n
D = (a*a)%n

xy = lambda (x1,y1),(x2,y2) : ((x1*x2+D*y1*y2)%n, (x1*y2+x2*y1)%n)
def getloop((x,y), e):
	ret = (x, y)
	for i in range(e-1):
		ret = xy(ret, (x,y))
	return ret
	
print n 
print getloop((X, Y), e)
print a

解题

Mx = bytes_to_long(os.urandom(30))
My = bytes_to_long(flag)
Z1 = (Mx*My)%n
inv_Z1 = inverse_mod(Z1, n)
inv_2 = inverse_mod(2, n)
X = ((Z1+inv_Z1)*inv_2)%n
Y = My
inv_Y = inverse_mod(Y, n)
a = ((inv_Z1-X)*inv_Y)%n
D = (a*a)%n

通过这段代码,可以发现除 M x Mx Mx , M y My My n n n 以外的其它数,基本元素均是由 M x Mx Mx , M y My My组成,而我们要求的也是 M y My My,所以可以将 Z 1 Z_1 Z1 i n v _ Z 1 inv\_Z_1 inv_Z1 X X X Y Y Y i n v _ Y inv\_Y inv_Y a a a D D D都化成只含 M x Mx Mx , M y My My

Z 1 = M x ∗ M y % n Z_1 = Mx * My \%n Z1=MxMy%n
i n v _ Z 1 = 1 M x ∗ M y % n inv\_Z_1 = \frac{1}{Mx * My}\%n inv_Z1=MxMy1%n
X = 1 + M y 2 ∗ M x 2 2 ∗ M x ∗ M y % n X = \frac{1+My^2 * Mx^2}{2 * Mx * My} \%n X=2MxMy1+My2Mx2%n
Y = M y Y = My Y=My
i n v _ Y = 1 M y % n inv\_Y= \frac{1}{My} \%n inv_Y=My1%n
a = 1 − M y 2 ∗ M x 2 2 ∗ M x ∗ M y 2 % n a = \frac{1- My^2 * Mx^2}{2* Mx * My^2} \%n a=2MxMy21My2Mx2%n
D = ( 1 − M y 2 ∗ M x 2 2 ∗ M x ∗ M y 2 ) 2 % n D = (\frac{1- My^2 * Mx^2}{2* Mx * My^2})^2\%n D=(2MxMy21My2Mx2)2%n

同样在getloop中的循环找 xi , yi 规律,写出前几项就可以发现规律:

第一次循环,n = 1, x 1 = 1 + M x 4 ∗ M y 4 2 ∗ M y 2 ∗ M x 2 x1 = \frac{1+ Mx^4 * My^4}{2*My^2*Mx^2} x1=2My2Mx21+Mx4My4 , y 1 = 1 + M x 2 ∗ M y 2 M x y 1= \frac{1+Mx^2*My^2}{Mx} y1=Mx1+Mx2My2
第二次循环, n = 2, x 2 = 1 + M x 6 ∗ M y 6 2 ∗ M y 3 ∗ M x 3 x2 = \frac{1+ Mx^6 * My^6}{2*My^3*Mx^3} x2=2My3Mx31+Mx6My6 , y 2 = 1 + M x 2 ∗ M y 2 + M x 4 ∗ M y 4 M x 2 ∗ M y y2 = \frac{1+Mx^2*My^2+Mx^4*My^4}{Mx^2*My} y2=Mx2My1+Mx2My2+Mx4My4
第三次循环, n = 3, x 3 = 1 + M x 8 ∗ M y 8 2 ∗ M y 4 ∗ M x 4 x3 = \frac{1+ Mx^8 * My^8}{2*My^4*Mx^4} x3=2My4Mx41+Mx8My8 , y 3 = 1 + M x 2 ∗ M y 2 + M x 4 ∗ M y 4 + M x 6 ∗ M y 6 M x 3 ∗ M y 2 y3 = \frac{1+Mx^2*My^2+Mx^4*My^4+Mx^6*My^6}{Mx^3*My^2} y3=Mx3My21+Mx2My2+Mx4My4+Mx6My6
所以规律为 x n = 1 + M x 2 ∗ n + 2 ∗ M y 2 ∗ n + 2 2 ∗ M y 4 ∗ M x 4 x_n = \frac{1+ Mx^{2*n+2} * My^{2*n+2}}{2*My^4*Mx^4} xn=2My4Mx41+Mx2n+2My2n+2 , y 3 = 1 + M x 2 ∗ M y 2 + M x 4 ∗ M y 4 + . . . + M x 2 ∗ n ∗ M y 2 ∗ n M x n ∗ M y n − 1 y3 = \frac{1+Mx^2*My^2+Mx^4*My^4+...+Mx^{2*n}*My^{2*n}}{Mx^n*My^{n-1}} y3=MxnMyn11+Mx2My2+Mx4My4+...+Mx2nMy2n

n ∈ [ 1 , e − 1 ] n\in [1,e-1] n[1,e1]

这样的话,代码的内容基本上都转化为了公式,而现在就要利用公式来求 M y My My

a ∗ y n = ( 1 − M x 2 ∗ M y 2 ) ∗ ( 1 + M x 2 ∗ M y 2 + M x 4 ∗ M y 4 + . . . + M x 2 ∗ n ∗ M y 2 ∗ n ) 2 M n + 1 ∗ M y n + 1 ( m o d   n ) a * y_n = \frac{(1-Mx^2*My^2)*(1+Mx^2*My^2+Mx^4*My^4+...+Mx^{2*n}*My^{2*n})}{2M^{n+1}*My^{n+1}}(mod\ n) ayn=2Mn+1Myn+1(1Mx2My2)(1+Mx2My2+Mx4My4+...+Mx2nMy2n)(mod n)
= 1 − M x 2 ∗ n + 2 ∗ M y 2 ∗ n + 2 2 M n + 1 ∗ M y n + 1 ( m o d   n ) =\frac{1-Mx^{2*n+2} * My^{2 * n+2}}{2M^{n+1}*My^{n+1}}(mod\ n) =2Mn+1Myn+11Mx2n+2My2n+2(mod n)
= x n − ( M x ∗ M y ) n + 1 ( m o d   n ) =x_n - (Mx*My)^{n+1}(mod\ n) =xn(MxMy)n+1(mod n)
于是,我们可以利用给出的 a a a y y y x x x 来求解 ( M x ∗ M y ) n + 1 (Mx*My)^{n+1} (MxMy)n+1
因为 n ∈ [ 1 , e − 1 ] n\in [1,e-1] n[1,e1],所以当循环完成后n + 1 = e = 65537。

令C = ( M x ∗ M y ) n + 1 (Mx*My)^{n+1} (MxMy)n+1 , M = M x ∗ M y Mx*My MxMy,即有 C = M e ( m o d   n ) C = M^e(mod\ n) C=Me(mod n)
,就很容易解出M = M x ∗ M y Mx*My MxMy的值
但是我们求的是 M y My My,需要从 M x ∗ M y Mx*My MxMy中提取 M y My My
a = 1 − M y 2 ∗ M x 2 2 ∗ M x ∗ M y 2 % n a = \frac{1- My^2 * Mx^2}{2* Mx * My^2} \%n a=2MxMy21My2Mx2%n中的分母正好多出了一个 M y My My,从而推出 M y = 1 − ( M x ∗ M y ) 2 2 ( M x ∗ M y ) ∗ a My =\frac{1-(Mx*My)^2}{2(Mx*My)*a} My=2(MxMy)a1(MxMy)2
这才得到了 M y My My的值,从而也就知道了flag。

from Crypto.Util.number import *
import gmpy2
n = 13390709926509813526471364597371124446888078365567927211781799241724742352679484983709219580483800891886832613684875066109177882219522305348565532970795023
(x,y) = (5404548088049249951619519701935576492239293254135836357417714329205323074367876875480850741613547220698045360461761929952847796420174204143917852624050110, 2110372753170830610718226848526649992911771424441223687775304654852191999130502986109306355582366065947895295520226816523397652918227241733632791793362785)
a = 1762039418842677123086894939949574689744108610561557889235294034870342076452734215004689409493802437034960516295735815195656138656970901855976802991519141
p = 115718235064789220654263009993128325569382592506655305434488398268608329541037
q = 115718235064789220654263009993128324769382192706654302434478391267607309966379
e = 65537
D = (a*a)%n
Mx_My_65537 = (x - a*y)%n
d = gmpy2.invert(e,(p-1)*(q-1))
Mx_My = pow(Mx_My_65537,d,n)
My = ((1 - Mx_My**2)*(gmpy2.invert(2,n) * gmpy2.invert(Mx_My,n) * gmpy2.invert(a,n)))%n
print(long_to_bytes(My))
#flag = b'GWHT{pell_equation_is_very_interesting}'

参考:
2021羊城杯 部分CRYPTO WP

3.Easy_Rsa

题目

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

def gen_prime(nbits, gamma):
    g = getPrime(int(nbits * gamma))
    alpha = 0.5 - gamma
    while True:
        a = getRandomNBitInteger(int(alpha * nbits))
        p = 2 * g * a + 1
        if isPrime(p):
            b = getRandomNBitInteger(int(alpha * nbits))
            q = 2 * g * b + 1
            h = 2 * g * a * b + a + b
            while not isPrime(q) or isPrime(h) or gmpy2.gcd(a, b) != 1:
                b = getRandomNBitInteger(int(alpha * nbits))
                q = 2 * g * b + 1
            return p, q

def encrypt(nbits, gamma):
    p, q = gen_prime(nbits, gamma)
    n = p * q
    e = getPrime(16)
    while gmpy2.gcd(e, gmpy2.lcm(p-1,q-1)) != 1:
        e = getPrime(16)
    m = bytes_to_long(flag)
    c = pow(m, e, n)
    return n, e, c

n, e, c = encrypt(1024, 0.48)
print 'n =', n
print 'e =', e
print 'c =', c

# n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039
# e = 58337
# c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668

解题

可以看出 p − 1 p-1 p1 , q − 1 q-1 q1 具有一个很大的相同的因数,可以利用Rho算法来快速分解大数。
Rho算法
文献.pdf

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

def f(x, n):
    return (pow(x, n - 1, n) + 3) % n


def rho(n):
    i = 1
    while True:
        a = getRandomRange(2, n)
        b = f(a, n)
        j = 1
        while True:
            p = GCD(abs(a - b), n)
            print('{} in {} circle'.format(j, i))
            if p == n:
                break
            elif p > 1:
                return (p, n // p)
            else:
                a = f(a, n)
                b = f(f(b, n), n)
            j += 1
        i += 1

n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039
e = 58337
c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668

p,q = rho(n)
d = gmpy2.invert(e,(p-1)*(q-1))

m = pow(c,d,n)
print(long_to_bytes(m))
#b'SangFor{0a8c2220-4c1b-32c8-e8c1-adf92ec7678b}'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值