死磕密码学|ECDSA算法 文章资料代码请star https://github.com/blockchainGuide/

u=1020757406,2710278676&fm=26&gp=0

生成签名

假设 Alice 希望对消息进行签名,所采用的椭圆曲线参数为,对应的密钥对为,其中为公钥为私钥。

Alice 将按如下步骤进行签名:

  1. 产生一个随机数. (签名算法首先生成一个临时私公钥对,该临时密钥对用于计算 r 和 s 值。)
  2. 计算,将化为整数.
  3. 计算,若,则转向第1步. (r 值为临时公钥的坐标 x 值)
  4. 计算
  5. 计算哈希值,并将得到的比特串转化为整数 e
  6. 计算,若,则转向第1步.
  7. 即为 Alice 对消息的签名.

椭圆曲线签名验证

为验证 Alice 对消息 m 的签名,Bob 需要得到 Alice 所用的椭圆曲线参数以及 Alice 的公钥 Q。

步骤如下:

  1. 验证 r 和 s 是区间上的整数.
  2. 计算并将其转化为整数 e.
  3. 计算
  4. 计算以及
  5. 计算
  6. ,则拒绝签名,否则将 X 的坐标转化为整数,并计
  7. 当且仅当时,签名通过验证.

椭圆曲线签名正确性

要证明,只需要证明即可。

证明步骤:

令:

带入:

得出,带入:

使用案例

func main() {
	//生成签名----
	//声明明文
	message := []byte("hello world")
	//生成私钥
	privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	//生成公钥
	pub := privateKey.PublicKey
	//将明文散列
	digest := sha256.Sum256(message)
	//生成签名
	r, s, _ := ecdsa.Sign(rand.Reader, privateKey, digest[:])
	//设置私钥的参数类型为曲线类型
	param := privateKey.Curve.Params()
	//获得私钥byte长度
	curveOrderByteSize := param.P.BitLen() / 8
	//获得签名返回值的字节
	rByte, sByte := r.Bytes(), s.Bytes()
	//创建数组
	signature := make([]byte, curveOrderByteSize*2)
	//通过数组保存了签名结果的返回值
	copy(signature[curveOrderByteSize-len(rByte):], rByte)
	copy(signature[curveOrderByteSize*2-len(sByte):], sByte)
 
	//验证----
	//将明文做hash散列,为了验证的内容对比
	digest = sha256.Sum256(message)
	curveOrderByteSize = pub.Curve.Params().P.BitLen() / 8
	//创建两个整形对象
	r, s = new(big.Int), new(big.Int)
	//设置证书值
	r.SetBytes(signature[:curveOrderByteSize])
	s.SetBytes(signature[curveOrderByteSize:])
 
	//验证
	e := ecdsa.Verify(&pub, digest[:], r, s)
	if e == true {
		fmt.Println("success")
	} else {
		fmt.Println("failed")
	}
}

参考

https://mindcarver.cn

https://juejin.cn/post/6844903671411671047

https://juejin.cn/post/6844903882343071758

http://read.pudn.com/downloads54/sourcecode/windows/188357/ECDSA%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0%E5%8F%8A%E5%85%B6%E5%AE%89%E5%85%A8%E6%80%A7%E5%88%86%E6%9E%90.pdf

https://zhuanlan.zhihu.com/p/94852431