现实中的签名有很多,简单举个例子:比如你小时候,考试不及格,老师常常会让你带着试卷在回去给你爸妈签名,以表示对你成绩的认可。那么这种签名可能会导致你乱认爸爸,老师也不容易验证你家长的签名。椭圆曲线数字签名是可以验证的。公式,函数图像如下图。4a3+27b2!=0,保证了图像上的
现实中的签名有很多,简单举个例子:比如你小时候,考试不及格,老师常常会让你带着试卷在回去给你爸妈签名,以表示对你成绩的认可。那么这种签名可能会导致你乱认爸爸,老师也不容易验证你家长的签名。 椭圆曲线数字签名是可以验证的。 公式,函数图像如下图。 4*a*3 + 27b**2 != 0,保证了图像上的所有点有唯一切线。
椭圆曲线点的基本运算。 加法运算:A+B = C,那么C点是在AB连线的与椭圆曲线交于第三个点关于x轴对称的点。 假设A,B重合,即该直线与椭圆曲线相切与A点,那么C = 2A, 那么C点是在A切线与椭圆曲线交于第2个点关于x轴对称的点。 加法解决了,乘法解决了。 好的,开始进入正题: 取一个基点G(公开)。 设私钥是一整大正整数S(不公开) 令点P=SG,P是公钥(公开)。
根据签名信息r,求出点R,此时R有两个值(因为函数关于x轴对称),取哪个,取决于恢复标识v。恢复过后的 R 等于 签名过程中的 R。(R = R = kG) 恢复公式(已知:{m,{r , s , v}}):(-m/r) * G + (s/r)R 恢复公式的值均为已知值。 那么
如果算出的结果P_ = P 则:该签名为真,否则为假。 由于计算机的存储问题,应用该算法时,需要对其进行映射在一个有限域中,即进行模运算。
假设一个场景,有公司做推广,免费给会员用户送礼品,公司可以快递送给每个用户,但是公司不想承担这部分的快递费,那么建立自取站,会员用户可以根据会员的ID来进行自取,那个也不是每个人都可以取,只有公司签过名的会员才能领取礼品。 那么此时的会员ID就是面的m。
以下就是类似的代码实现。
function claim(uint256 amountV, bytes32 r, bytes32 s) external {
uint256 amount = uint248(amountV);
uint8 v = uint8(amountV >> 248);
uint256 total = _totalSupply + amount;
require(total <= MAX_SUPPLY, "Exceed max supply");
require(minted(msg.sender) == 0, "Claimed");
bytes32 digest = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",
ECDSA.toTypedDataHash(_domainSeparatorV4(),
keccak256(abi.encode(MINT_CALL_HASH_TYPE, msg.sender, amount))
)));
require(ecrecover(digest, v, r, s) == cSigner, "Invalid signer");
_totalSupply = total;
_mint(msg.sender, amount);
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!