做者:林冠宏 / 指尖下的幽靈git
掘金:juejin.im/user/587f0d…github
GitHub : github.com/af913337456…數組
騰訊雲專欄: cloud.tencent.com/developer/u…安全
最近的工做一直是基於 以太坊公鏈 作 DApp 開發,雖然對其各 API 的調用都已經很瞭解了,可是源碼部分一直還沒深刻去看過。工欲善其事,必先利其器,故計劃閱讀完 以太坊go 版源碼,後續會更新系列文章。本文主要簡談 sendRawTransaction 是如何保證咱們交易安全的。函數
PS:本人技術書籍:《區塊鏈以太坊DApp開發實戰》已經出版並能夠網購了區塊鏈
sendRawTransaction
- 傳入各參數 ---->
- 使用
from
對應的privateKey
與secp256k1
算法對各入參
簽名得出三個量:V
,R
,S
---->
RLP
(遞歸長度前綴
) 方式序列比簽名的數據 與 原入參數據 ---->
- 發送到 ETH 節點
sendRawTransaction
函數的各個入參:ui
它們都將會被 from
所對應的密鑰
進行簽名而得出三個量:V
,R
,S
。同時,各個入參依然以原來的可見的形式進入序列化步驟。編碼
還有另一個叫作 sendTransaction
的方法,經過分析源碼
,能夠發現 sendTransaction
內部其實會幫助咱們根據咱們傳參的 from
字段到節點的 accountManager
帳號管理器中獲取from
的密鑰,來幫咱們進行數據簽名,因此,sendTransaction
通常不會用於遠程調用,而用於本地調用,由於只有在本地啓動節點的時候,才能配置咱們解鎖的錢包。加密
所用的簽名加密方式是:非對稱加密
中的 secp256k1
橢圓曲線算法
它是一類加密方式的統稱。具體到某種能實現它的算法有下面幾種:
而 sendRawTransaction
用到的就是 secp256k1
RLP
(遞歸長度前綴
)提供了一種適用於任意二進制數據數組的編碼,RLP已經成爲以太坊中對對象進行序列化的主要編碼方式。RLP的惟一目標就是解決結構體的編碼問題;對原子數據類型(好比,字符串,整數型,浮點型)的編碼則交給更高層的協議;以太坊中要求數字必須是一個大端字節序的、沒有零佔位的存儲的格式。
簽名後,數據將會被髮送到 ETH 節點。
對應到以太坊的 sendRawTransaction
RPC 接口。
func (s *PublicTransactionPoolAPI) SendRawTransaction(..., encodedTx hexutil.Bytes) (common.Hash, error) {
tx := new(types.Transaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil { // 反序列化
return common.Hash{}, err
}
return submitTransaction(ctx, s.b, tx)
}
複製代碼
檢查簽名
,所使用的是 secp256k1.RecoverPubkey
方法,secp256k1 自己支持根據簽名信息反推公鑰
用消息和簽名推導出對方的公鑰。再經過公鑰,簽名,消息的哈希值計算出一個叫
r
的值,這個r
是簽名的一部分,校驗簽名就是拿計算出來的r
和簽名中攜帶的r
經行對比,若是一致就校驗經過
if C.secp256k1_ext_ecdsa_recover(
context,
(*C.uchar)(unsafe.Pointer(&pubkey[0])),
sigdata, // 簽名
msgdata) == 0 { // msgdata tx 的 hash 內容
return nil, ErrRecoverFailed
}
複製代碼
由於簽名生成的 V R S 是由私鑰進行簽名的,若是修改者只修改了外部的值,例如 value
,原本是要轉 10 個 ETH , 被改爲轉 100 個,等數據傳到以太坊的時候,在檢查簽名的時候,就會發現不匹配,而拋出錯誤。