椭圆曲线加密ECC及密钥交换ECDH


EC, Elliptic Curve

ECC, Elliptic Curve Cryptography.

特点:密钥长度比RSA短。

比如,3072 bits RSA的强度等同于256 bits ECC.

基于椭圆曲线上乘法运算的逆运算的困难度。

ECC其实有三种用途 :

  • 公钥密码ECC
  • 数字签名ECDSA
  • 密钥交换ECDH

公钥密码的签名和密钥交换都是基于加密实现的。

运算

EC上的运算都是以EC上的点为对象的。

这些运算相当于包含EC上所有点以及无限远点的集合上的阿贝尔群(交换群)。

椭圆曲线本身是一条光滑的曲线,即实数域R上的椭圆曲线。但ECC使用的椭圆曲线则是在有限域Fp上。有限域Fp有两种:

  • 特征数为质数p的素域GF§,在整数集合{0, 1, , , p-1}中定义的加减乘除运算。
  • 特征数为2m的扩张域GF(2m),已过时(FIPS 186-5)。

所以,椭圆曲线密码中的曲线并不是线,而是离散的点。

这里我们使用素域。

P是大于3的素数,且
4 a 3 + 27 b 2 ≠ 0 m o d    P 4a^3+27b^2\ne 0 \mod P 4a3+27b2=0modP

这个条件保证曲线不包含奇点(singularities)。

奇点是高中数学导数的内容,是曲线上瞬间改变方向的一个点。

GF§上的EC:
y 2 = x 3 + a x + b m o d    P a , b ∈ G F ( P ) y^2=x^3+ax+b \mod P \\ a,b\in GF(P) y2=x3+ax+bmodPa,bGF(P)

这个方程又称为椭圆曲线的维尔斯特拉斯标准形式(Weierstrass normal form)。

EC是始终关于x轴对称的。

P,Q互逆:

P ( x , y ) + Q ( x , − y ) = 0 P(x,y)+Q(x,-y)=0 P(x,y)+Q(x,y)=0

无穷远点的逆即自己。

P ( x 1 , y 1 ) + Q ( x 2 , y 2 ) = R ( x 3 , y 3 ) { λ = y 2 − y 1 x 2 − x 1 x 3 = λ 2 − x 1 − x 2 y 3 = λ ( x 1 − x 3 ) − y 1 P(x_1,y_1)+Q(x_2,y_2)=R(x_3,y_3) \begin{cases} \lambda=\frac{y_2-y_1}{x_2-x_1}\\ x_3=\lambda^2-x_1-x_2\\ y_3=\lambda(x_1-x_3)-y_1 \end{cases} P(x1,y1)+Q(x2,y2)=R(x3,y3) λ=x2x1y2y1x3=λ2x1x2y3=λ(x1x3)y1

P=Q时

{ λ = 3 x 1 2 + a 2 y 1 x 3 = λ 2 − 2 x 1 y 3 = λ ( x 1 − x 3 ) − y 1 \begin{cases} \lambda=\frac{3x_1^2+a}{2y_1} x_3=\lambda^2-2x_1 y_3=\lambda(x_1-x_3)-y_1 \end{cases} {λ=2y13x12+ax3=λ22x1y3=λ(x1x3)y1

负数

A为EC上的一个点,-A就是A的纵坐标取反,即关于x轴的对称点。

加法

A+B

A和B两个点构成一条直线,会经过EC上的另一个点C(c1, c2),则A+B = (c1, -c2)。‘

A+(-A),直线与y轴平行,得不到点C,则将其记为单位元、无穷点、0元素,后续记为0:

◯ ( ∞ , ∞ ) ◯ ( ∞ , ∞ ) + ◯ ( ∞ , ∞ ) = 0 + 0 = 0 P ( x , y ) + ◯ ( ∞ , ∞ ) = P ( x , y ) \bigcirc(\infty,\infty) \\ \bigcirc(\infty,\infty)+\bigcirc(\infty,\infty)=0+0=0 \\ P(x,y)+\bigcirc(\infty,\infty)=P(x,y) \\ (,)(,)+(,)=0+0=0P(x,y)+(,)=P(x,y)
所以注意,点O不是原点。

倍数

2A

其实就是加法中,B=A。这时直线就取EC的切线,也能得到另一个点C,纵坐标取反就是2A。

而3A,则是2A+A.

逆运算

已知条件如下,求x:

  • 椭圆曲线EC
  • EC上的生成元点G
  • G的x倍点xG(正运算)

这就是椭圆曲线上的离散对数问题。

ECC原理

收发双方已知:

  • EC
  • base point G

n:生成元G的阶

  • nG == 0
  • 私钥为随机数k,取值范围{1, 2, , , n-1}
  • 公钥Q = kG

( n G = ◯ ) 私钥 : k ∈ { 1 , 2 , . . . , n − 1 } 公钥 : Q = k G M ∈ { 0 , 1 , . . . , n − 1 } (nG=\bigcirc) \\ 私钥: k\in\{1,2,...,n-1\} \\ 公钥: Q=kG \\ M\in\{0,1,...,n-1\} (nG=)私钥:k{1,2,...,n1}公钥:Q=kGM{0,1,...,n1}

加密

  1. 生成随机数r, 取值范围{1, 2, , , n-1}
  2. 点X1(x1, y1) = rG
  3. 点X2(x2, y2) = rQ,若横坐标x2 == 0,则重新生成r;
  4. 明文M作为横坐标m1映射至曲线上一点(m1, m2)
  5. 公钥加密c = m1 * x2 mod n
  6. 密文 {X1, xc}

解密

  1. 还原X2 = d*X1 = (x2, y2)
  2. 求x2的逆 1/x2 mod n
  3. m1 = c * 1/x2 mod n

整个过程中,主要是使用点的x坐标。

实现

https://github.com/C0deStarr/CryptoImp/tree/main/pubkey/ecc

  • ecc.h
  • ecc.c

ECDH原理

Elliptic Curve Diffie-Hellman

相比ECC的公钥加密,私钥解密,ECDH是将加密时的随机数r,换成发送方的私钥。

解密时,接收方把X1换成发送方的公钥。

比如,Alice的私钥为a,Bob的私钥为b,则共享密钥为abG。

加密:C = M + abG

解密:M = C - abG

攻击者已知:

  • C
  • aG
  • bG

但是,攻击者不能根据aG和bG还原出双方私钥a和b,无法计算出abG来解密。

Miracl示例

本人基于ECC加解密修改了一下,把m1*x2改成M+X2,并不是所有消息都能解密成功,bug未解决。但下面这个demo没问题。

EC:

y 2 = x 3 − 2 x − 3 ( m o d    7 ) y^2=x^3-2x-3(\mod 7) y2=x32x3(mod7)

生成元G=(3,2),阶n=10。

明文M(0, 2)

随机数r = 3

接收方

  • 私钥k=3
  • 公钥kG = (4, 2)
#include "ecc.h"

#include<stdio.h>
#include "miracl.h"

void print_point(epoint* p)
{
	big bx = mirvar(0);
	big by = mirvar(0);
	char x = 0, y = 0;

	epoint_get(p, bx, by);

	big_to_bytes(1, bx, &x, TRUE);
	big_to_bytes(1, by, &y, TRUE);
	printf("(%d, %d)\n", x, y);
}

void test_ecc()
{

	miracl* mip = mirsys(10, 10);
	int i;

	int N = 10;
	int nP = N + 1;
	int nRet = 0;
	// y^2 = x^3 -2x - 3 mod 7
	big bigA = mirvar(-2);
	big bigB = mirvar(-3);
	big bigP = mirvar(7);


	// G(3, 2)
	big gx = mirvar(3);
	big gy = mirvar(2);
	epoint* epointG = epoint_init();

	epoint* epointAdd = epoint_init();

	// public key
	epoint* epointPubkey = epoint_init();
	// private key
	big bigK = mirvar(3);
	// random 
	big bigR = mirvar(3);
	// message
	epoint* epointM = epoint_init();
	// cipher (X1, C)
	epoint* epointC = epoint_init();
	epoint* epointX1 = epoint_init();
	// r * public key
	epoint* epointX2 = epoint_init();
	// dec
	epoint* epointDec = epoint_init();

	big bx = mirvar(0);
	big by = mirvar(0);
	big bn = mirvar(1);

	//init ecurve
	ecurve_init(bigA, bigB, bigP, MR_PROJECTIVE);

	//init generator
	if (epoint_set(gx, gy, 0, epointG))
	{
		// epointG is on the active EC
		for (i = 0; i < nP; i++)
		{
			ecurve_mult(bn, epointG, epointAdd);
			printf("%2dG: ", i+1);
			print_point(epointAdd);
			incr(bn, 1, bn);
		}

	}
	// public key
	ecurve_mult(bigK, epointG, epointPubkey);
	
	// encrypt
	printf("======encrypt========\n");
	convert(0, bx);
	convert(2, by);
	epoint_set(bx, by, 0, epointM);
	printf("msg:\n");
	print_point(epointM);

	epoint_copy(epointM, epointC);

	ecurve_mult(bigR, epointG, epointX1);
	printf("X1:\n");
	print_point(epointX1);
	
	ecurve_mult(bigR, epointPubkey, epointX2);
	printf("X2:\n");
	print_point(epointX2);

	ecurve_add(epointX2, epointC);
	printf("cipher: (X2 + M, X1)\n");
	print_point(epointC);
	print_point(epointX1);

	// decrypt
	printf("======decrypt========\n");
	ecurve_mult(bigK, epointX1, epointX2);
	printf("kX1 == X2\n");
	print_point(epointX2);
	epoint_copy(epointC, epointDec);
	ecurve_sub(epointX2, epointDec);
	printf("decrypt: C - kX1\n");
	print_point(epointDec);

/*
 1G: (3, 2)
 2G: (2, 6)
 3G: (4, 2)
 4G: (0, 5)
 5G: (5, 0)
 6G: (0, 2)
 7G: (4, 5)
 8G: (2, 1)
 9G: (3, 5)
10G: (0, 0)
11G: (3, 2)
======encrypt========
msg:
(0, 2)
X1:
(4, 2)
X2:
(3, 5)
cipher: (X2 + M, X1)
(5, 0)
(4, 2)
======decrypt========
kX1 == X2
(3, 5)
decrypt: C - kX1
(0, 2)
*/
	mirexit();
	getchar();
	return 0;
}

参考资料

《图解密码技术》第3版

ECC — PyCryptodome 3.17.0 documentation

Elliptic Curve Cryptography: a gentle introduction - Andrea Corbellini

FIPS 186-5, Digital Signature Standard (DSS) | CSRC (nist.gov)

Digital Signature Standard (DSS) (nist.gov)

Edwards-Curve Digital Signature Algorithm (EdDSA)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值