以太坊使用的数据结构与算法-ECDSA 数字签名算法

本文详细介绍了数字签名算法(DSA)的工作原理,重点讲解了DSA和基于椭圆曲线的ECDSA,包括密钥生成、签名生成和验证过程。此外,文章还讨论了ECDSA在比特币和以太坊中的应用,以及Secp256k1和Ed25519等常见曲线。
摘要由CSDN通过智能技术生成

什么是数字签名算法(DSA)

全称Digital Signature Algorithm,即数字签名算法,它主要用于数字签名的生成和验证。

只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。

一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。

数字签名主要是为了完成两个目的:

(1)确认信息是由签名者发送的;

(2)确认信息自签名后到收到为止,未被修改过。

DSA算法的工作原理

主要基于离散对数问题,它包含三个阶段:密钥生成、签名生成和签名验证。

在密钥生成阶段,DSA会生成一对公钥和私钥。公钥用于验证签名,而私钥则用于生成签名。

在签名生成阶段,DSA会使用私钥和一些随机数来生成一个数字签名。这个签名是独一无二的,并且与消息内容紧密相关。

在签名验证阶段,DSA会使用公钥和原始消息来验证签名的有效性。如果签名是有效的,那么就可以确认这条消息是由私钥的持有者发送的,并且在传输过程中没有被篡改。

 DSA分类

  • RSA
  • DSA 
  • ECDSA 
  • Schnorr

什么是椭圆曲线数字签名算法(ECDSA)

椭圆曲线数字签名算法(英语:Elliptic Curve Digital Signature Algorithm,缩写作 ECDSA)是一种基于椭圆曲线密码学公开金钥加密算法。1985年,Koblitz和Miller把数字签名算法移植到椭圆曲线上,椭圆曲线数字签名算法由此诞生

具体说明可以参考

椭圆曲线数字签名算法(ECDSA)

ECDSA处理过程:


1.参与数字签名的所有通信方都使用相同的全局参数,用于定义椭圆曲线以及曲线上的基点
2.签名者首先生成一对公私钥。对于私钥,选择一个随机数或者伪随机数作为私钥,利用随机数和基点算出另一点,作为公钥
3.对消息计算Hash值,用私钥、全局参数和Hash值生成签名
4.验证者用签名者的公钥、全局参数等验证。

                        
原文链接:https://blog.csdn.net/weixin_43586667/article/details/122766815
———————————————

ECDSA作用:

比特币和以太坊使用ECDSA来生成账户的公私钥以及对交易和区块进行验证。

1.在已知公钥的情况下,无法推导出该公钥对应的私钥。
2.可以通过某些方法来证明某人拥有一个公钥所对应的私钥,而此过程不会暴露关于私钥的任何信息。

Secp256k1:

Secp256k1是指比特币、以太坊中使用的ECDSA(椭圆曲线数字签名算法)曲线的参数,并且在高效密码学标准(Certicom Research,http://www.secg.org/sec2-v2.pdf)中进行了定义。

Secp256k1基于Fp有限域上的椭圆曲线,由于其特殊构造的特殊性,其优化后的实现比其他曲线性能上可以特高30%。这种算法具有许多优点,例如占用很少的带宽和存储资源,密钥的长度很短,让所有的用户都可以使用同样的操作完成域运算。

各加密货币采用的签名算法的现状

ECDSA分类:

  • spec256k1(特定的椭圆曲线称为secp256k1,即曲线 y² = x³ + 7 在有限域 (⼜名伽罗瓦域)
  • spec256r1(secp256k1和secp256r1都是ECDSA(椭圆曲线数字签名算法)曲线的参数,区别是他们所使用的随机质数不同,目前行业内对于r1算法的安全性存疑。)
  • ed25519(ed25519是基于扭曲爱德华曲线Edwards25519和SHA-512的EdDSA签名机制。)

ECDSA使用:

在EVM中预编译一个方法

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

从椭圆曲线签名中恢复与公钥关联的地址或在错误时返回零。函数参数对应于签名的 ECDSA 值:

  • r= 签名的前 32 个字节

  • s= 签名的第二个 32 字节

  • v= 签名的最后 1 个字节

为什么需要ecrecover函数?

 1.实现广义元交易

2.避免使用进行两步交易:授权+ transferFrom!

作用实质为验证一个签名数据,而这些数据不一定来自交易签署者

如何使用ecrecover函数

       有些业务场景只需要用户签名交易数据,让商户付费来执行交易并付手续费,就得确保用户清楚地知道他们在签署什么,所以提供用户签名服务时就得符合 EIP-712的规范

// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

contract VerifySignature {
    function getMessageHash(
        address _to,
        uint _amount,
        string memory _message,
        uint _nonce
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_to, _amount, _message, _nonce));
    }

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

    function verify(
        address _signer,
        address _to,
        uint _amount,
        string memory _message,
        uint _nonce,
        bytes memory signature
    ) public pure returns (bool) {
        bytes32 messageHash = getMessageHash(_to, _amount, _message, _nonce);
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);

        return recoverSigner(ethSignedMessageHash, signature) == _signer;
    }

    function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature)
        public
        pure
        returns (address)
    {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);

        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

    function splitSignature(bytes memory sig)
        public
        pure
        returns (
            bytes32 r,
            bytes32 s,
            uint8 v
        )
    {
        require(sig.length == 65, "invalid signature length");

        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
    }
}

使用Hardhat进行测式

const { expect } = require("chai")
const { ethers } = require("hardhat")

describe("VerifySignature", function () {
  it("Check signature", async function () {
    const accounts = await ethers.getSigners(2)

    const VerifySignature = await ethers.getContractFactory("VerifySignature")
    const contract = await VerifySignature.deploy()
    await contract.deployed()

    // const PRIV_KEY = "0x..."
    // const signer = new ethers.Wallet(PRIV_KEY)
    const signer = accounts[0]
    const to = accounts[1].address
    const amount = 999
    const message = "Hello"
    const nonce = 123

    const hash = await contract.getMessageHash(to, amount, message, nonce)
    const sig = await signer.signMessage(ethers.utils.arrayify(hash))
    

    const ethHash = await contract.getEthSignedMessageHash(hash)

    console.log("signer          ", signer.address)
    console.log("recovered signer", await contract.recoverSigner(ethHash, sig))

    // Correct signature and message returns true
    expect(
      await contract.verify(signer.address, to, amount, message, nonce, sig)
    ).to.equal(true)

    // Incorrect message returns false
    expect(
      await contract.verify(signer.address, to, amount + 1, message, nonce, sig)
    ).to.equal(false)
  })
})

运行结果

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值