一、说明
在使用web3.js类库开发dapp时涉及到需要在后台程序中使用私钥对消息进行签名的需求,比如签名验签、充提币接口、批量归集usdt等场景下都需要使用私钥在程序后台进行签名。无法通过metamask或者其他web3客户端钱包进行签名,因为客户端钱包签名只适用于个人签名的方式,系统以交互式的方式请求用户个人签名时可以调用metamask钱包进行签名。
但是,后台程序签名要求必须是直接在程序中异步完成签名,并提交请求到链端。web3.js中常用的签名函数包括web3.eth.accounts.sign、web3.eth.sign等。
本dapp示例代码包含通过metamask钱包客户端签名的方式,私钥后台签名的方式,已经solidity链端完成签名验签的过程,最后执行代币的充提接口。
dapp前端页面展示效果如下:
二、web3.js中签名验签的原理
在签名时,先对原始消息进行Hash,然后使用私钥对Hash结果进行签名,生成签名结果。签名结果包括三个部分:r、s和v。
在验签时,需要对原始消息进行Hash,并使用公钥对签名结果进行验证。具体来说,会使用签名结果中的r、s和v以及原始消息的Hash值作为输入,使用椭圆曲线加密算法计算出公钥,然后将计算出的公钥与签名中的v进行比较,如果相同则表示验签成功。
需要注意的是,对于同一个原始消息和同一个私钥,每次进行签名都会生成不同的签名结果。这是因为Web3.js中的签名算法使用了随机数,以增强签名的安全性。
三、核心代码分析
1、solidity端签名验签代码如下:
function getEthSignedMessageHash(bytes32 _messageHash) private pure returns (bytes32) { return keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", _messageHash ) ); } function queryEthSignedMessageHash( uint256 amount, address to, uint256 _nonce ) external pure returns (bytes32) { bytes32 messageHash = getMessageHash(amount, to, _nonce); bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); return ethSignedMessageHash; }
2、dapp前端web3.js类库引用代码如下:
const Web3 = require('web3'); const web3 = new Web3('https://mainnet.infura.io/v3/<PROJECT_ID>'); const signedMessage = web3.eth.accounts.sign(message, privateKey); const signature = await web3.eth.sign(messageHash, account, privateKey); web3.eth.accounts.sign(message, privateKey, (err, result) => { if (err) { console.error('Failed to sign message:', err); } else { console.log('Signed message:', result.signature); } });
web3.eth.accounts.sign
函数对消息进行签名。该函数需要传入三个参数:
- 待签名的消息;
- 待签名账户的私钥;
- 回调函数,用于处理签名结果或错误。
函数返回一个对象,包含签名结果(signature
)、消息哈希(messageHash
)和签名账户地址(from
)等属性。你可以根据需要使用这些属性。
以下为使用 web3.eth.sign进行签名的代码实现:
web3.eth.sign(message, privateKey, function(err, result) { if (err) return console.error(err); console.log('Signed message: ' + result); });
根据实际情况,选择合适的签名方法。
3、dapp前端页面布局代码如下:
<form> <label for="address-input">提币地址:</label> <input type="text" id="address-input"> <label for="amount-input">提币数量:</label> <input type="number" id="amount-input"> <label for="nonce-input">提币nonce:</label> <input type="number" id="nonce-input"> <p class="form-note">提币数量需要包含精度,提币nonce值需要唯一,nonce步长值为2</p> </form> <div class="button-group"> <button class="connect-wallet-btn" onclick="connWallet()">连接钱包</button> <button class="signmgs-btn" onclick="signMessage()">签名消息(钱包)</button> <button class="signmgs-btn" onclick="signMessagePriKey()">签名消息(私钥)</button> <button class="verifysig-btn" onclick="verifyMessage()">验证签名</button> <button class="execute-contract-btn" onclick="withdraw()">执行提币</button> </div>
前端根据用户form表达是输入,对多个变量值进行hash签名产生正确的签名消息后,提交到链端,由链端完成签名验签,最终完成代币的自动化提币,dapp中会员可以自动实现链上充提币操作。
至此,完成web3.js中私钥方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提所有操作流程。
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载:
币安智能链BSC发币(合约部署、开源、锁仓、LP、参数配置、开发、故障处理、工具使用)教程下载:
多模式(燃烧、回流指定营销地址、分红本币及任意币种,邀请推广八代收益,LP加池分红、交易分红、复利分红、NFT分红、自动筑池、动态手续费、定时开盘、回购)组合合约源代码下载:
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载地址:
添加VX或者telegram获取全程线上免费指导
评论前必须登录!
注册