數(shù)據(jù)簽名

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)證成功")
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 先放一張以太坊的架構(gòu)圖: 在學(xué)習(xí)的過(guò)程中主要是采用單個(gè)模塊了學(xué)習(xí)了解的,包括P2P,密碼學(xué),網(wǎng)絡(luò),協(xié)議等。直接開(kāi)...
    麻臉大叔閱讀 11,534評(píng)論 1 10
  • 原文地址 https://mbinary.coding.me/introduction-to-bitcoin.ht...
    mbinary閱讀 5,708評(píng)論 0 4
  • 每個(gè)人都可能以某種形式聽(tīng)說(shuō)過(guò)ECDSA。當(dāng)我說(shuō)“數(shù)字簽名”時(shí),有些哥們會(huì)更好地認(rèn)識(shí)到這一點(diǎn),當(dāng)然有些哥們根本不知道...
    wolf4j閱讀 1,810評(píng)論 2 2
  • 原諒我的一時(shí)迷茫 原諒我的一時(shí)無(wú)助 原諒我的一時(shí)冷漠 原諒我的 感謝有你,讓我再次找到目標(biāo) 感謝有你,讓我再次獲得...
    星韻追閱讀 175評(píng)論 0 0
  • 第24周檢視: 八大關(guān)注: 好習(xí)慣:①早睡早起②每天閱讀③運(yùn)動(dòng) ①個(gè)人:最近這一周自己的狀態(tài)并不是很好。在閱讀...
    李尚琴閱讀 282評(píng)論 0 2

友情鏈接更多精彩內(nèi)容