RSA加密方式及常见攻击手法

RSA:

RSA加密操作流程:

第一步:选取一对不相等且足够大的质数,记做p和q;

第二步:计算p和q的乘积n;n=pq;

第三步:计算欧拉函数:phi(n)=(p-1)(q-1)

第四步:选一个与phi(n)互素的整数e,1<e<phi(n)

第五步:计算出e对phi(n)的模反元素d,de mod phi(n)=1;

第六步:公钥—K1=(e,n);

第七步:私钥—K2=(d,n);

加密:明文M: M^e mod n = C

解密:密文C: C^d mod n = M

RSA普通破解方式

1.RSA安全位数:

RSA算法的安全性取决于其底层的数学难题—大整数因数分解问题的难度。目前最新的大整数分解的世界记录为829-bits().

请添加图片描述

2.直接分解:

对于一些不安全/位数比较小的素数(N),以当前的算法和算力很容易将其分解。通常在300bits以下的模数均可在较短的时间内被分解,一些不安全的素数也会很快被特定的算法所分解掉

CTF中常见的分解手法:

在线网站:factordb.com(类似于一个映射表,存放前人已经分解过的大素数的分解结果,然后根据你的输入进行查找)

在线网站:https://www.alpertron.con.com.ar/ECM.HTM(运行ECM分解算法来计算)

工具:yafu

SageMath内置的factor函数:

操作:

1.判断n的位数:
n=0x564656435135468436651321354368368154136547683543

n.bit_length()
2.求p和q

因为n的位数比较小直接通过在线网站可以获取到n的分解结果p和q

3.求解明文m

之后的步骤相当于已知p和q,c求明文m

#n,p和q已知可推出
#公钥e,密文c知道

from Crypto.Util.number import *
d=inverse(e,(p-1)*(q-1))
m = pow(c,d,n)

long_to_bytes(m)
print(long_to_bytes(m))

3.p,q相近:

在计算RSA模数的时候,生成两个素数靠的很近,这个时候也很不安全的。

例如生成:

生成代码:

p和q相近的情况:

from Crypto.Util.number import getPrime,isPrime

def nextPrime(p):
	p=(p+2)|1 #一般p是一个素数
   	while not isPrime(p):
        p+=2
   	return p

def genKey(bits):
    p=getPrime(bits)
    q=nextPrime(p)
    e=65537
    n=p*q
    return n
   

这样的话一般来说生成的两个数p和q相差仅仅不过几百或者几千

破解原理:

此时,会有如下关系:
p 2 < n < q 2 p^2 < n <q^2 p2<n<q2
如果对n开近似平方根:


p < √ n < q p<√n<q p<n<q
则近似平方根必然落在p和q之间,并且距离p和q很近,可以通过穷举的方式找到p和q。

4.(模不互素)

当两个模数共有一个素数时,有如下关系:

​ n1=p*q1

​ n2=p*q2

可以对n1和n2求最大公约数(gcd),这两者的最大公约数即为其中的一个素因子p,从而可以分解为这两个模数。

#案例代码:
p=getPrime(1024)
q1=getPrime(1024)
q2=getPrime(1024)

n1=p * q1
n2=p * q2

#解题代码

from Crypto.Util.number import GCD

p=GCD(n1,n2)
q1=n1 // p	#整除
q2=n2 // p

5.共模攻击:

两个用户使用相同的模数,不同的私钥,加密同一明文消息时存在“共模”

#案例代码

p = getPrime(512)
q = getPrime(512)
n = p*q
e1 = getPrime(64)
e2 = getPrime(64)
m = bytes_to_long(flag)

c1 = pow(m,e1,n)
c2 = pow(m,e2,n)

RSA解密可以看作是,对C开e次方根;或者说是,找到一个d,使得
( m e ) d ≡ m 1 ( m o d n ) (m^e)^d≡m^1(mod n) (me)dm1(modn)
目的是为了让m右上角的指数变成1。

这在只有一个 c ≡ m e ( m o d n ) c≡m^e(mod n ) cme(modn)时是很难得的,因此也被称为RSA Problem

目前已经有了两组这样的关系:

m^e1≡c1(mod n )

m^e2≡c2(mod n )

可以通过扩展欧几里得算法计算出

re1 + se2 = 1

从而有:

C1^r * C2^s ≡ m^(re1 + se2)≡m^1(mod n )

使得右上角的指数变成1

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, r = divmod(a, b)
        u, u1 = u1, u - q * u1
        v, v1 = v1, v - q * v1
        a, b = b, r
    return u, v, a

r, s, _ = egcd(e1, e2)
if r < 0:
    r = -r
    c1 = inverse(c1, n)
else:
    s = -s
    c2 = inverse(c2, n)

m = pow(c1, r, n) * pow(c2, s, n) % n
print(long_to_bytes(m))

RSA指数相关利用手法:

1.小公钥指数的利用:

1.引言:

RSA算法通过模幂运算对明文信息加密,当指数逐渐增大时,模运算将会发挥作用,将整数的幂运算的结果截断到有限的范围内。

但是当指数太小时,模运算还未发挥作用,幂运算就已经结束了。此时的加密结果并没有被解截断,即是原本的幂运算,此时就不存在“加密”效果了。
C ≡ m e ( m o d n ) = = > c = m e C≡m^e (mod n ) ==> c =m^e Cme(modn)==>c=me

2.什么情况下会发生小公钥指数利用?

当m较小时,即m^e < n时,就会存在这种利用。

另外,即使m^e稍比n大一点点,也可以通过穷举的方式对其尝试开根。

c ≡ m e ( m o d n ) ⇒ c = m e − k ⋅ n c \equiv m^e \pmod{n} \Rightarrow c = m^e - k \cdot n cme(modn)c=mekn

可以从0开始穷举k,并对k·n+c尝试开e次方根,若可以开出来根,则说明成功解密。(对于正常的RSA加密,k一般很大,无法被穷举)

3.代码:
from sympy import nth_root

# 假设这些值是已知的
c = 123456789  # 密文
e = 3          # 公钥指数
n = 323         # 模数

# 尝试穷举k来破解RSA加密
for k in range(0, 1000000):
    tmp = k * n + c
    root = nth_root(tmp, e, 1)[0]  # 计算e次方根
    if root.is_integer and root > 0:  # 检查根是否为正整数
        print(f"成功解密: 明文m = {
     int(root)}")
        break
else:
    print("在给定的范围内未能成功解密。")

2.已知e和d分解n

RSA算法若能够知道加密指数e和解密指数d,则可以完成对n的分解。

根据e和d的关系有

e ⋅ d ≡ 1 ( mod ϕ ( n ) ) e \cdot d \equiv 1 (\text{mod} \phi(n)) ed1(modϕ(n))

同样可以化为

⇒ e ⋅ d = 1 + k ⋅ ϕ ( n ) \Rightarrow e \cdot d = 1 + k \cdot \phi(n) ed=1+k

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值