椭圆曲线数字签名算法原理及其应用

现实中的签名有很多,简单举个例子:比如你小时候,考试不及格,老师常常会让你带着试卷在回去给你爸妈签名,以表示对你成绩的认可。那么这种签名可能会导致你乱认爸爸,老师也不容易验证你家长的签名。
椭圆曲线数字签名是可以验证的。
公式,函数图像如下图。
4a**3 + 27b**2 != 0,保证了图像上的所有点有唯一切线。
图片来自网络
椭圆曲线点的基本运算。
加法运算:A+B = C,那么C点是在AB连线的与椭圆曲线交于第三个点关于x轴对称的点。
假设A,B重合,即该直线与椭圆曲线相切与A点,那么C = 2A, 那么C点是在A切线与椭圆曲线交于第2个点关于x轴对称的点。
加法解决了,乘法解决了。
好的,开始进入正题:
取一个基点G(公开)。
设私钥是一整大正整数S(不公开)
令点P=SG,P是公钥(公开)。

签名过程

  1. 去一个随机数k
  2. 用该随机数产生一个点R_,坐标(x1,y1) = kG
  3. 令r=x1
  4. 对需要发送的信息取hash,m = hash(M)
  5. 令 s = (m+rS)/k
  6. 取恢复标识v
  7. 则签名是:{r , s , v}

验证签名过程

根据签名信息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);
 }

猜你喜欢

转载自blog.csdn.net/wjl__ai__/article/details/122271497