一.前言
目前比较受欢迎的加密算法一共存在两种,一种是基于大整数因子分解问题(IFP
)的RSA
算法和基于椭圆曲线上离散对数计算问题(ECDLP
)的ECC
算法。之前对RSA
算法进行过很详细的讲解,但是ECC
加密算法还没有讲过,所以给大家在尽量简单易懂不去深究数学概念的情况下讲解一下ECC
加密算法的内容。
二.加密过程
这里不可避免的要接触一些数学知识,看不懂加密秘密的过程,请对应过程看我的第三部分解释,保姆级教学了。
1.数学原理
我们假设椭圆曲线上有两个点P和Q,然后k为整数。此时有:
Q = k P Q=kPQ=kP
对于给定的k和P,根据加法法则,计算Q很容易,但是给定P和Q,来求k非常困难
2.加密和解密
- 选取一条椭圆曲线Ep(a,b),并取椭圆曲线上一点作为基点P
- 选取一个大数字k为私钥,并且生成公钥Q(Q=kP)
- 加密:选择随机数r,将明文M生产密文C。密文是一个点对,
C=(rP,M+rQ)
- 解密:M+rQ-k(rP)=M+r(kP)-K(rP)=M
三.数学补充
1.为什么用椭圆曲线
不管是ECC加密算法还是其他的加密算法,加密的基础都是基于一个数学难题,ECC
加密就是基于椭圆曲线离散对数问题设计的,我们先来看这个问题的数学原理。
我们假设椭圆曲线上有两个点P
和Q
,然后k
为整数。此时有: Q=KP
对于给定的k
和P
,根据加法法则,计算Q
很容易,但是给定P
和Q
,来求k
非常困难。
这里的Q=KP不是你理解的数学中的乘法,后面我会解释,同时告诉你KPQ是什么东西。
2.什么是椭圆曲线
这里先把你脑袋里面想的数学里面的椭圆抛掉,椭圆曲线并不是一个椭圆。
你脑袋里的椭圆是:x2 /a2 +y2 /b2 =1,
现在椭圆曲线是: y2 = x3 + ax +b,其中还要满足(4a3 + 27b≠0)
其中满足4a^3 + 27b^2 ≠ 0
是为了保证曲线不存在奇点,即为了保证曲线上每一点都存在切线。
奇点,也叫瑕点,大学高数里面应该介绍过,忘了记得翻高数,当然在这里不是重点。
这是在网上找的椭圆曲线的图形,大家参考一下:
3.有限域
首先我们知道椭圆曲线是连续的,它不适合加密,我们要把椭圆曲线变成离散的点,这些离散的点构成的区域就是有限域。
注意:有限域不是简单的集合,后面写物联网信息安全时我会提到详细域的介绍,这里简单提一下。
域是一个可以在其上进行加法、减法、乘法、和除法运算,而结果不会超出域的集合,如:有理数集合、实数集合、复数集合都是域,但整数集合不是。(很明显,使用除法得到的分数或者小数已超出整数集合)
如果域F只包含有限个元素,则称其为有限域,有限域中元素的个数称为有限域的阶。
每个有限域的阶必为素数的幂,即有限域的阶可表示为pn (p是素数,n是正整数),该有限域通常称为Galois域(Galois Fields),记为GF§。
在域的定义基础,上,作如下修改:
- 1.定义模p加法和模p乘法(加或乘的结果超过p时,模p取余数,p为素数)
- 2.集合内的元素经过加法和乘法计算,结果仍然在集合内。
- 3.计算符合交换率、结合率、分配率
- 4.加法和乘法有单位元素(所有 的集合内的值都有对应的负数,所有集合内非零值都有倒数)。
怎么样保证经过运算后,元素还在有限域内呢?这就需要取模运算。
4.椭圆曲线的加法规则
椭圆曲线的运算法则虽然使用的都是和平时运算一样的加法乘法等,但并不是简单的两点坐标的相加或者相乘,这里我们先的和大家介绍一下椭圆曲线的运算法则是怎么样的,再去介绍如何计算,首先我们来看加法法则,如下图所示:
看图理解:这里我们有A、B两个点(在椭圆曲线上),现在把它们的连线与椭圆曲线的交点关于x轴对称的点,才是我们需要计算的A+B的点。
这里A、B两点确定的直线选取还是很有必要的,要保证它是有第三个交点的,假设你现在取B=-A,那么画出来的图形是这样的:
这种情况我们可以认为直线与椭圆曲线相交于无穷远点。
5.椭圆曲线的乘法
在数学上,我们是不是把乘法理解为加法的叠加,在这里亦如此,A+A=2A。
在刚刚的加法基础上,我们让B点无限接近A点,直至重合,此时AB连线相当于做A的切线,该切线与椭圆的交点关于X
轴对称位置的点就是A+A
,即2A
计算3A就是计算A+2A
的结果,过A
点和2A
点做一条直线,然后与椭圆曲线的焦点关于X
轴的对称点就是3A
。
补充:第二部分中的Q=KP,现在理解了吗,其中K就是我们这里2、3……的数字,P就是我们这里举例用的A点,Q就是计算结果。
到这里大家就应该能理解为什么在一开始我们所说的椭圆曲线的数学问题:Q=KP
对于给定的k
和P
,根据加法法则,计算Q
很容易。
这里的K可以取很大的,不要以为就简单的2、3,这里是为了举例说明。
6.举例说明
椭圆曲线方程:x3 + x +1
当在有限域GF(23)
上面时,我们的椭圆曲线就成为了下面的样子:
四.举例计算
1.运算规则
2.例如
现在我们假设y2 =x3 + x +1 mod(23)
绩点:A(0,1)
当A=B时,带入计算k=3*02 +1/2=1/2 mod(23)
这里涉及到分数取模运算,我们可以用同余替换来计算:
所以,这里的x3计算出来就是6;
同时y3也可以计算出来为19。
这里x3和y3都出来了,关于x轴对称就不说了吧。
3.老师课堂例子
五.python实现
def get_points(a, b, p):"""获取有限域下的散点集"""# 计算所有可能的点坐标points = []for x in range(p):y_square = (x ** 3 + a * x + b) % pfor y in range(p):if (y ** 2) % p == y_square:points.append((x, y))return pointsdef cal_k(point_A, point_B, p):"""计算斜率k"""if point_A == point_B:son = 3 * pow(point_A[0], 2) + amother = 2 * point_A[1]# 费马小定理求分数取模return (son * pow(mother, p - 2)) % pelse:son = point_B[1] - point_A[1]mother = point_B[0] - point_A[0]# 费马小定理求分数取模return (son * pow(mother, p - 2)) % pdef cal_add(point_A, point_B, p, k):"""椭圆曲线加法计算A+B的结果坐标:param k: 斜率"""# A+B=C,计算c的坐标cx = (k ** 2 - point_A[0] - point_B[0]) % pcy = (k * (point_A[0] - cx) - point_A[1]) % preturn cx, cydef cal_NA(key, point_A, point_B, p):"""椭圆曲线乘法计算NA"""# 执行0~key-1共key次for i in range(key - 1):k = cal_k(point_A, point_B, p)point_B = cal_add(point_A, point_B, p, k)return point_Bdef encryption(r, Q, m, p):"""加密"""cx = cal_NA(r, A, B, p)rQ = cal_NA(r, Q, Q, p)k = cal_k(m, rQ, p)cy = cal_add(m, rQ, p, k)return cx, cydef decryption(cplantext, key, p):"""解密"""kc2 = cal_NA(key, cplantext[0], cplantext[0], p)# 减法即关于x轴对称点的坐标kc2 = (kc2[0], -kc2[1])k = cal_k(cplantext[1], kc2, p)result = cal_add(cplantext[1], kc2, p, k)return result# 测试-------------------------------------------------------------------
# 椭圆曲线的a,b
a = 1
b = 6
# 有限域的阶
p = 11
# 私钥k
key = 7
# 散点表
points = get_points(a, b, p)
print("散点表中的元素:")
print(points, end='')
print("\n-------------------------------------------------------------------")
# ------------------------------------------------------------------------
# A是基点,为散点表中的一点,B是另一个交点,这里初始时相同
A = (2, 7)
B = (2, 7)
# 公钥Q=7A
Q = cal_NA(key, A, B, p)
# 随机数r
r = 3
# --------------------------------------------------------------------------
# 消息
message = (10, 9)
print(f"原始消息:{message}")
# 密文
c = encryption(r, Q, message, p)
print(f"加密后的结果:{c}")
# 解密
result = decryption(c, key, p)
print(f"解密后的结果:{result}")
六.运行结果
本人也是开始学的过程。
参考链接:
- 1.ECC算法博客
- 2.ECC加密视频