想知道更多關於區塊鏈技術知識,請百度【鏈客區塊鏈技術問答社區】 鏈客,有問必答!!
數字簽名在信息安全,包括身份認證、數據完整性、不能否認性以及匿名性有着重要應用,是現代密碼學的重要分支。簽名隸屬於公鑰密碼學。簽名過程:發送方用本身的私鑰對發送信息進行所謂的加密運算,獲得一個hash值,該hash值就是簽名。使用時須要將簽名和信息發給接收方。接受者用發送方公開的公鑰和接收到的信息對簽名進行驗證,經過認證,說明接收到的信息是完整的、準確的,不然說明消息來源不對。算法
簡單描述數字簽名:私鑰簽名;公鑰驗籤。數組
1 普通簽名
簽名只是用一把私鑰,而且是發送方本身進行地簽名動做,這類簽名就是普通簽名。經常使用的簽名方法有較多,包括RSA數字簽名、DSS數字簽名、ElGamal數字簽名、ECDSA數字簽名等等。其中RSA和ECDSA簽名已經在加密算法中有講解。區塊鏈項目中最經常使用的簽名方法是ECDSA數字簽名。簽名和驗籤的原理不做講解,感興趣能夠翻閱以前的章節。安全
由於ECDSA數字簽名在區塊鏈的重要性,我接下來只對它進行講解如何應用。
下邊代碼展現簡單地用ECDSA簽名對數據BLOCK進行簽名,上鍊以前須要先進行驗證,驗證經過以後才能上鍊。具體解析在代碼中有說明。app
過程:
1.經過ecdsa.GenerateKey產生一私鑰;輸出的私鑰是指針類型;
2.經過私鑰產生公鑰;
3.對數據BLOCK進行hash運算,實際公鏈中就是挖礦過程;
4.爲了能夠給任何長度的data進行簽名,咱們建立本身的簽名方法;
5.驗證數據是否合法,也就是經過公鑰對簽名進行驗證,經過後才能對數據進行上鍊動做。函數
package main區塊鏈
import (加密
"bytes" "encoding/binary" "log" "time" "crypto/sha256" "fmt" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "math/big"
)代理
//簡單的區塊鏈塊結構
type Block struct {指針
//1. 區塊高度 Height int64 //2. 上一個區塊HASH PrevBlockHash []byte //3. 交易數據 Data []byte //4. 時間戳 Timestamp int64 //5. 實際經過挖礦獲得Hash Hash []byte // 6. 隨機數Nonce Nonce int64
}code
func main() {
//調用底層函數,產生私鑰
prk,_:=ecdsa.GenerateKey(elliptic.P256(),rand.Reader) //生成公鑰 pubkey:=prk.PublicKey //須要上鍊的數據 data:=[]byte("helloworld") //手動建立一個區塊信息,實際中,經過交易來觸發自動建立block block:=&Block{2,nil,data,time.Now().Unix(),nil,0} //將block信息內容拼接成字節數組 blockbytes:=prepareData(block) //對block進行hash運算,實際中是挖礦過程 blockHash:=sha256.Sum256(blockbytes)
//簽名
signatrue,_:=Sign(blockHash[:],prk)
//驗證,若是經過就進行上鍊處理,不然rollback
if Verify(blockHash[:],signatrue,&pubkey){ fmt.Println("該block合法,能夠上鍊") }else { fmt.Println("該Block不合法,rollback") }
}
//數據拼接
func prepareData(block *Block) []byte {
Block:=block data := bytes.Join( [][]byte{ Block.PrevBlockHash, Block.Data, IntToHex(Block.Timestamp), Block.Data, IntToHex(int64(Block.Nonce)), IntToHex(int64(Block.Height)), }, []byte{}, ) return data
}
// 將int64轉換爲字節數組
func IntToHex(num int64) []byte {
buff := new(bytes.Buffer) err := binary.Write(buff, binary.BigEndian, num) if err != nil { log.Panic(err) } return buff.Bytes()
}
func Sign(data []byte, privkey *ecdsa.PrivateKey) ([]byte, error) {
// 對要簽名的信息進行sha256散列,生成一個長度爲32的字節數組 digest := sha256.Sum256(data) // 經過橢圓曲線方法對散列後的明文進行簽名,返回兩個big.int類型的大數 r, s, err := ecdsa.Sign(rand.Reader, privkey, digest[:]) if err != nil { return nil, err } //將大數轉換成字節數組,並拼接起來,造成簽名 signature := append(r.Bytes(), s.Bytes()...) return signature, nil
}
// 經過公鑰驗證簽名
func Verify(data, signature []byte, pubkey *ecdsa.PublicKey) bool {
// 將明文轉換成字節數組 digest := sha256.Sum256(data) //聲明兩個大數r,s r := big.Int{} s := big.Int{} //將簽名平均分割成兩部分切片,並將切片轉換成*big.int類型 sigLen := len(signature) r.SetBytes(signature[:(sigLen / 2)]) s.SetBytes(signature[(sigLen / 2):]) //經過公鑰對獲得的r,s進行驗證 return ecdsa.Verify(pubkey, digest[:], &r, &s)
}
2 羣簽名
1991年,Chaum和Van Heyst首次提出了羣簽名的概念。羣簽名容許一個羣體中的任意一個成員以匿名的方式表明整個羣體對消息進行簽名。
羣簽名須要有一個集體,通常是公司。管理員經過認證添加羣簽名的成員,每一個成員的簽名都表明集體。利用羣簽名能夠很好的隱藏組織結構。例如,一個公司的職員能夠利用羣簽名方案表明公司進行簽名,驗證者(多是公司顧客)只須要利用公司的羣公鑰進行簽名的合法性驗證。驗證者並不知道該簽名是由哪一個職員所簽名的。當發生爭議時,羣管理員能夠識別出實際的簽名者。固然,羣簽名還能夠應用於電子投票、電子投標和電子現金等。
如何實現羣簽名呢?
入羣:羣成員在入羣以前都會向羣管理進行申請入羣,經過後,申請人會和羣管理員達成交互式協議,該協議可生成羣成員的私鑰。羣管理員對該密鑰進行簽名,並頒發給申請人,完成入羣。羣成員羣管理員將羣公鑰對外公開。
簽名:羣成員經過本身的羣密鑰和羣公鑰對消息進行簽名,獲得羣簽名。
驗證:經過輸入羣公鑰和羣簽名用公開的某種驗證方法進行驗證,返回值只有真假,驗證者沒法計算獲得簽名者是羣公鑰裏的具體人員,只知道該簽名者屬於羣公鑰裏的,能夠表明羣體。
追蹤:羣管理員能夠經過羣簽名獲得具體是哪一個羣成員進行簽名的。
羣簽名是一箇中心化的簽名結構,該結構的算法都是羣管理員定的,形成簽名者的隱私沒有作到真正的保障。
因此總結羣簽名有三點:
1.只有羣體中的合法成員才能表明整個羣體進行簽名;
2.接收者能夠用羣公鑰驗證羣簽名的合法性,但不知道該羣簽名是羣體具體哪一個成員所籤;、
3.在發生爭議時,羣管理員能夠識別出實際的簽名者。
3 環簽名
環簽名由Rivest,shamir和Tauman三位密碼學家在2001年首次提出。因簽名中參數Ci(i=1,2,…,n)根據必定的規則首尾相接組成環狀而得名。其實就是實際的簽名者用其餘可能簽名者的公鑰產生一個帶有斷口的環,而後用私鑰將斷口連成一個完整的環。
環簽名能夠認爲是不可追蹤的羣簽名,實際的操做過程都是本身完成的,沒有羣管理員。
簽名者是某個羣體的成員,他把其餘羣體的公鑰拿來並加上本身的公鑰組合成一個羣公鑰,而後用本身的私鑰和羣公鑰對要發佈的信息進行環簽名。接收者接收到羣公鑰、簽名和信息,而後對簽名進行驗證,若是簽名來自羣公鑰,那麼驗證成功,不然消息不合法。
羣公鑰中籤名者的公鑰只是迷惑做用,並不對數據有任何操做。
造成的簽名由於是每一個其它羣公鑰產生的數據和本身用私鑰產生的數據組成的環,本身的數據隱藏環中,攻擊者很難找到簽名者的公鑰。因此簽名者的隱私很好地被保護起來了。
4 代理簽名
1996年,Mambo等人首次提出了代理簽名的概念。在代理簽名方案中,容許一個原始簽名者把他的簽名權利委託給一個稱爲代理簽名者的人,而後代理簽名者就能夠表明原始簽名者進行簽名。代理簽名者可用於須要委託權力的密碼協議中,如電子現金、移動代理和移動通訊等。
5 盲簽名
1982年Chaum首次提出了盲簽名的概念。盲簽名容許使用者得到一個消息的簽名,而簽名者既不知道該消息的內容,也不知道該消息的簽名。盲簽名可用於須要提供匿名性的密碼協議中,如電子投票和電子現金。
一個盲簽名方案由如下部分組成。
1)消息盲化:使用者利用盲因子對要簽名的信息進行盲化處理,而後將盲化後的消息發送給簽名者。
2)盲消息簽名:簽名者對盲化後的消息進行簽名,所以他並不知道真實消息的具體內容。
3)恢復簽名:使用者除去盲因子,獲得真實消息的簽名。
6 零知識證實零知識證實:實質上是一種涉及兩方或更多方的協議,即兩方或更多方完成一項任務所需採起的一系列步驟。證實者向驗證者證實並使其相信本身知道或擁有某一消息,但證實過程不能向驗證者泄漏任何關於被證實消息的信息。簡單理解,就是證實者可以在不向驗證者提供任何有用信息的狀況下,讓驗證者相信你。