成都兄弟连IT培训学校

176-1289-1020

兄弟连区块链培训Fabric 1.0源代码分析(47)ECDSA(椭圆曲线数字签名算法)

编辑:成都兄弟连IT培训学校时间:2019-05-31

兄弟连区块链技术培训Fabric1.0源代码分析(47)ECDSA(椭圆曲线数字签名算法)

#Fabric1.0源代码笔记之ECDSA(椭圆曲线数字签名算法)

##1、椭圆曲线算法概述

###1.1、无穷远点、无穷远直线、射影平面

*平行线相交于无穷远点;

*直线上有且只有一个无穷远点;

*一组相互平行的直线有公共的无穷远点;

*平面上任何相交的两直线,有不同的无穷远点;

*全部无穷远点沟通一条无穷远直线;

*平面上全部无穷远点和全部普通点构成射影平面。

###1.2、射影平面点定义

对于普通平面上点(x,y),令x=X/Z,y=Y/Z,Z≠0,则投影为射影平面上的点为(X:Y:Z)。

如点(1,2)在射影平面的坐标为:(Z:2Z:Z)Z≠0,即(1:2:1)或(2:4:2)均为(1,2)在射影平面上的点。

Z=0时,(X:Y:0)即为无穷远点,Z=0即为无穷远直线。

###1.3、椭圆曲线方程

椭圆曲线的定义:

一条椭圆曲线是在射影平面上满足方程Y2Z+a1XYZ+a3YZ2=X3+a2X2Z+a4XZ2+a6Z3的所有点的集合,且曲线上的每个点都是非奇异(或光滑)的。

该方程为维尔斯特拉斯方程,是一个齐次方程。

所谓“非奇异”或“光滑”的,即满足方程的任意一点都存在切线。

椭圆曲线存在无穷远点(0,Y,0),可以在平面坐标系中用椭圆曲线、加一个无穷远点来表示。

令x=X/Z,y=Y/Z,代入椭圆曲线方程,即椭圆曲线普通方程:y2+a1xy+a3y=x3+a2x2+a4x+a6。

###1.4、椭圆曲线上的加法

任意取椭圆曲线上两点P、Q(若P、Q两点重合,则做P点的切线)做直线交于椭圆曲线的另一点R’,过R’做y轴的平行线交于R。我们规定P+Q=R。

根据这个法则,可以知道椭圆曲线无穷远点O∞与椭圆曲线上一点P的连线交于P’,过P’作y轴的平行线交于P,所以有无穷远点O∞+P=P。

这样,无穷远点O∞的作用与普通加法中零的作用相当(0+2=2),我们把无穷远点O∞称为零元。同时我们把P’称为P的负元(简称,负P;记作,-P)。

根据这个法则,可以得到如下结论:如果椭圆曲线上的三个点A、B、C,处于同一条直线上,那么他们的和等于零元,即A+B+C=O∞。

k个相同的点P相加,我们记作kP。如:P+P+P=2P+P=3P。

###1.5、有限域椭圆曲线

椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点,我们要把椭圆曲线定义在有限域上。

*我们给出一个有限域Fp

*Fp中有p(p为质数)个元素0,1,2,…,p-2,p-1

*Fp的加法是a+b≡c(modp)

*Fp的乘法是a×b≡c(modp)

*Fp的除法是a÷b≡c(modp),即a×b^(-1)≡c(modp),b^(-1)也是一个0到p-1之间的整数,但满足b×b^(-1)≡1(modp)

*Fp的单位元是1,零元是0

同时,并不是所有的椭圆曲线都适合加密。y2=x3+ax+b是一类可以用来加密的椭圆曲线,也是最为简单的一类。

下面我们就把y2=x3+ax+b这条曲线定义在Fp上:

选择两个满足下列条件的小于p(p为素数)的非负整数a、b,4a3+27b2≠0(modp)。

则满足下列方程的所有点(x,y),再加上无穷远点O∞,构成一条椭圆曲线。

y2=x3+ax+b(modp)其中x,y属于0到p-1间的整数,并将这条椭圆曲线记为Ep(a,b)。

Fp上的椭圆曲线同样有加法,但已经不能给以几何意义的解释。

```

无穷远点O∞是零元,有O∞+O∞=O∞,O∞+P=P

P(x,y)的负元是(x,-y),有P+(-P)=O∞

P(x1,y1),Q(x2,y2)的和R(x3,y3)有如下关系:

x3≡k2-x1-x2(modp)

y3≡k(x1-x3)-y1(modp)

其中若P=Q则k=(3x12+a)/2y1若P≠Q,则k=(y2-y1)/(x2-x1)

```

例已知E23(1,1)上两点P(3,10),Q(9,7),求1)-P,2)P+Q,3)2P。

```

1)–P的值为(3,-10)

2)k=(7-10)/(9-3)=-1/2,2的乘法逆元为12因为2*12≡1(mod23)

k≡-1*12(mod23)故k=11。

x=112-3-9=109≡17(mod23);

y=11[3-(-6)]-10=89≡20(mod23)

故P+Q的坐标为(17,20)

3)k=[3(32)+1]/(2*10)=1/4≡6(mod23)

x=62-3-3=30≡20(mod23)

y=6(3-7)-10=-34≡12(mod23)

故2P的坐标为(7,12)

```

如果椭圆曲线上一点P,存在最小的正整数n,使得数乘nP=O∞,则将n称为P的阶,若n不存在,我们说P是无限阶的。

事实上,在有限域上定义的椭圆曲线上所有的点的阶n都是存在的。

###1.6、椭圆曲线上简单的加密/解密

考虑如下等式:

K=kG[其中K,G为Ep(a,b)上的点,k为小于n(n是点G的阶)的整数]。

不难发现,给定k和G,根据加法法则,计算K很容易;但给定K和G,求k就相对困难了。

这就是椭圆曲线加密算法采用的难题。

我们把点G称为基点(basepoint),k(k

##2、椭圆曲线接口及实现

###2.1、椭圆曲线接口定义

```go

typeCurveinterface{

Params()*CurveParams//返回曲线参数

IsOnCurve(x,y*big.Int)bool//(x,y)是否在曲线上

Add(x1,y1,x2,y2*big.Int)(x,y*big.Int)//(x1,y1)和(x2,y2)求和

Double(x1,y1*big.Int)(x,y*big.Int)//2*(x,y)

ScalarMult(x1,y1*big.Int,k[]byte)(x,y*big.Int)//返回k*(Bx,By)

ScalarBaseMult(k[]byte)(x,y*big.Int)//返回k*G,其中G为基点

}

//代码在crypto/elliptic/elliptic.go

```

###2.2、CurveParams结构体定义及通用实现

CurveParams包括椭圆曲线的参数,并提供了一个通用椭圆曲线实现。代码如下:

```go

typeCurveParamsstruct{

P*big.Int//%p中的p

N*big.Int//基点的阶,如果椭圆曲线上一点P,存在最小的正整数n,使得数乘nP=O∞,则将n称为P的阶

B*big.Int//曲线方程中常数b,如y2=x3-3x+b

Gx,Gy*big.Int//基点G(x,y)

BitSizeint//基础字段的大小

Namestring//椭圆曲线的名称

}

//代码在crypto/elliptic/elliptic.go

```

CurveParams涉及如下方法:

```go

func(curve*CurveParams)Params()*CurveParams//返回曲线参数,即curve

func(curve*CurveParams)IsOnCurve(x,y*big.Int)bool//(x,y)是否在曲线上

func(curve*CurveParams)Add(x1,y1,x2,y2*big.Int)(*big.Int,*big.Int)//(x1,y1)和(x2,y2)求和

func(curve*CurveParams)Double(x1,y1*big.Int)(*big.Int,*big.Int)//2*(x,y)

func(curve*CurveParams)ScalarMult(Bx,By*big.Int,k[]byte)(*big.Int,*big.Int)//返回k*(Bx,By)

func(curve*CurveParams)ScalarBaseMult(k[]byte)(*big.Int,*big.Int)//返回k*G,其中G为基点

//代码在crypto/elliptic/elliptic.go

```

###2.3、几种曲线

```go

funcP224()Curve//实现了P-224的曲线

funcP256()Curve//实现了P-256的曲线

funcP384()Curve//实现了P-384的曲线

funcP521()Curve//实现了P-512的曲线

//代码在crypto/elliptic/elliptic.go

```

##3、椭圆曲线数字签名算法

结构体定义:

```go

typePublicKeystruct{//公钥

elliptic.Curve

X,Y*big.Int

}

typePrivateKeystruct{//私钥

PublicKey

D*big.Int

}

typeecdsaSignaturestruct{//椭圆曲线签名

R,S*big.Int

}

//代码在crypto/ecdsa/ecdsa.go

```

涉及如下方法:

```go

func(priv*PrivateKey)Public()crypto.PublicKey//获取公钥

func(priv*PrivateKey)Sign(randio.Reader,msg[]byte,optscrypto.SignerOpts)([]byte,error)//使用私钥对任意长度的hash值进行签名

funcGenerateKey(celliptic.Curve,randio.Reader)(*PrivateKey,error)//生成一对公钥/私钥

funcSign(randio.Reader,priv*PrivateKey,hash[]byte)(r,s*big.Int,errerror)//使用私钥对任意长度的hash值进行签名

funcVerify(pub*PublicKey,hash[]byte,r,s*big.Int)bool//使用公钥验证hash值和两个大整数r、s构成的签名

//代码在crypto/ecdsa/ecdsa.go

```


上一篇:Java语言有前景吗?Java培训哪家好?

下一篇:兄弟连区块链培训Fabric 1.0源代码分析(48)Fabric 1.0.4 go代码量统计

联系方式

选择专业时,如果犹豫不定,不知道选择哪个比较好,敬请致电,专业的咨询老师会为你解答。

  • 报名热线:176-1289-1020
  • 咨询老师:何老师
  • 点击咨询:

友情连接:

关于我们|联系我们|网站地图

QQ咨询
在线咨询
在线报名
176-1289-1020
返回顶部