泰链联盟代码
区块链密码学理论基础
椭圆曲线普通方程
椭圆曲线 y 2 = a x 3 + b x + c ( m o d p ) \begin{matrix} y^2=ax^3+bx+c(mod & p) \end{matrix} y2=ax3+bx+c(modp)
在区块链行业中,以太坊和比特币都选用参数为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} y3=x2+b(modp)
椭圆曲线方程的图形
有限域椭圆曲线
椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点,我们要把椭圆曲线定义在有限域上。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。包括加密解密,签名和验签,生成共享秘钥。恢复公钥的方法。待续。。。。