做者:林冠宏 / 指尖下的幽灵git
GitHub : https://github.com/af913337456/数组
腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities安全
最近的工做一直是基于 以太坊公链 作 DApp 开发,虽然对其各 API 的调用都已经很了解了,可是源码部分一直还没深刻去看过。工欲善其事,必先利其器,故计划阅读完 以太坊go 版源码,后续会更新系列文章。本文主要简谈 sendRawTransaction 是如何保证咱们交易安全的。函数
sendRawTransaction
- 传入各参数 ---->
- 使用
from
对应的privateKey
与secp256k1
算法对各入参
签名得出三个量:V
,R
,S
---->
RLP
(递归长度前缀
) 方式序列比签名的数据 与 原入参数据 ---->
- 发送到 ETH 节点
sendRawTransaction
函数的各个入参:编码
它们都将会被 from
所对应的密钥
进行签名而得出三个量:V
,R
,S
。同时,各个入参依然以原来的可见的形式进入序列化步骤。加密
还有另一个叫作 sendTransaction
的方法,经过分析源码
,能够发现 sendTransaction
内部其实会帮助咱们根据咱们传参的 from
字段到节点的 accountManager
帐号管理器中获取from
的密钥,来帮咱们进行数据签名,因此,sendTransaction
通常不会用于远程调用,而用于本地调用,由于只有在本地启动节点的时候,才能配置咱们解锁的钱包。code
所用的签名加密方式是:非对称加密
中的 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 个,等数据传到以太坊的时候,在检查签名的时候,就会发现不匹配,而抛出错误。