当前位置:   article > 正文

从Metamask区块链签名到钓鱼案例分析_metamsk

metamsk

从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”

整体应用过程:

  1. 生成椭圆曲线的公钥和私钥
// 生成密钥
 privateKey, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
// 保存密钥
// x509编码
 x509PrivateKey, _ := x509.MarshalECPrivateKey(privateKey)

 保存公钥//
// x509编码
 x509PublicKey, _ := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 根据 待签名数据和私钥,生成两个big.Int r和s, r和s就是签名结果
func Sign(rand io.Reader, priv *PrivateKey, hash []byte)
  • 1
  1. 根据公钥,明文,r,s验证签名
func Verify(pub *PublicKey, hash []byte, r, s *big.Int)
  • 1

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 节点

  1. 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字节长的交易哈希值。

  1. 对应到以太坊的 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
     };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 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中发生了什么?

  1. 对(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)进行RLP编码;
  2. 对上面的RLP编码值进行Keccak256 ;
  3. 对上面的Keccak256值进行ECDSA私钥签名(即正向算法);
  4. 对上面的ECDSA私钥签名(v、r、s)结果与交易消息再次进行RPL编码,即RLP(nonce, gasPrice, gasLimit, to, value, data, v, r, s).

为什么步骤1中包含chainId字段,而步骤4中再次编码时没有chainId字段?原始消息内容都不一样,怎么可能会验证通过?这是因为chainId 是被编码到签名的 v参数中的,因此我们不会将chainId本身包含在最终的签名交易数据中。当然,我们也不会提供任何发送方地址,因为地址可以通过签名恢复。这就是以太坊网络内部用来验证交易的方式。

3. 验签

验证过程:交易签名发送后,以太坊节点如何进行身份认证、不可否认、完整性

  1. 对上面最终的RPL解码,可得到(nonce, gasPrice, gasLimit, to, value, data, v, r, s);
  2. 对(nonce, gasPrice, gasLimit, to, value, data)和(v,r,s)ECDSA验证(即反向算法),得到签名者的address,细心的同学可以看到第一个括号少了chainId,这是因为chainId在ECDSA私钥签名(即正向算法) 时被编码到了v,所以由v可以直接解码出chainId(所以在对上面的RLP编码值进行Keccak256;这一步,肯定是把chainId复制了一下,给对上面的Keccak256值进行ECDSA私钥签名(即正向算法);这一步用);
  3. 对上面得到的签名者的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 contract

     constructor() 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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • address(this)和msg.sender是两个唯一的地址,第一个是指合约实例的地址,第二个是指合约调用的地址。
  • 你可以通过 transfer 函数向一个地址发送以太, 然后 this.balance 将返回当前合约存储了多少以太。
  • view: 意味着它只能读取数据不能更改数据
  • payable允许我们接受存款,转账的时候可以转ETH进合约。

如何对抗钓鱼网址的反调试技巧?

在这里插入图片描述

(function anonymous(
) {
debugger
})
  • 1
  • 2
  • 3
  • 4

这是钓鱼网站的反调试技巧,许多新人做钓鱼网站分析可能这步就卡住了。你点击继续执行脚本(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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/453544
推荐阅读
  

闽ICP备14008679号