
image

image
- 隨機(jī)數(shù)字K用作臨時(shí)私鑰,進(jìn)而生成臨時(shí)公鑰(與生成比特幣公鑰方式相同)。
- R代表臨時(shí)公鑰x軸坐標(biāo)
- k還是剛剛的臨時(shí)私鑰
- dA代表簽名私鑰(不是剛剛的臨時(shí)私鑰)
- z是交易數(shù)據(jù)的hash值—>hash(交易數(shù)據(jù))
- p是素?cái)?shù),橢圓曲線的主要順序(這一點(diǎn)沒(méi)有理清楚,待定)
==R+S就是簽名==
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"fmt"
"log"
)
//生成私鑰和公鑰,生成的私鑰為結(jié)構(gòu)體ecdsa.PrivateKey的指針
//type PrivateKey struct {
// PublicKey
// D *big.Int
//}
func newKeyPair2() (ecdsa.PrivateKey, []byte) {
//生成橢圓曲線
curve := elliptic.P256()
//產(chǎn)生的是一個(gè)結(jié)構(gòu)體指針,結(jié)構(gòu)體類(lèi)型為ecdsa.PrivateKey
private, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
log.Panic(err)
}
//x坐標(biāo)與y坐標(biāo)拼接在一起,生成公鑰
pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...)
return *private, pubKey
}
func main(){
//調(diào)用函數(shù)生成私鑰與公鑰
privKey,_ := newKeyPair2()
//信息的哈希,簽名什么樣的數(shù)據(jù)
hash := sha256.Sum256([]byte("hello world\n"))
//根據(jù)私鑰和信息的哈希進(jìn)行數(shù)字簽名,產(chǎn)生r和s
r, s, err := ecdsa.Sign(rand.Reader, &privKey, hash[:])
if err != nil {
log.Panic(err)
}
//r和s拼接在一起實(shí)現(xiàn)了數(shù)字簽名
signature := append(r.Bytes(), s.Bytes()...)
//打印數(shù)字簽名的16進(jìn)制顯示
fmt.Printf("%x\n", signature)
fmt.Printf("%x\n", r.Bytes())
fmt.Printf("%x\n", s.Bytes())
//補(bǔ)充:如何把一個(gè)字符串轉(zhuǎn)換為16進(jìn)制數(shù)據(jù)
//m := big.Int{}
//n := big.Int{}
//rr,_:=hex.DecodeString("7dccc0f58639584a3f0c879c3688d2f4a0137697cbf34245d075c764e36233d2")
//ss,_:=hex.DecodeString("cf3713bf4369eb1c02e476cdbefb7f76a25b572f53fb71d4e4742fa11c827526")
//
//m.SetBytes(rr)
//n.SetBytes(ss)
//
//fmt.Printf("%x\n", m.Bytes())
//fmt.Printf("%x\n", n.Bytes())
}
驗(yàn)證數(shù)據(jù)簽名
驗(yàn)證是生成簽名函數(shù)的倒數(shù),使用R、S、公鑰來(lái)計(jì)算一個(gè)P,這個(gè)P是橢圓曲線上的一個(gè)點(diǎn),就是剛剛簽名創(chuàng)建中生成的臨時(shí)公鑰

image
- R、S是簽名值
- Qa是簽名私鑰(不是臨時(shí)私鑰)
- m是交易數(shù)據(jù)
- G是橢圓曲線發(fā)生器點(diǎn)(不同橢圓的G點(diǎn)不同,相同橢圓曲線G點(diǎn)相同)
如果計(jì)算的P點(diǎn)的x坐標(biāo)等于R,則證明簽名有效
==驗(yàn)證簽名時(shí),私鑰既不知道,也不顯示==
package main
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"crypto/elliptic"
"log"
"fmt"
"math/big"
)
//生成私鑰和公鑰,生成的私鑰為結(jié)構(gòu)體ecdsa.PrivateKey的指針
//type PrivateKey struct {
// PublicKey
// D *big.Int
//}
func newKeyPair3() (ecdsa.PrivateKey, []byte) {
//生成secp256k1橢圓曲線
curve := elliptic.P256()
//產(chǎn)生的是一個(gè)結(jié)構(gòu)體指針,結(jié)構(gòu)體類(lèi)型為ecdsa.PrivateKey
private, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
log.Panic(err)
}
//x坐標(biāo)與y坐標(biāo)拼接在一起,生成公鑰
pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...)
return *private, pubKey
}
func main(){
//生成公鑰和私鑰
privKey,pubkey := newKeyPair3()
//生成某一串信息的哈希值,需要簽名的數(shù)據(jù)
hash := sha256.Sum256([]byte("ruok?\n"))
//根據(jù)私鑰和信息的哈希值生成數(shù)字簽名的r和s,r和s拼接在一起就是數(shù)字簽名,在這里省略了拼接的步驟,欲查看,請(qǐng)看3.數(shù)字簽名
r, s, _ := ecdsa.Sign(rand.Reader, &privKey, hash[:])
//fmt.Printf("%v\n", *r)
//fmt.Printf("%v\n", *s)
////生成secp256k1橢圓曲線
curve := elliptic.P256()
//公鑰的長(zhǎng)度
keyLen := len(pubkey)
//前一半為x軸坐標(biāo),后一半為y軸坐標(biāo)
x := big.Int{}
y := big.Int{}
x.SetBytes(pubkey[:(keyLen / 2)])
y.SetBytes(pubkey[(keyLen / 2):])
//rawPubKey為生成PublicKey結(jié)構(gòu)體,作為下面ecdsa.Verify的參數(shù)
//type PublicKey struct {
// elliptic.Curve
// X, Y * big.Int }
//公鑰
rawPubKey := ecdsa.PublicKey{curve, &x, &y}
//根據(jù)交易哈希、公鑰、數(shù)字簽名驗(yàn)證成功。ecdsa.Verify func Verify(pub *PublicKey, hash []byte, r *big.Int, s *big.Int) bool
if ecdsa.Verify(&rawPubKey, hash[:], r, s) == false {
fmt.Printf("%s\n", "驗(yàn)證失敗")
}else{
fmt.Printf("%s\n", "驗(yàn)證成功")
}
//用其他的信息哈?!C明驗(yàn)證失敗
hash2 := sha256.Sum256([]byte("我要給你200愿\n"))
if ecdsa.Verify(&rawPubKey, hash2[:], r, s) == false {
fmt.Printf("%s\n", "驗(yàn)證失敗")
}else{
fmt.Printf("%s\n", "驗(yàn)證成功")
}
}