实用工具 - OpenZeppelin 文档

本文介绍了OpenZeppelin Contracts社区版中用于密码学的多个实用工具,包括验证类型化数据签名(EIP712)、嵌套EIP712签名验证(ERC-7739)以及ERC-7913签名验证器,这些工具旨在简化智能合约中复杂签名的处理并提高账户安全性。

实用工具

OpenZeppelin Contracts 社区版本中包含的多个库和通用实用工具。这些只是一组实用工具合约。有关完整列表,请查看 API 参考

密码学

验证类型化数据签名

有关如何在链上验证签名的预备知识,请查看 OpenZeppelin Contracts 文档

与验证纯文本消息相反,可以让用户签署结构化数据(即类型化值),并在他们的钱包上仍然可读。这可以通过实现 EIP712 来实现,这是一种将结构化数据编码为类型化数据哈希的标准方法。

要开始验证已签名的类型化结构,只需验证 类型化数据哈希

// contracts/MyContractDomain.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

/// @dev 不安全的合约,用于演示 EIP712 和 ECDSA 的用法。
abstract contract MyContractDomain is EIP712 {
    function validateSignature(
        address mailTo,
        string memory mailContents,
        bytes memory signature
    ) internal view returns (address) {
        bytes32 digest = _hashTypedDataV4(
            keccak256(abi.encode(keccak256("Mail(address to,string contents)"), mailTo, keccak256(bytes(mailContents))))
        );
        return ECDSA.recover(digest, signature);
    }
}

作为消息的一部分,EIP-712 要求实施者包含一个域名分隔符,这是一个包含当前智能合约地址及其部署链 ID 的哈希。这样,智能合约可以确保结构化消息是为其特定域签名的,从而避免了智能合约中签名的可重放性。

验证嵌套的 EIP-712 签名

帐户(即智能合约钱包或智能帐户)特别可能由多个签名者控制。因此,重要的是要确保签名:

  1. 仅对预期的域和帐户有效。

  2. 以最终签名者可读的方式进行验证。

一方面,确保帐户签名仅对特定的智能合约(即应用程序)有效是困难的,因为它需要验证其域是应用程序而且是帐户本身的签名。因此,社区开发了 ERC-7739;一种防御性重新哈希机制,它使用嵌套的 EIP-712 方法(即包装另一个 EIP-712 类型结构的 EIP-712)将签名绑定到单个域。

如果你的智能合约验证签名,则使用 ERC7739Signer 将实现 IERC1271 接口,用于验证智能合约签名,遵循 ERC-7739 建议的方法:

// contracts/ERC7739ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

import {ERC7739} from "@openzeppelin/community-contracts/utils/cryptography/signers/ERC7739.sol";

contract ERC7739ECDSA is ERC7739 {
    address private immutable _signer;

    constructor(address signerAddr) EIP712("ERC7739ECDSA", "1") {
        _signer = signerAddr;
    }

    function _rawSignatureValidation(
        bytes32 hash,
        bytes calldata signature
    ) internal view virtual override returns (bool) {
        (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature);
        return _signer == recovered && err == ECDSA.RecoverError.NoError;
    }
}

ERC-7913 签名验证器

ERC-7913 扩展了签名验证的概念,以支持没有自己的以太坊地址的密钥。这对于将非以太坊加密曲线、硬件设备或其他身份系统集成到智能帐户中特别有用。

该标准定义了一个可以实现的验证器接口,以支持不同类型的密钥。签名者表示为一个 bytes 对象,该对象连接一个验证器地址和一个密钥:verifier || key

ERC7913Utils 提供了使用与 ERC-7913 兼容的验证器来验证签名的函数:

using ERC7913Utils for bytes;

function _verify(bytes memory signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
    return signer.isValidSignatureNow(hash, signature);
}

验证过程如下:

  • 如果 signer.length < 20:验证失败

  • 如果 signer.length == 20:使用 SignatureChecker 完成验证

  • 否则:使用 ERC-7913 验证器完成验证。

这允许与 EOA 和 ERC-1271 合约向后兼容,同时支持新类型的密钥。

← 跨链

访问 →

  • 原文链接: docs.openzeppelin.com/co...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。