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

生成签名
假设 Alice 希望对消息进行签名,所采用的椭圆曲线参数为,对应的密钥对为,其中为公钥,为私钥。
Alice 将按如下步骤进行签名:
- 产生一个随机数,. (签名算法首先生成一个临时私公钥对,该临时密钥对用于计算 r 和 s 值。)
- 计算,将化为整数.
- 计算,若,则转向第1步. (r 值为临时公钥的坐标 x 值)
- 计算
- 计算哈希值,并将得到的比特串转化为整数 e
- 计算,若,则转向第1步.
- 即为 Alice 对消息的签名.
椭圆曲线签名验证
为验证 Alice 对消息 m 的签名,Bob 需要得到 Alice 所用的椭圆曲线参数以及 Alice 的公钥 Q。
步骤如下:
- 验证 r 和 s 是区间上的整数.
- 计算并将其转化为整数 e.
- 计算
- 计算以及
- 计算
- 若,则拒绝签名,否则将 X 的坐标转化为整数,并计算
- 当且仅当时,签名通过验证.
椭圆曲线签名正确性
要证明,只需要证明即可。
证明步骤:
令:
将、带入:
由得出,带入:
使用案例
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://juejin.cn/post/6844903671411671047