以太坊中的数字签名ECDSA
,以及如何利用它发放NFT
白名单
代码中的ECDSA
库由OpenZeppelin
的同名库简化而成。
数字签名
如果你用过opensea
交易NFT
,对签名就不会陌生。下图是小狐狸(metamask
)钱包进行签名时弹出的窗口,它可以证明你拥有私钥的同时不需要对外公布私钥。
以太坊使用的数字签名算法叫双椭圆曲线数字签名算法(ECDSA
),基于双椭圆曲线“私钥-公钥”对的数字签名算法。它主要起到了三个作用:
- 身份认证:证明签名方是私钥的持有人。
- 不可否认:发送方不能否认发送过这个消息。
- 完整性:消息在传输过程中无法被修改。
ECDSA
合约
ECDSA
标准中包含两个部分:
- 签名者利用
私钥
(隐私的)对消息
(公开的)创建签名
(公开的)。 - 其他人使用
消息
(公开的)和签名
(公开的)恢复签名者的公钥
(公开的)并验证签名。 我们将配合ECDSA
库讲解这两个部分。本教程所用的私钥
,公钥
,消息
,以太坊签名消息
,签名
如下所示:
私钥: 0x227dbb8586117d55284e26620bc76534dfbd2394be34cf4a09cb775d593b6f2b
公钥: 0xe16C1623c1AA7D919cd2241d8b36d9E79C1Be2A2
消息: 0x1bf2c0ce4546651a1a2feb457b39d891a6b83931cc2454434f39961345ac378c
以太坊签名消息: 0xb42ca4636f721c7a331923e764587e98ec577cea1a185f60dfcc14dbb9bd900b
签名: 0x390d704d7ab732ce034203599ee93dd5d3cb0d4d1d7c600ac11726659489773d559b12d220f99f41d17651b0c1c6a669d346a397f8541760d6b32a5725378b241c
创建签名
1. 打包消息:
在以太坊的ECDSA
标准中,被签名的消息
是一组数据的keccak256
哈希,为bytes32
类型。我们可以把任何想要签名的内容利用abi.encodePacked()
函数打包,然后用keccak256()
计算哈希,作为消息
。我们例子中的消息
是由一个address
类型变量和一个uint256
类型变量得到的:
/** 将mint地址(address类型)和tokenId(uint256类型)拼成消息msgHash* _account: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4* _tokenId: 0* 对应的消息msgHash: 0x1bf2c0ce4546651a1a2feb457b39d891a6b83931cc2454434f39961345ac378c*/function getMessageHash(address _account, uint256 _tokenId) public pure returns(bytes32){return keccak256(abi.encodePacked(_account, _tokenId));}
2. 计算以太坊签名消息:
所谓计算以太坊签名消息,本质上是第二次打包消息,只是这次打包是在上一次打包消息的基础上,加上一个字符串作为编码的一部分:"\x19Ethereum Signe