ECC椭圆曲线加密学习

离散对数

基础的定义和只是不应该是我多讲的,如果只是想理解解密,看wiki上面的几个就可以,但是如果想要更加深入,还是建议学习一下离散数学相关的知识点,并不是需要很深入,但知道的多在理解和记忆方面会更加深刻。 \

Baby-step giant-step暴力分解

这个解密方法我称其为大小步分解。
img
还是先看看wiki上面的说法,然后我对其的应用进行一些补充说明。首先是m的得到,如果是第一次看到这里的话,就算前面提到了n的定义,如果没有相关的离散数学基础,可能会需要比较长的时间来联系。
直接说结论就是,如果离散数学的知识被用于密码学的话,这个群肯定是一个有限群,比如素数阶群,循环群,或是可解群这样的。
现在我们看到这些方法,假设有这样一个使用离散数学加密的密文y,然后我们得知关系是y = g ^ x mod p,然后x是明文,而其是一个优先群G。现在我们带着这个问题去看这个破解方法。
因为,y,g,p都是已经知道的,然后n是p-1,所以设m就可以得到是根号p-1。然后结合x是再0到n-1,
i和j的范围不予证明,i的话直接取j假设最大最小可以证明,而j的范围则是由于其是 g(生成元) ^ j mod p,然后由于m是根号n的限制导致其被限制在m之中。
概念性和前置的东西都说明完毕,现在上代码:

def bsgs(g, y, p):
    m = int(ceil(sqrt(p - 1)))
    S = {pow(g, j, p): j for j in range(m)}
    gs = pow(g, p - 1 - m, p)
    for i in range(m):
        if y in S:
            return i * m + S[y]
        y = y * gs % p
    return None

这里有个地方没有写证明过程,就是gs的得到。
这里首先先证明:假设生成元g,和一个素数p,然后gcd(g,p)=1,则有g ^ (p-1) === 1 mod p,则可以有所以g ^ -m * 1 = g ^ -m * g ^ (p-1) mod p,则有g ^ -m = g ^ (p-1-m),则就可以,然后为何使用p-1-m而非-m,其实就是因为这样可以多个约束条件,让所求的范围更小或结果更准确。

其它两个不讲,建议之间看wiki,第一是因为是基础,第二是因为其其实不影响后面的解密。

补充:

使用sympy库discrete_log求解离散对数阶数

1.对于求解离散数学的对数问题除了上面的方法之外,还有使用python的sympy库的函数discrete_log(a,b,c)函数,其中a是其离散熟悉而中的阶,或者说模数也行,然后b是其的答案,c是题目给的生成原或者说底数也可以。
列:[网鼎杯 2020 青龙组]you_raise_me_up
题目:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Crypto.Util.number import *
import random

n = 2 ** 512
m = random.randint(2, n-1) | 1
c = pow(m, bytes_to_long(flag), n)
print 'm = ' + str(m)
print 'c = ' + str(c)

# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499

然后使用sympy库进行离散对数的阶数求解:

from Crypto.Util.number import long_to_bytes

m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n = 2 ** 512

import sympy
flag=sympy.discrete_log(2**512,c,m)
print(long_to_bytes(flag))
#flag{5f95ca93-1594-762d-ed0b-a9139692cb4a}

ECC

椭圆曲线加解密算数困扰了我近一两个月的问题,但是在比赛的时候又时常遇见,这也让我下定决定要思考熟悉一下这个问题。包括对离散数学的学习,也都只是因为我想要了解和熟悉ECC加密相关的问题。

要搞清楚ECC加解密的原理,首先需要的基础是离散数学的,然后就是要清楚知道其各个数值间的关系和作用,首先是ECC的一个椭圆曲线定义,由于并非任何一种ECC都使用于加密,所以这里主要以比赛中容易出题的一个椭圆曲线为例子:以素数为模的整数域 GF(p)。
式子不采用wiki上面的形式,而是大多数情况可能出现的一个格式:
y ^ 2 = x ^ 3 + ax+b(mod p)
a,b,p在解密的时候一般都会给出的。想要知道其解密过程,就得知道其加密是如何进行的。而重点就是选择一个生成元G,这个是很重要的一个点。之后的加密和解密都跟其相关。

**加密**
首先把明文m通过方法编码到椭圆曲线上有明文点m,然后计算一个P=nG,然后在规定的有限域内选取一个随机数值k,得到一个c1=kG,得到一个加密点,然后使用然后c2=m+c1。
然后做题所给出的信息会有,a,b,p,P,G
(其实还会添加一些其它的加密方法或者改变其加密逻辑来增加难度,但是万变不离其宗,从加密分析出解密的方法)
**解密**
其实写过相关题目就可以发现,ECC解密相关的题目往往比较难以解决的是k的问题,目前我能想到的也就只用通过已经知道P和G然后采用生成群的加法来一个个尝试出k的值。
sage代码如下:
a = 1234577
b = 3213242
n = 7654319

E = EllipticCurve(GF(n), [0, 0, 0, a, b])

base = E([5234568, 2287747])
pub = E([2366653, 1424308])

c1 = E([5081741, 6744615])
c2 = E([610619, 6218])

X = base

for i in range(1, n):
    if X == pub:
        secret = i
        print "[+] secret:", i
        break
    else:
        X = X + base
        print i
#这是一个sage脚本,ECC加密的问题通常是用sage脚本来解决的。

然后对于其它的问题类型,如果要进行求解,往往要解决的问题还是求解私钥k,当给出的生成元跟p相差并非很大的时候,用群加法来遍历出k的值还是可行的,如果k使用遍历求解的方式比较困难的话,还是得考虑使用其它得算法来减少其时间开销。在之后遇到其它的椭圆曲线加密的问题,我会再进行补充。

思考:ECC椭圆曲线解密其实就题目而言,并不是说非常的困难,其实绝大多是困难的情况是由于不清楚其的具体式子和给出数值的关系或是对于其的加密过程并不是理解的很透彻,所以才导致出现了这样的问题,这里我觉得要搞懂ECC的解密的话,一是需要有离散数学的一定基础,二是需要去花时间搞懂ECC的加密过程以及加密原理,三是要学习一下sage代码相关的语法。

posted @ 2025-05-22 18:22  喵老师哒哟  阅读(42)  评论(0)    收藏  举报