椭圆曲线介绍(二):整数域上面的椭圆曲线以及离散对数问题

内容来自ANDREA CORBELLINI的椭圆曲线密码学的介绍:Elliptic Curve Cryptography: a gentle introduction

前言

本文是椭圆曲线介绍中的第二篇:整数域上面的椭圆曲线以及离散对数问题。

上一篇中,一届看到了实数域上面的椭圆曲线以及如何用椭圆曲线的性质来定义一个群。两个点之间的加法定义为:一条直线与椭圆曲线的三个交点,他们的和为0: ( P + Q + R = 0 ) (P+Q+R=0) (P+Q+R=0)

标量乘法的定义为: ( n P = P + P + ⋯ + P ) (nP=P+P+\cdots +P) (nP=P+P++P),可以使用类似二进制分解的方法加速标量乘法的运算。

现在将椭圆曲线限制到一个有限域中。

模p的整数域

有限域的概念可以参考这个链接。这里略过了。

F p 上 面 的 椭 圆 曲 线 \mathbb{F}_p上面的椭圆曲线 Fp线

在实数上面的椭圆曲线定义为:
{ ( x , y ) ∈ R 2 ∣ y 2 = x 3 + a x + b , 4 a 3 + 27 b 2 ≠ 0 } ∪ { 0 } \left\{(x,y)\in \mathbb{R}^2 \quad |\quad y^2 = x^3+ax+b,4a^3+27b^2\ne 0 \right\} \cup \{0\} {(x,y)R2y2=x3+ax+b,4a3+27b2=0}{0}
而有限域上面的椭圆曲线为:
{ ( x , y ) ∈ ( F p ) 2 ∣ y 2 = x 3 + a x + b ( m o d p ) , 4 a 3 + 27 b 2 ≠ 0 ( m o d p ) } ∪ { 0 } \left\{(x,y)\in (\mathbb{F}_p)^2 \quad |\quad y^2 = x^3+ax+b \pmod p,4a^3+27b^2\ne 0 \pmod p \right\} \cup \{0\} {(x,y)(Fp)2y2=x3+ax+b(modp),4a3+27b2=0(modp)}{0}
,其中 0 0 0表示无穷远点, a a a b b b F p \mathbb{F}_p Fp中的元素。

在这里插入图片描述
上面的图片分别为 y 2 ≡ x 3 − 7 x + 10 ( m o d p ) y^2 \equiv x^3-7x+10 \pmod p y2x37x+10(modp) p = 19 , 97 , 127 , 487 p=19,97,127,487 p=19,97,127,487时的情况。可以注意到 x x x要么没有对应的 y y y值,要么有两个对应的 y y y值,且这两个 y y y值是对于 y = p / 2 y=p/2 y=p/2对称的。

在这里插入图片描述
上图为有限域上面的奇异曲线的例子,即 3 a 3 + 27 b 2 = 0 3a^3+27b^2=0 3a3+27b2=0的情况,这里的例子是 y 2 ≡ x 3 ( m o d 29 ) y^2\equiv x^3 \pmod{29} y2x3(mod29)的情况,可以看到有一个奇异点 ( 0 , 0 ) (0,0) (0,0),所以这不是一个有效的椭圆曲线。

点之间的加法(几何上)

在实数上面,我们定义加法为三个一条直线上面的点的和为零 ( P + Q + R = 0 ) (P+Q+R=0) (P+Q+R=0),在有限域 F p \mathbb{F}_p Fp上面也可以这么定义,但是怎么理解有限域上面的在一条直线上呢?

显然,这条直线和实数上面的直线是不一样的。在实数上面我们定义满足同一个 a x + b y + c = 0 ax+by+c=0 ax+by+c=0关系式的点是在一条直线上面。那么类似的,我们在有限域 F p \mathbb{F}_p Fp上面可以定义 a x + b y + c ≡ 0 ( m o d p ) ax+by+c\equiv 0 \pmod p ax+by+c0(modp)上面的点在一条直线上面。

在这里插入图片描述
上图的椭圆曲线为 y 2 ≡ x 3 − x + 3 ( m o d 127 ) y^2 \equiv x^3-x+3\pmod{127} y2x3x+3(mod127),其中 P = ( 16 , 20 ) , Q = ( 41 , 120 ) P=(16,20),Q=(41,120) P=(16,20),Q=(41,120)。直线为 y ≡ 4 x + 83 ( m o d 127 ) y \equiv 4x + 83 \pmod{127} y4x+83(mod127)

这样的加法仍然是满足群的性质的:

  • Q + 0 = 0 + Q = Q Q+0=0+Q=Q Q+0=0+Q=Q 0 0 0是单位元。
  • 逆元的定义为 Q = ( x Q , y Q )   m o d   p Q=(x_Q,y_Q) \bmod p Q=(xQ,yQ)modp − Q = ( x Q , − y Q )   m o d   p -Q=(x_Q,-y_Q) \bmod p Q=(xQ,yQ)modp,比如 F 29 \mathbb{F}_{29} F29中点 Q = ( 2 , 5 ) Q=(2,5) Q=(2,5)的逆元为 − Q = ( 2 , 24 ) -Q=(2,24) Q=(2,24)
  • P+(-P)=0。

遗憾的是,这样的 0 0 0并不能给出几何上面的解释。

点之间的加法(代数上)

F p \mathbb{F}_p Fp中计算加法和 R \mathbb{R} R中的计算方法是一致的,除了要模 p p p

那么,给定 P = ( x P , y P ) , Q = ( x Q , y Q ) P=(x_P,y_P),Q=(x_Q,y_Q) P=(xP,yP)Q=(xQ,yQ),以及 R = ( x R , y R ) R=(x_R,y_R) R=(xR,yR),那么可以按如下方法计算 P + Q = − R P+Q=-R P+Q=R
x R = ( m 2 − x P − x Q )   m o d   p y R = [ y P + m ( x R − x P ) ]   m o d   p = [ y Q + m ( x R − x Q ) ]   m o d   p \begin{aligned} x_{R} &=\left(m^{2}-x_{P}-x_{Q}\right) \bmod p \\ y_{R} &=\left[y_{P}+m\left(x_{R}-x_{P}\right)\right] \bmod p \\ &=\left[y_{Q}+m\left(x_{R}-x_{Q}\right)\right] \bmod p \end{aligned} xRyR=(m2xPxQ)modp=[yP+m(xRxP)]modp=[yQ+m(xRxQ)]modp

如果 P ≠ Q P\ne Q P=Q,那么 m = ( y P − y Q ) ( x P − x Q ) − 1   m o d   p m=\left(y_{P}-y_{Q}\right)\left(x_{P}-x_{Q}\right)^{-1} \bmod p m=(yPyQ)(xPxQ)1modp
如果 P = Q P=Q P=Q,那么 m = ( 3 x P 2 + a ) ( 2 y P ) − 1   m o d   p m=\left(3 x_{P}^{2}+a\right)\left(2 y_{P}\right)^{-1} \bmod p m=(3xP2+a)(2yP)1modp

椭圆曲线的阶:

有限域上面的椭圆曲线是由有限个点所构成的,那么具体有几个点呢?

首先,定义概念椭圆曲线群的阶为当前椭圆曲线群上面的点的数量。

可以直接将 x x x 0 0 0 p − 1 p-1 p1计数有多少点,但这样的复杂度是 O ( p ) O(p) O(p)的,在 p p p比较大的时候会很慢,也有比较高效的算法来计算椭圆曲线的阶,比如Schoof算法,这里不具体展开。

标量乘法以及循环群

标量乘法的计算方法即为计算多次的加法:
n P = P + P + ⋯ + P ⏟ n  times  n P=\underbrace{P+P+\cdots+P}_{n \text { times }} nP=n times  P+P++P

同样的,可以用之前提出的二进制分解的方法来加快运算。

但有限域上面的乘法有一个有趣的性质,就是他会构成一个乘法循环子群。

在这里插入图片描述
y 2 = x 3 + 2 x + 3 ( m o d 97 ) y^2=x^3+2x+3 \pmod {97} y2=x3+2x+3(mod97)来举例, P = ( 3 , 6 ) P=(3,6) P=(3,6)的话,会发现 n P nP nP会在 ( 0 , P , 2 P , 3 P , 4 P ) (0,P,2P,3P,4P) (0,P,2P,3P,4P)这些值中不断循环。可以在这个链接里面试一下。

这样的 P P P被称作这个循环子群的生成元(generator)或者基本点(base point)。

子群的阶

有一个问题就是 P P P生成的循环子群的阶是多少呢?。或者换一种说法, P P P的阶是多少?。

  • P P P的阶就是令 n P = 0 nP=0 nP=0的最小的 n n n,( 0 0 0本身除外),在上面的例子里面就是 5 5 5
  • P P P的阶和整个椭圆曲线的阶是满足拉格朗日定理的,也就是说子群的阶可以整除父群的阶。

因此就可以用下面的方法找出某个点 P P P的阶了:

  1. 使用Schoof算法计算得出整个椭圆曲线的阶 N N N
  2. 找到阶 N N N的所有因子。
  3. 对于 N N N的每个因子 n n n,按照从小到大的方式,计算 n P nP nP
  4. 如果 n P = 0 nP=0 nP=0,那么 n n n是子群的阶。

特例是如同 y 2 = x 3 − x + 1 ( m o d 29 ) y^2=x^3-x+1 \pmod{29} y2=x3x+1(mod29)这样的阶为素数 37 37 37的曲线,那么他的子群就是本身。也就是这个一个循环群。

如何找生成元

在椭圆曲线密码学中,我们需要一个较高次数的子群。所以一般来说,是先取一个曲线,然后计算他的阶 N N N,选择一个比较大的因子 n n n,然后根据这个因子来找到一个合适的生成元。

首先,介绍一下cofactor的概念,因此拉格朗日定理的存在,所以可以推断 h = N / n h=N/n h=N/n是一个整数,那么这个 h h h就是子群的cofactor。

那么对于曲线中的任意一个点,满足 N P = 0 NP=0 NP=0,也可以写成是 n ( h P ) = 0 n(hP)=0 n(hP)=0

n n n为素数时,只要任取一点 P P P,令 G = h P G=hP G=hP,那么 G G G就是一个阶为 n n n的生成元。

总结一下找生成元的步骤:

  1. 计算椭圆曲线的阶 N N N
  2. 选择某个因子 n n n作为子群的阶。
  3. 计算cofactor h = N / n h=N/n h=N/n
  4. 选择曲线上面随机一个点 P P P
  5. 计算 G = h P G=hP G=hP
  6. 如果 G = 0 G=0 G=0,那么从第四步开始重新选,否则 G G G就是我们要的生成元了。

椭圆曲线上面的离散对数问题

在有限域的椭圆曲线中,其离散对数问题定义为:

如果知道 P P P Q Q Q,那么如何找到一个 k k k使得 Q = k P Q=kP Q=kP?。

这样一个问题是一个标准的密码学难题假设,也就是大家公认这个问题是比较困难的。

而那些基于整数群上面的离散对数问题的算法比如DSA或者Diffle-Hellman以及Elgamal,都有其在椭圆曲线上面的平替。

椭圆曲线一个优秀的性质在于,同样对于整数上面的离散对数问题 b = a k   m o d   p b=a^k \bmod p b=akmodp,在参数大小相同的情况下,椭圆曲线的离散对数问题更难解决。

因此,要达到同样的安全等级,椭圆曲线的参数大小更小。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者: 裴定一 / 祝跃飞 出版社: 科学出版社 出版年: 2002年09月 页数: 233 页 定价: 19.00 装帧: 平装 ISBN: 9787030106834 内容简介 · · · · · · 本书论述了算法数论的基本内容,其中包括:连分数、代数数椭圆曲线、素性检验、大整数因子分解算法、椭圆曲线上的离散对数、超椭圆曲线。本书的特点是内容涉及面广,在有限的篇幅内,包含了必要的预备知识和数学证明,尽可能形成一个完整的体系。并且本书的部分内容曾多次在中国科学院研究生院信息安全国家重点实验室和广州大学作为硕士研究生教材使用。 本书可作为信息安全、数论等专业的研究生教材及相关专业的研究人员、高等学校的教师和高年级学生的参考。 序 前言 第一章 整数的因子分解 1.1 唯一分解定理 1.2 辗转相除法(欧氏除法) 1.3 Mersenne素数和Fermat素数 1.4 整系数多项式 1.5 环Z[i]和Z[ω] 习题一 第章 同余式 2.1 孙子定理 2.2 剩余类环 2.3 Euler函数ρ(m) 2.4 同余方程 2.5 原根 2.6 缩系的构造 习题 第三章 次剩余 3.1 定义及Euler判别条件 3.2 Legendre符号 3.3 Jacobi符号 习题三 第四章 特征 4.1 剩余系的表示 4.2 特征 4.3 原特征 4.4 特征和 4.5 Gauss和 习题四 第五章 连分数 5.1 简单连分数 5.2 用连分数表实数 5.3 最佳渐近分数 5.4 Legendre判别条件 习题五 第六章 代数数 6.1 代数整数 6.2 Dedekind整环 6.3 阶的一些性质 第七章 椭圆曲线 7.1 椭圆曲线的群结构 7.2 除子类群 7.3 同种映射 7.4 Tate模和Weil对 7.5 有限上的椭圆曲线 习题七 第八章 在密码学中的一些应用 8.1 RSA公钥密码 8.2 Uiffie-Hellman体制 8.3 ElGamal算法 8.4 基于背包问题的公钥密码 8.5 秘密共享 第九章 素性检验 9.1 Fermat小定理及伪素数 9.2 强伪素数及Miller-Rabin检验 9.3 利用n-1的因子分解的素性检验 9.4 利用n+1的因子分解的素性检验 9.5 分圆环素性检验 9.6 基于椭圆曲线的素性检验 第十章 大整数因子分解算法 10.1 连分数因子分解算法 10.2 次筛法 10.3 Pollard的P-1因子分解算法 10.4 椭圆曲线因子分解算法 10.5 数筛法 习题十 第十一章 椭圆曲线上的离散对数 11.1 椭圆曲线公钥密码 11.2 小步-大步法 11.3 家袋鼠和野袋鼠 11.4 MOV约化 11.5 FR约化 11.6 SSSA约化 11.7 有限离散对数的计算 第十章 超椭圆曲线 12.1 超椭圆曲线的Jacobian 12.2 虚次代数函数 12.3 基于超椭圆曲线的公钥密码 附录 一些常用算法 A.1 不可约多项式的判别 A.2 有限中平方根的求解 A.3 有限上的分解 A.4 Hensel引理 A.5 格 A.6 Z[x]中多项式的分解 参考文献
好的,以下是一个简单的椭圆曲线加密算法的实现,使用的是secp256k1椭圆曲线。 首先,需要定义椭圆曲线的参数和点结构体: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> // 定义有限Fp和椭圆曲线y^2 = x^3 + ax + b (mod p) const int p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; const int a = 0; const int b = 7; // 定义椭圆曲线上的点结构体 typedef struct { int x, y; } point_t; ``` 接下来,需要实现椭圆曲线上的加法和点倍乘运算: ```c // 求模意义下的乘法逆元 int mod_inv(int a, int m) { int x, y; int g = ext_gcd(a, m, &x, &y); if (g == 1) { return (x + m) % m; } else { return 0; } } // 扩展欧几里得算法 int ext_gcd(int a, int b, int* x, int* y) { if (b == 0) { *x = 1; *y = 0; return a; } else { int g = ext_gcd(b, a % b, y, x); *y -= a / b * (*x); return g; } } // 椭圆曲线上的加法运算 point_t ecc_add(point_t P, point_t Q) { point_t R; int lambda; if (P.x == Q.x && P.y == Q.y) { lambda = (3 * P.x * P.x + a) * mod_inv(2 * P.y, p); } else { lambda = (Q.y - P.y) * mod_inv(Q.x - P.x, p); } R.x = (lambda * lambda - P.x - Q.x + p) % p; R.y = (lambda * (P.x - R.x) - P.y + p) % p; return R; } // 椭圆曲线上的点倍乘运算 point_t ecc_mul(int d, point_t P) { point_t R = {0, 0}; while (d) { if (d & 1) { R = ecc_add(R, P); } P = ecc_add(P, P); d >>= 1; } return R; } ``` 然后,需要实现密钥生成、加密和解密函数: ```c // 生成随机私钥和对应的公钥 void ecc_gen_keypair(point_t G, int n, int* d, point_t* Q) { *d = rand_between(1, n - 1); *Q = ecc_mul(*d, G); } // 加密消息msg,返回密文C point_t ecc_encrypt(char* msg, int len, point_t G, point_t Q) { int k = rand_between(1, n - 1); point_t C1 = ecc_mul(k, G); point_t C2 = {0, 0}; for (int i = 0; i < len; i++) { C2 = ecc_add(C2, ecc_mul(k, ecc_encode(msg[i]))); } return ecc_add(C1, C2); } // 解密密文C,返回明文msg和长度len void ecc_decrypt(point_t C, int d, char* msg, int* len) { point_t C1 = ecc_mul(d, C.x); point_t C2 = ecc_mul(d, C.y); C2 = ecc_add(C2, ecc_neg(C1)); *len = 0; while (C2.x || C2.y) { msg[(*len)++] = ecc_decode(ecc_mul(d, C2.x).x); C2 = ecc_neg(C2); C2 = ecc_add(C2, ecc_encode(msg[*len - 1])); } for (int i = 0; i < *len / 2; i++) { char t = msg[i]; msg[i] = msg[*len - i - 1]; msg[*len - i - 1] = t; } } ``` 其中,`rand_between`是生成指定范围内的随机整数函数,`ecc_encode`是将字符编码为椭圆曲线上的点,`ecc_decode`是将椭圆曲线上的点解码为字符,`ecc_neg`是点的相反点。 最后,可以编写一个简单的测试程序: ```c int main() { // 选择secp256k1椭圆曲线的基点G和阶n point_t G = {0x79BE667EF9DCBBAC, 0x55A06295CE870B07}; int n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; // 生成随机密钥对 srand(time(NULL)); int d; point_t Q; ecc_gen_keypair(G, n, &d, &Q); printf("私钥d: %d\n", d); printf("公钥Q: (%llx, %llx)\n", Q.x, Q.y); // 加密消息 char msg[] = "hello world"; int len = strlen(msg); point_t C = ecc_encrypt(msg, len, G, Q); printf("密文C: (%llx, %llx)\n", C.x, C.y); // 解密消息 char dec[100]; int dec_len; ecc_decrypt(C, d, dec, &dec_len); printf("明文: %s\n", dec); return 0; } ``` 完整代码如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值