Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-2477: Token Metadata Integrity

定义了一种机制,客户端可以通过该机制验证获取的 token 元数据文档是否在未经预期修改的情况下被交付。

Authors Kristijan Sedlak (@xpepermint), William Entriken <github.com@phor.net>, Witek Radomski <witek@enjin.io>
Created 2020-01-02
Discussion Link https://github.com/ethereum/EIPs/issues/2483
Requires EIP-165, EIP-721, EIP-1155

简述

本规范定义了一种机制,客户端可以通过该机制验证获取的 token 元数据文档是否在未经预期修改的情况下被交付。

这是 W3C 子资源完整性 (SRI) 规范的 Web3 对应物。

摘要

为智能合约指定了一个具有两个函数 tokenURIIntegritytokenURISchemaIntegrity 的接口 ERC2477,并提供了一个叙述来解释这如何提高 token 元数据文档的完整性。

动机

Token 被广泛应用于许多应用中,以表示、追踪并提供对链下资产的访问。这些资产包括移动应用中的游戏内数字物品、奢侈手表以及我们全球供应链中的产品等等。

一些 token 标准允许使用 URI (RFC 3986) 将元数据附加到特定的 token,并且这些标准得到了上述应用的支持。这些元数据标准包括:

  • ERC-721 元数据扩展 (ERC721Metadata)
  • ERC-1155 元数据扩展 (ERC1155Metadata_URI)
  • ERC-1046 (草案) ERC-20 元数据扩展

尽管所有这些标准都允许将元数据完全存储在链上(使用 “data” URI, RFC 2397),或者使用内容寻址系统(例如,IPFS 的内容标识符 [原文如此]),但我们发现几乎每个实现都使用统一资源定位符(例外是 The Sandbox,它使用 IPFS URI)。这些 URL 不提供内容正确性或不变性的保证。本标准增加了这样的保证。

设计

方法 A: Token 合约可以通过使用其 URL 来引用元数据。这不提供任何完整性保护,因为如果托管内容是可变的,则引用的元数据和/或模式可能会随时更改。这是 EIP-2477 之前的世界:

┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│─────▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘

注意:根据 JSON Schema 项目,使用 $schema 键中的 URI 引用模式的元数据文档是一种已知的方法,但它尚未标准化。

方法 B: EIP-2477 提供了建立这些引用完整性的机制。在一种方法中,元数据文档具有完整性。在这里,链上数据包括元数据文档的哈希值。元数据可以引用也可以不引用模式。在这种方法中,更改元数据文档将需要更新链上 tokenURIIntegrity

┌───────────────────────┐       ┌────────┐      ┌ ─ ─ ─ ─ 
│        TokenID        │──────▶│Metadata│─ ─ ─▶  Schema │
└───────────────────────┘       └────────┘      └ ─ ─ ─ ─ 
┌───────────────────────┐            ▲                    
│   tokenURIIntegrity   │════════════╝                    
└───────────────────────┘                                 

方法 C: 在一种更强的方法中,模式通过 JSON Schema 的扩展被元数据引用,从而提供完整性。在这种方法中,更改元数据文档或模式将需要更新链上 tokenURIIntegrity 和元数据文档,此外,更改模式还需要更新链上 tokenURISchemaIntegrity

┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│═════▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲                    
│   tokenURIIntegrity   │════════════╝                    
└───────────────────────┘                                 

方法 D: 同样强大的是,元数据可以对模式进行正常引用(没有完整性保护),并且链上数据还包括模式文档的哈希值。在这种方法中,更改元数据文档将需要更新链上 tokenURIIntegrity,而更新模式文档将需要更新 tokenURISchemaIntegrity

┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│─────▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲               ▲    
│   tokenURIIntegrity   │════════════╝               ║    
└───────────────────────┘                            ║    
┌───────────────────────┐                            ║    
│tokenURISchemaIntegrity│════════════════════════════╝    
└───────────────────────┘

方法 E: 最后,可以从元数据和使用链上数据引用具有完整性的模式。在这种方法中,更改元数据文档或模式将需要更新链上 tokenURIIntegrity 和元数据文档,此外,更改模式还需要更新链上 tokenURISchemaIntegrity

┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│═════▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲               ▲    
│   tokenURIIntegrity   │════════════╝               ║    
└───────────────────────┘                            ║    
┌───────────────────────┐                            ║    
│tokenURISchemaIntegrity│════════════════════════════╝    
└───────────────────────┘                                 

规范

本文档中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 和 “OPTIONAL” 按照 RFC 2119 中的描述进行解释。

智能合约

实现 ERC-2477 标准的智能合约必须实现 ERC2477 接口。

// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.7;

/// @title ERC-2477 Token Metadata Integrity
/// @dev See https://eips.ethereum.org/EIPS/eip-2477
/// @dev The ERC-165 identifier for this interface is 0x832a7e0e
interface ERC2477 /* is ERC165 */ {
    /// @notice Get the cryptographic hash of the specified tokenID's metadata
    /// @dev 获取指定 tokenID 的元数据的加密哈希值
    /// @param  tokenId       Identifier for a specific token
    /// @dev token 的标识符
    /// @return digest        Bytes returned from the hash algorithm, or "" if not available
    /// @dev 哈希算法返回的字节,如果不可用则返回 ""
    /// @return hashAlgorithm The name of the cryptographic hash algorithm, or "" if not available
    /// @dev 加密哈希算法的名称,如果不可用则返回 ""
    function tokenURIIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm);

    /// @notice Get the cryptographic hash for the specified tokenID's metadata schema
    /// @dev 获取指定 tokenID 的元数据模式的加密哈希值
    /// @param  tokenId       Identifier for a specific token
    /// @dev token 的标识符
    /// @return digest        Bytes returned from the hash algorithm, or "" if not available
    /// @dev 哈希算法返回的字节,如果不可用则返回 ""
    /// @return hashAlgorithm The name of the cryptographic hash algorithm, or "" if not available
    /// @dev 加密哈希算法的名称,如果不可用则返回 ""
    function tokenURISchemaIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm);
}

返回的加密哈希分别对应于 token 的元数据文档和该元数据文档的模式。

例如,使用 ERC-721,tokenURIIntegrity(21) 将对应于 tokenURI(21)。使用 ERC-1155,tokenURIIntegrity(16) 将对应于 uri(16)。在这两种情况下,tokenURISchemaIntegrity(32) 将对应于 tokenURIIntegrity(32) 匹配的文档的模式。

实现 ERC-2477 标准的智能合约必须实现 ERC-165 标准,包括上面的接口标识符。

实现 ERC-2477 标准的智能合约可以使用任何哈希或内容完整性方案。

实现 ERC-2477 标准的智能合约可以使用或省略一种在完整性更新时通知的机制(例如,以太坊日志操作)。

实现 ERC-2477 标准的智能合约可以使用任何机制来为元数据文档提供模式,并且应该为此目的在元数据文档上使用 JSON-LD(即 "@schema":...)。

元数据

元数据文档可以符合此模式,以提供对其模式文档的引用完整性。

{
  "title": "EIP-2477 JSON Object With Refererential Integrity to Schema",
  "type": "object",
  "properties": {
    "$schema": {
      "type": "string",
      "format": "uri"
    },
    "$schemaIntegrity": {
      "type": "object",
      "properties": {
        "digest": {
          "type": "string"
        },
        "hashAlgorithm": {
          "type": "string"
        }
      },
      "required": ["digest", "hashAlgorithm"]
    }
  },
  "required": ["$schema", "$schemaIntegrity"]
}

客户端

实现 ERC-2477 标准的客户端必须至少支持 sha256 哈希算法,并且可以支持其他算法。

注意事项

  • 由于 EIP 元数据的技术限制,此 EIP 元数据将 ERC-721 和 ERC-1155 列为实现的 “required”。实际上,此标准可用于任何具有 tokenURI(uint id) 或类似函数的 token 实现。

理由

函数和参数命名

W3C 子资源完整性 (SRI) 规范使用属性 “integrity” 来执行完整性验证。此 ERC-2477 标准提供了一种类似的机制,并重用了完整性名称,以便让以前见过 SRI 的人熟悉。

函数返回元组

SRI 完整性属性编码了元组 \((cryptographic\ hash\ function, digest, options)\) 的元素。此 ERC-2477 标准返回摘要和哈希函数名称,并省略了向前兼容性选项。

目前,SRI 规范没有使用选项。因此,我们无法知道在实现时它们可能采用什么格式。这是排除此参数的动机。

摘要返回值排在第一位,这是一种优化,因为我们期望链上实现如果仅使用其中一个,则更有可能使用此返回值。

函数返回类型

摘要是一个字节数组,支持各种哈希长度。这与 SRI 一致。SRI 使用 base64 编码来定位 HTML 文档,而我们使用字节数组,因为以太坊已经允许这种编码。

哈希函数名称是一个字符串。目前,没有哈希函数名称的通用分类法。SRI 识别名称 sha256sha384sha512 (不区分大小写匹配)。我们知道有两个机构提供哈希函数的分类法和规范名称:ETSI 对象标识符和 NIST 计算机安全对象注册。但是,SRI 的方法更容易遵循,我们在此处采用了这种方法。

函数返回类型 — 哈希长度

客户端必须支持 SHA-256 算法,并且可以选择支持其他算法。这是对 SRI 规范的偏离,SRI 规范要求 SHA-256、SHA-384 和 SHA-512。这种安全性较低的要求的原因是,我们期望某些客户端在链上。目前,SHA-256 在以太坊上执行起来简单且成本低廉,而 SHA-384 和 SHA-512 则更加昂贵且麻烦。

当前使用中最流行的低于 256 位的哈希函数大小是 SHA-1,为 160 位。已发布多个冲突(“Shattered” PDF 文件、320 字节文件、选择的前缀),并给出了生成无限多冲突的配方。SHA-1 已被破坏。美国国家标准与技术研究所 (NIST) 于 2015 年 11 月首次弃用了 SHA-1 用于某些用例,后来又进一步扩大了此弃用范围。

当前使用中最流行的高于 256 位的哈希函数大小是 SHA-384,由 NIST 指定。

美国国家安全局要求 SHA-2 算法套件(CNSA 套件概况介绍)的哈希长度为 384 位或更多,以用于 TOP SECRET 网络。(目前没有未分类的文档可以指定更高级别分类网络上的用例。)

我们怀疑 SHA-256 和 0xcert 资产认证将在可预见的未来成为保护 token 元数据的流行选择。

带内信令

使用现有 token 标准实现强大的内容完整性的一种可能方法是在所有 URL 的末尾包含一个 ?integrity=XXXXX。我们所知的任何现有实现都没有使用这种方法。我们没有选择这种方法的原因有很多。最主要的原因是万维网也存在同样的问题,他们选择使用子资源完整性方法,该方法是一个独立的数据字段,而不是 URL。

其他补充原因是:

  • 对于数据的链上消费者来说,解析直接哈希字段比执行字符串操作更容易。

  • 也许有一些 URI 不适合以这种方式进行修改,因此限制了该方法的通用性。

此设计理由也适用于 tokenURISchemaIntegrity。当前的 JSON-LD 规范允许 JSON 文档链接到模式文档。但是它不提供完整性。我们没有改变 JSON-LD 的工作方式,也没有改变 JSON Schema,而是使用 tokenURISchemaIntegrity 属性来提供完整性。

向后兼容性

ERC-721 和 ERC-1155 都提供了兼容的 token 元数据规范,这些规范使用 URI 和 JSON Schema。ERC-2477 标准与两者兼容,并且所有规范都是附加的。因此,不存在向后兼容性回归。

ERC-1523 标准,用于将保险单作为 ERC-721 非同质化 Token(草案),提出了 ERC-721 的扩展,该扩展也收紧了对元数据的要求。因为它完全是 ERC-721 的扩展,所以 ERC-2477 自动支持 ERC-1523(因为此标准已经支持 ERC-721)。

ERC-1046 (DRAFT) ERC-20 元数据扩展提出了 ERC-20 的比较扩展。这种概念超出了此 ERC-2477 标准的范围。如果 ERC-1046(草案)最终确定,我们将欢迎一个新的 ERC,该 ERC 复制 ERC-2477 并删除 tokenId 参数。

类似地,ERC-918 (DRAFT) 可挖矿 Token 标准提出了 ERC-20 的扩展,并且还包括元数据。与 ERC-1046 相同的评论也适用于此处。

测试用例

以下是一个 token 元数据文档,它同时与 ERC-721、ERC-1155 和 ERC-2477 标准兼容。

{
  "$schema": "https://URL_TO_SCHEMA_DOCUMENT",
  "name": "Asset Name",
  "description": "Lorem ipsum...",
  "image": "https://s3.amazonaws.com/your-bucket/images/{id}.png"
}

上面的示例显示了如何使用 JSON-LD 来引用模式文档 ($schema)。

以下是对应的模式文档,可以使用上面的 URI "https://URL_TO_SCHEMA_DOCUMENT" 访问。

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Identifies the asset to which this NFT represents"
    },
    "description": {
      "type": "string",
      "description": "Describes the asset to which this NFT represents"
    },
    "image": {
      "type": "string",
      "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
    }
  }
}

假设以上元数据和模式适用于标识符为 1234 的 token。(在 ERC-721 中,这将是一个特定的 token,在 ERC-1155 中,这将是一个 token 类型。)那么这两个函数调用可能具有以下输出:

  • function tokenURIIntegrity(1234)
    • bytes digest : 3fc58b72faff20684f1925fd379907e22e96b660
    • string hashAlgorithm: sha256
  • function tokenURISchemaIntegrity(1234)
    • bytes digest : ddb61583d82e87502d5ee94e3f2237f864eeff72
    • string hashAlgorithm: sha256

为了避免疑问:前一段指定“MAY”具有该输出,因为其他哈希函数也是可以接受的。

实现

0xcert Framework 支持 ERC-2477。

参考

规范性标准参考

  1. RFC 2119 用于指示需求级别的 RFC 中的关键词。https://www.ietf.org/rfc/rfc2119.txt
  2. ERC-165 标准接口检测。./eip-165.md
  3. ERC-721 非同质化 Token 标准。./eip-721.md
  4. ERC-1155 多 Token 标准。./eip-1155.md
  5. JSON-LD。https://www.w3.org/TR/json-ld/
  6. 安全哈希标准 (SHS)。https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf

其他标准

  1. ERC-1046 ERC-20 元数据扩展(草案)。./eip-1046.md
  2. ERC-918 可挖矿 Token 标准(草案)。./eip-918.md
  3. ERC-1523 标准,用于将保险单作为 ERC-721 非同质化 Token(草案)。./eip-1523.md
  4. W3C 子资源完整性 (SRI)。https://www.w3.org/TR/SRI/
  5. “data” URL 方案。https://tools.ietf.org/html/rfc2397
  6. 统一资源标识符 (URI):通用语法。https://tools.ietf.org/html/rfc3986
  7. CID [规范](草案)。https://github.com/multiformats/cid

讨论

  1. JSON-LD 关于引用完整性的讨论。https://lists.w3.org/Archives/Public/public-json-ld-wg/2020Feb/0003.html
  2. JSON Schema 使用 $schema 键来表示文档。https://github.com/json-schema-org/json-schema-spec/issues/647#issuecomment-417362877

其他

  1. [0xcert Framework 支持 ERC-2477]。https://github.com/0xcert/framework/pull/717
  2. [Shattered] 第一个完整的 SHA-1 冲突。https://shattered.io/static/shattered.pdf
  3. [320 字节文件] 第二个 SHA 冲突。https://privacylog.blogspot.com/2019/12/the-second-sha-collision.html
  4. [选择前缀] https://sha-mbles.github.io
  5. 过渡:关于转换密码算法和密钥长度使用的建议。(修订版 1。已取代。)https://csrc.nist.gov/publications/detail/sp/800-131a/rev-1/archive/2015-11-06
  6. 商业国家安全算法 (CNSA) 套件概况介绍。https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/commercial-national-security-algorithm-suite-factsheet.cfm
  7. ETSI 分配的 ASN.1 对象标识符。https://portal.etsi.org/pnns/oidlist
  8. 计算机安全对象注册。https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
  9. The Sandbox 实现。https://github.com/pixowl/sandbox-smart-contracts/blob/7022ce38f81363b8b75a64e6457f6923d91960d6/src/Asset/ERC1155ERC721.sol

版权

CC0 下放弃版权及相关权利。

Citation

Please cite this document as:

Kristijan Sedlak (@xpepermint), William Entriken <github.com@phor.net>, Witek Radomski <witek@enjin.io>, "ERC-2477: Token Metadata Integrity [DRAFT]," Ethereum Improvement Proposals, no. 2477, January 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2477.