Solidity应用:验证签名

solidity验证签名分为四步:

  • 打包消息
  • 以太坊签名消息
  • 钱包把消息和私钥进行签名
  • 恢复公钥

打包消息

在以太坊的ECDSA标准中,被签名的消息是一组数据的keccak256哈希,为bytes32类型。我们可以把任何想要签名的内容利用abi.encodePacked()函数打包,然后用keccak256()计算哈希,作为消息。例子中的消息是一个字符串。

function getMessageHash(string calldata _message) public pure returns(bytes32) {
	return keccak256(abi.encodePacked(_message));
}

在这里插入图片描述

以太坊签名消息

以太坊签名消息与打包消息代码类似,只增加了固定字符串 \x19Ethereum Signed Message:\n32,该字符串是在EIP191提出的。EIP191提倡在消息前加上"\x19Ethereum Signed Message:\n32"字符,并再做一次keccak256哈希,作为以太坊签名消息。

function getEthSignMessageHash(bytes32 _msgHash) public pure returns(bytes32) {
	return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",_msgHash));
}

在这里插入图片描述

钱包把消息和私钥进行签名

在浏览器控制台输入以下代码,浏览器必须安装小狐狸钱包:

ethereum.enable()
account="0xd4be041fb762980d242bba468eb51f836d18cd4b"(替换成自己的钱包地址)
hash="0x7ef7eb5e71f100c5c272816c12ebabe1d7ee29d4a7d4d23f79b4a1b6087de92b"(消息打包的hash)
ethereum.request({method:"personal_sign", params:[account, hash]})

在这里插入图片描述

恢复公钥

使用以太坊签名和钱包签名恢复公钥,solidity内置函数ecrecover

function recover(bytes32 _ethSignMessageHash, bytes memory _signature) public pure returns(address) {
	(bytes32 r, bytes32 s, uint8 v) = _split(_signature);
	return ecrecover(_ethSignMessageHash, v, r, s);
}

// 分割签名,签名由r s v三部分拼接而成
function _split(bytes memory _signature) internal pure returns(bytes32 r, bytes32 s, uint8 v) {
	require(_signature.length == 65, "invalid signature length");
	assembly {
		r := mload(add(_signature, 32))
        s := mload(add(_signature, 64))
        v := byte(0,mload(add(_signature, 96)))
    }
}

在这里插入图片描述
然后我们对比恢复出来的地址和小狐狸钱包签名的地址是否一致,即可验证签名是否有效。

对比公钥并验证签名

function verify(bytes32 _ethSignMessageHash, bytes memory _signature, address _signer) internal pure returns (bool) {
	return recoverSigner(_ethSignMessageHash, _signature) == _signer;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值