区块链密码学知识

泰链联盟代码

区块链密码学理论基础

椭圆曲线普通方程

椭圆曲线 y 2 = a x 3 + b x + c ( m o d p ) \begin{matrix} y^2=ax^3+bx+c(mod & p) \end{matrix}
在区块链行业中,以太坊和比特币都选用参数为S256,参数都选用

theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0)
	theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0)
	theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0)
	theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0)
	theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0)
	theCurve.BitSize = 256

当然还有其他参数的椭圆曲线,都大同小异。不一一列举。由于参数选用的不同,导致椭圆曲线方程就不同。
以太坊和比特币采用的曲线都为
y 3 = x 2 + b ( m o d p ) \begin{matrix} y^3=x^2+b(mod & p) \end{matrix}

椭圆曲线方程的图形

在这里插入图片描述

有限域椭圆曲线

椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点,我们要把椭圆曲线定义在有限域上。mod p 就是把椭圆曲线变为离散点。这些点构成一个群,就是所谓的阿贝尔群。
在数学中,群是一种代数结构,由一个集合以及一个二元运算所组成。已知集合和运算(G,*)如果是群则必须满足如下要求

  • 封闭性:∀a,b∈G,a*b ∈ G
  • 结合性: ∀a,b,c∈G ,有 (ab)c = a* (b*c)
  • 单位元:ョe∈G, ∀a ∈G,有ea = ae = a
  • 逆元: ∀a ∈G ,ョb∈G 使得 ab = ba = e
  • 阿贝尔群除了上面的性质还满足交换律公理a * b = b * a
    同样在椭圆曲线也可以定义阿贝尔群。任意取椭圆曲线上两点P、Q(若P、Q两点重合,则作P点的切线),作直线交于椭圆曲线的另一点R’,过R’做y轴的平行线交于R,定义P+Q=R。这样,加法的和也在椭圆曲线上,并同样具备加法的交换律、结合律。

生成公私钥

func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
	k, err := randFieldElement(c, rand)
	if err != nil {
		return nil, err
	}
	priv := new(PrivateKey)
	priv.PublicKey.Curve = c
	priv.D = k
	priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
	return priv, nil
}

在上述代码中就是生成公私钥的go代码。elliptic.Curve 是选用的那一个参数的曲线。rand io.Reader 是一个随机数。

func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
	params := c.Params()
	b := make([]byte, params.BitSize/8+8)
	_, err = io.ReadFull(rand, b)
	if err != nil {
		return
	}

	k = new(big.Int).SetBytes(b)
	n := new(big.Int).Sub(params.N, one)
	k.Mod(k, n)
	k.Add(k, one)
	return
}

randFieldElement 函数就是一定范围内产生一个随机数。此随机数就是私钥。公钥的产生就是私钥 k*G,G是椭圆曲线上的一个基点。c.ScalarBaseMult(k.Bytes()) 此代码就是生成公钥的代码。G不是一个点,而是一个椭圆曲线上的点,所以一个数与点相乘,就会产生一个椭圆曲线上的点。

上述椭圆曲线可以满足公链的要求,不论在以太坊还是比特币,都可以应用,但是在联盟链中此椭圆曲线就不支持生成证书。,生成证书在泰岳联盟链中就采用参数P256生成。
代码位置[参考文档](参考文档


// Generate an elliptic curve public / private keypair. If params is nil,
// the recommended default parameters for the key will be chosen.
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
	pb, x, y, err := elliptic.GenerateKey(curve, rand)
	if err != nil {
		return
	}
	prv = new(PrivateKey)
	prv.PublicKey.X = x
	prv.PublicKey.Y = y
	prv.PublicKey.Curve = curve
	prv.D = new(big.Int).SetBytes(pb)
	if params == nil {
		params = ParamsFromCurve(curve)
	}
	prv.PublicKey.Params = params
	return
}

同样的原理只不过参数需要改变,elliptic.P256()就是elliptic.Curve的 参数,整个联盟链就需要用参数P256。包括加密解密,签名和验签,生成共享秘钥。恢复公钥的方法。待续。。。。

猜你喜欢

转载自blog.csdn.net/qq_26563551/article/details/106356416