本文主要是介绍从Metamask区块链签名到钓鱼案例分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 从Metamask区块链签名到钓鱼案例分析
- 一、什么是metamsk
- 二、公钥、私钥和数字签名
- 三、椭圆加密算法(ECC)
- 1. 关于ECDSA/ECC
- 2. 椭圆曲线数字签名算法(ECDSA)原理
- 3. golang使用ecdsa签名和验签
- 4. secp256k1
- 四、区块链中的签名
- 区块链签名分类
- Personal Sign
- eth_sign签名(非常危险的签名方式)
- EIP712 Sign
- 五、 以太坊交易签名
- 递归长度前缀编码RLP(Recursive Length Rrefix)
- 交易签名
- 以太坊交易签名整体流程
- 1. 构建原始交易对象
- 2. 签署交易
- 3. 验签
- 六、钓鱼签名案例
- 以太坊账户(Ethereum account)
- 钓鱼签名举例
- 钓鱼合约代码
- 如何对抗钓鱼网址的反调试技巧?
- 总结
- 参考
从Metamask区块链签名到钓鱼案例分析
一、什么是metamsk
MetaMask(小狐狸钱包)是一个浏览器插件,可以用作以太坊钱包,并且可以像任何常规插件一样安装。安装之后,它允许用户存储 Ether 和其他 ERC-20 令牌,从而使他们能跟其他以太坊地址之间进行交易转账。
MetaMask 在用户的浏览器中保存私钥。
二、公钥、私钥和数字签名
- 公钥加密的数据只有对应的私钥才可以解密(公钥加密后公钥也不能解密)
- 私钥加密的数据也只有对应的公钥才可以解密。
A 收到消息后如何确认发信人是 B 而不是第三方呢?其实也很简单,只要发消息前多进行一次使用自己的私钥加密的过程就可以了,这次使用自己私钥加密信息的步骤就叫做签名。
公钥一般用来加密,私钥用来签名。
由于非对称加密是复杂且耗时的,而且需要加密的内容越长就越耗时。在实际使用中一般经过摘要算法得到一串哈希值,然后使用私钥对哈希值进行加密。习惯性将这样对摘要使用私钥加密生成的文件叫做签名文件。
以太坊使用的数字签名算法叫双椭圆曲线数字签名算法(ECDSA),基于双椭圆曲线“私钥-公钥”对的数字签名算法。它主要起到了三个作用:
- 身份认证:证明你拥有地址的私钥;
- 不可否认:确认你的确发布过该消息;
- 完整性:确保信息没有被篡改;
三、椭圆加密算法(ECC)
椭圆加密算法(ECC)是一种公钥加密体制,最初由Koblitz和Miller两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。
相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全,RSA加密算法也是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用。
1. 关于ECDSA/ECC
ECC:Elliptic Curves Cryptography,椭圆曲线密码编码学。
椭圆曲线数字签名算法(ECDSA):用于数字签名,是ECC与DSA的结合,整个签名过程与DSA类似,所不一样的是签名中采取的算法为ECC,最后签名出来的值也是分为r,s。
椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟。
2. 椭圆曲线数字签名算法(ECDSA)原理
ECDSA是ECC与DSA的结合,整个签名过程与DSA类似,所不一样的是签名中采取的算法为ECC,最后签名出来的值也是分为r,s。
签名过程如下:
1、选择一条椭圆曲线Ep(a,b),和基点G;
2、选择私有密钥k(k<n,n为G的阶),利用基点G计算公开密钥K=kG;
3、产生一个随机整数r(r<n),计算点R=rG;
4、将原数据和点R的坐标值x,y作为参数,计算SHA1做为hash,即Hash=SHA1(原数据,x,y);
5、计算s≡r - Hash * k (mod n)
6、r和s做为签名值,如果r和s其中一个为0,重新从第3步开始执行
验证过程如下:
1、接受方在收到消息(m)和签名值(r,s)后,进行以下运算
2、计算:sG+H(m)P=(x1,y1), r1≡ x1 mod p。
3、验证等式:r1 ≡ r mod p。
4、如果等式成立,接受签名,否则签名无效。
3. golang使用ecdsa签名和验签
椭圆曲线加密算法
参考URL: https://blog.csdn.net/weixin_42117918/article/details/103221756
go使用库 “crypto/ecdsa” 、“crypto/x509”
整体应用过程:
- 生成椭圆曲线的公钥和私钥
// 生成密钥privateKey, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
// 保存密钥
// x509编码x509PrivateKey, _ := x509.MarshalECPrivateKey(privateKey)保存公钥//
// x509编码x509PublicKey, _ := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
- 根据 待签名数据和私钥,生成两个big.Int r和s, r和s就是签名结果
func Sign(rand io.Reader, priv *PrivateKey, hash []byte)
- 根据公钥,明文,r,s验证签名
func Verify(pub *PublicKey, hash []byte, r, s *big.Int)
4. secp256k1
谁能最简单的详解椭圆曲线算法,secp256k1 是如何生成公钥和私钥的?
参考URL: https://www.zhihu.com/question/22399196/answer/330577147
比特币使用基于椭圆曲线加密的椭圆曲线数字签名算法(ECDSA)。特定的椭圆曲线称为secp256k1。
secp256k1 是区块链项目中应用最多的椭圆曲线算法,源于比特币中的应用(比特币选择的椭圆曲线是名为secp256k1的曲线),后来的大多数区块链项目如以太坊等都在用。
secp256k1的私钥地址长度是32字节256位,公钥地址长度是65字节,而以太坊的地址长度是20字节,
名称中的前三个字母sec代表Standards for Efficient Cryptography (SEC)
后面的p256K1指的是参数256位素数域。
secp256k1是一条用于密码学的椭圆曲线,它总共包含以下6个参数:
四、区块链中的签名
签名示例 原文链接:https://www.ud.hk/sc/thoughtleader/article/blockchain-security-metamask-wallet-3-signature-mechanisms
区块链上,当你进行一个交易时,除了要指示区块链「要做什麽」,还需要进行身份认证,确保你是真正的账户拥有者,才可进行相应操作。 这个身份认证,就是我们所说的「签名」。
签名的具体做法,是使用你保存在区块链钱包(如 MetaMask)中的私钥(Private Key)通过加密算法,对你发出的指示做数字签署,而这个签署,是可以透过与你的地址公钥(Public Key)比对从而认证确实是你发出的相应指示,而完成认证过程。另外,「签名」这个动作,可以是不需要上链的。在没有网路的情况下亦可进行。
区块链签名分类
以太坊签名分为对消息签名与对交易签名,这两种签名都是基于ECDSA算法与流程。
在以太坊、比特币中这个算法是经过二次开发的ECDSA(原始的ECDSA只有r、s组成,以太坊、比特币的ECDSA由r、s、v组成)。
在整个过程中交易签名是重中之重。换句话说,黑客可以伪造一个交易,骗取你的交易签名,然后黑客便可以使用这个签名,执行该伪造交易,从而导致你在莫名其妙的情况下,损失资产。而交易签名洩露,也就是许多数字资产被盗的元凶之一。
Personal Sign
Personal Sign 可以用于签署一段 UTF-8 编码的文字,使用这种方法,MetaMask会清楚显示被签名的内容 ,这种方式常见于网站登入。
Personal Sign常见Web3 登录签名。,查看学习:
OpenSea、crew3 登入, 就是使用了 Personal Sign 这个方式。
personal_sign 规范被提及:https://github.com/ethereum/go-ethereum/pull/2940 它为数据添加了一个前缀,因此它不能模拟交易。我们还使这种方法能够在 UTF-8 编码时显示人类可读的文本,使其成为站点登录的流行选择。
JSON-RPC eth_sign
是一种开放式签名方法,允许对任意散列进行签名,这意味着它可用于对交易或任何其他数据进行签名,使其具有危险的网络钓鱼风险。
通过向消息添加前缀,可以将计算出的签名识别为以太坊特定签名。这可以防止恶意 dapp 可以签署任意数据(例如交易)并使用签名冒充受害者的滥用。
eth_sign签名(非常危险的签名方式)
ethsign 是 MetaMask 很早期提供的签名方法,这个方法需要传入一个 32 byte 的杂凑数 (Hash) 以供签名,而杂凑数可以是由任何内容得到,因此,仅凭这个无意义的杂凑数,签名者完全不会知道自己正在签署什么内容,这个内容可能是一个交易,一个授权,也可能是网站登入请求,又或者其它任何内容,因此有非常大的风险,现在 MetaMask 已经开始对这类的签名请求弹出红色警告,以警示用户。
EIP712 Sign
EIP712 Sign是一种更安全的签名标准,这个标准规定了签名数据的结构,也加入了对数据的作用域限制,如 domain,验证合约地址等。
这个标准的好处是,签名者可以清楚看到自己在签署的内容,很大程度上降低被钓鱼的风险。 但是,这并不等于这种签名是绝对安全的,签名时,一定要看清楚究竟在签署什么内容。
五、 以太坊交易签名
递归长度前缀编码RLP(Recursive Length Rrefix)
以太坊 RLP编码
参考URL: http://www.codebaoku.com/eth/eth-src-rlp-encode.html
RLP(Recursive Length Rrefix)递归长度前缀编码, 是以太坊对象进行序列化的主要编码方式,主要用于以太坊中数据的网络传输和持久化存储。
RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式。RLP的唯一目标就是解决结构体的编码问题;对原子数据类型(比如,字符串,整数型,浮点型)的编码则交给更高层的协议;以太坊中要求数字必须是一个大端字节序的、没有零占位的存储的格式。
总结:
RLP是以太坊中用于序列化对象的主要编码方法。RLP的唯一目的是对结构进行编码。RLP(Recursive Length Prefix)可以将任意的数据编码为二进制byte的数组,即[]byte的形式。
交易签名
在以太坊实现的ECDSA中,被签名的“消息”是交易,或者更确切地说,来自交易的RLP编码数据的Keccak256哈希。
在进行交易广播前,MetaMask 会获取我们转账的对象(to)、转账的金额(value)、附带的数据(data),以及 MetaMask 自动帮我们获取并计算的 nonce、gasPrice、gasLimit 参数进行 RLP 编码得到原始交易内容(rawTransaction)。如果是合约调用,那么 to 即为合约地址,data 即为调用数据。
以太坊交易签名整体流程
web3.eth.sendTransaction
参考URL: http://cw.hubwiz.com/card/c/web3.js-1.0/1/2/21/
eth_sendRawTransaction流程分析
参考URL: https://www.jianshu.com/p/c53e00067ddf
传入各参数 ---->
使用from 对应的 privateKey 与 secp256k1 算法对 各入参 签名得出三个量:V,R,S ---->
RLP (递归长度前缀) 方式序列比签名的数据 与 原入参数据 ---->
发送到 ETH 节点
- web3.eth.sendTransaction()方法向以太坊网络提交一个交易。
- from - String|Number: 交易发送方账户地址,不设置该字段的话,则使用web3.eth.defaultAccount属性值。可设置为一个地址或本地钱包。(sendTransaction 内部其实会帮助我们根据我们传参的 from 字段到节点的 accountManager 账号管理器中获取from 的密钥,来帮我们进行数据签名)
- to - String: 可选,消息的目标地址,对于合约创建交易该字段为null
- value - Number|String|BN|BigNumber: (optional) The value transferred for the transaction in wei, also the endowment if it’s a contract-creation transaction.
- gas - Number: 可选,默认值:待定,用于交易的gas总量,未用完的gas会退还
- gasPrice - Number|String|BN|BigNumber: 可选,该交易的gas价格,单位为wei,默认值为web3.eth.gasPrice属性值
- data - String: 可选,可以是包含合约方法数据的ABI字符串,或者是合约创建交易中的初始化代码
- nonce - Number: 可选,使用该字段覆盖使用相同nonce值的挂起交易
- callback - Function: 可选的回调函数,其第一个参数为错误对象,第二个参数为结果
它们都将会被 from 所对应的密钥 进行签名而得出三个量:V,R,S。同时,各个入参依然以原来的可见的形式进入序列化步骤。
web3.eth.sendTransaction()方法的返回值是32字节长的交易哈希值。
- 对应到以太坊的 sendRawTransaction RPC 接口(internal/ethapi/api.go)SendRawTransaction方法)
收到 RLP 序列化的数据后,先进行 RLP 的反序列化
据的基础校验,主要是一些范围限制以及格式限制校验
tx.Size() > 32*102
tx.Value().Sign() < 0
pool.currentMaxGas < tx.Gas()
…
检查签名,所使用的是 secp256k1.RecoverPubkey 方法,secp256k1 本身支持根据签名信息反推公钥用消息和签名推导出对方的公钥。
再通过公钥,签名,消息的哈希值计算出一个叫 r 的值,这个 r 是签名的一部分,校验签名就是拿计算出来的 r 和签名中携带的 r 经行对比,如果一致就校验通过。
所用的签名加密方式是:非对称加密 中的 secp256k1 椭圆曲线算法
1. 构建原始交易对象
可以使用JavaScript对象表示法(JSON)描述事务:
var rawTransaction = {"from": myAddress,"nonce": web3.utils.toHex(nonceCnt),// "gasLimit": web3.utils.toHex(80000000),"gasPrice": web3.utils.toHex(10e9),"to": contractAddress,"value": web3.utils.toHex(transferAmount),"data": myContract.methods.SecurityUpdate().encodeABI(),"chainId": 0x1691 //4:Rinkeby, 3:Ropsten, 1:mainnet 开发网:5777->1691};
- nonce: 记录发起交易的账户已执行交易总数。Nonce的值随着每个新交易的执行不断增加,这能让网络了解执行交易需要遵循的顺序,并且作为交易的重放保护。
- gasPrice:该交易每单位gas的价格,Gas价格目前以Gwei为单位(即10^9wei),其范围是大于0.1Gwei,可进行灵活设置。 一个Gas Price就是单价,交易费用=Gas*Gas Price。一般单位为 Gwei。
- gasLimit:该交易支付的最高gas上限。该上限能确保在出现交易执行问题(比如陷入无限循环)之时,交易账户不会耗尽所有资金。一旦交易执行完毕,剩余所有gas会返还至交易账户。
一枚 ETH 分为:Finney,Szabo,Gwei,Mwei,Kwei 和 Wei,其中Wei是最小的 ETH 单位,一个ETH 等于一千 Finney,一百万 Szabo,十亿Gwei和百万万亿 Wei 。
Gas由两个部分组成: 限制(Gas limit)和价格(Gas Price)。Gas Limit 是用户愿意为执行某个操作或确认交易支付的最大Gas量。Gas Price 是 Gwei 的数量,用户愿意花费于每个 Gas 单位的价钱。
当进行每笔交易时,发送人设定Gas Limit 和Gas Price,将 Gas Limit*Gas Price ,就得到了ETH交易佣金的成本。
-
to:该交易被送往的地址(调用的合约地址或转账对方的账户地址)。
-
value:交易发送的以太币总量。
-
data
- 若该交易是以太币交易,则data为空;
- 若是部署合约,则data为合约的bytecode;
- 若是合约调用,则需要从合约ABI中获取函数签名,并取函数签名hash值前4字节与所有参数的编码方式值进行拼接而成
-
chainId:防止跨链重放攻击。 ->EIP155
2. 签署交易
签署交易可使用MetaMask和ethers库。
wallet.signTransaction中发生了什么?
- 对(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)进行RLP编码;
- 对上面的RLP编码值进行Keccak256 ;
- 对上面的Keccak256值进行ECDSA私钥签名(即正向算法);
- 对上面的ECDSA私钥签名(v、r、s)结果与交易消息再次进行RPL编码,即RLP(nonce, gasPrice, gasLimit, to, value, data, v, r, s).
为什么步骤1中包含chainId字段,而步骤4中再次编码时没有chainId字段?原始消息内容都不一样,怎么可能会验证通过?这是因为chainId 是被编码到签名的 v参数中的,因此我们不会将chainId本身包含在最终的签名交易数据中。当然,我们也不会提供任何发送方地址,因为地址可以通过签名恢复。这就是以太坊网络内部用来验证交易的方式。
3. 验签
验证过程:交易签名发送后,以太坊节点如何进行身份认证、不可否认、完整性
- 对上面最终的RPL解码,可得到(nonce, gasPrice, gasLimit, to, value, data, v, r, s);
- 对(nonce, gasPrice, gasLimit, to, value, data)和(v,r,s)ECDSA验证(即反向算法),得到签名者的address,细心的同学可以看到第一个括号少了chainId,这是因为chainId在ECDSA私钥签名(即正向算法) 时被编码到了v,所以由v可以直接解码出chainId(所以在对上面的RLP编码值进行Keccak256;这一步,肯定是把chainId复制了一下,给对上面的Keccak256值进行ECDSA私钥签名(即正向算法);这一步用);
- 对上面得到的签名者的address与签名者公钥推导的address进行比对,相等即完成身份认证、不可否认性、完整性。
我们可以去MyCrypto - Ethereum Wallet Manager,将wallet.signTransaction生成的编码复制进去,对上述验证步骤有一个直观的感受。
六、钓鱼签名案例
以太坊账户(Ethereum account)
以太坊账号模型
以太坊有两种账户类型:
- 外部拥有账户(EOA)——由拥有私钥的任何人控制
- 合约账户——部署到网络的智能合约,由代码控制。了
两种账户类型都能够:
- 接收、持有和发送 ETH 和代币
- 与部署的智能合约交互
两种账户类型主要差异
EOA:
- 创建帐户无需任何费用
- 可以发起交易
- EOA账户之间的交易只能是 ETH/代币转账
- 由一对加密密钥组成:控制帐户活动的公钥和私钥
合约账户
- 创建合约是有成本的,因为您使用的是网络存储
- 只能发送交易以响应接收交易
- 从EOA账户到合约账户的交易可以触发代码,该代码可以执行许多不同的操作,例如转移代币甚至创建新合约
- 合约账户没有私钥。相反,它们由智能合约代码的逻辑控制
钓鱼签名举例
慢雾:空白支票 eth_sign 钓鱼分析
参考URL: https://mp.weixin.qq.com/s/E-LSN5eYwWhCQOH46-XyNg
钓鱼签名举例:
钓鱼网址(注意 不要点击这个链接):https://sei-network.io/
区块链浏览器:https://etherscan.io/address/0xd13b093EAfA3878De27183388Fea7D0D2B0AbF9E
钓鱼合约代码
pragma solidity ^0.4.26;contract SecurityUpdates {address private owner; // current owner of the contractconstructor() public{ owner=msg.sender;}function getOwner() public view returns (address) { return owner;}function withdraw() public {require(owner == msg.sender);msg.sender.transfer(address(this).balance);}function SecurityUpdate() public payable {}function getBalance() public view returns (uint256) {return address(this).balance;}
}
- address(this)和msg.sender是两个唯一的地址,第一个是指合约实例的地址,第二个是指合约调用的地址。
- 你可以通过 transfer 函数向一个地址发送以太, 然后 this.balance 将返回当前合约存储了多少以太。
- view: 意味着它只能读取数据不能更改数据
- payable允许我们接受存款,转账的时候可以转ETH进合约。
如何对抗钓鱼网址的反调试技巧?
(function anonymous(
) {
debugger
})
这是钓鱼网站的反调试技巧,许多新人做钓鱼网站分析可能这步就卡住了。你点击继续执行脚本(Resume script execute)那个蓝色执行小按钮,没用,会继续中断。
总结
合约本身没有什么,很正常的一个合约,黑客的手段不在于合约本身,在于您的安全意识以及对区块链签名的认知。
不管界面如何显示,一定要检查meatmask显示的签名内容。
参考
网络安全把关不求人! MetaMask钱包签名前要留神!
参考URL: https://www.ud.hk/sc/thoughtleader/article/blockchain-security-metamask-wallet-3-signature-mechanisms
一文读懂以太坊签名:ECDSA、RLP、EIP155、EIP191、EIP712
参考URL: https://learnblockchain.cn/article/5012
以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程
参考URL: http://t.zoukankan.com/linguanh-p-9612592.html
以太坊交易签名解析源码解读
参考URL: https://cloud.tencent.com/developer/article/1665125
教程:Ethers前端签名,Solidity后端验签【原创智能合约solidity教程】22年最新最全持续新增及更新课程内容B站唯一官方
参考URL: https://www.bilibili.com/video/BV1dD4y1v79z
精通以太坊 (中文版)
参考URL: https://www.bookstack.cn/read/ethereum_book-zh/spilt.8.ee4988229e1934ea.md
这篇关于从Metamask区块链签名到钓鱼案例分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!