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 对应物。
摘要
为智能合约指定了一个具有两个函数 tokenURIIntegrity
和 tokenURISchemaIntegrity
的接口 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 识别名称 sha256
、sha384
和 sha512
(不区分大小写匹配)。我们知道有两个机构提供哈希函数的分类法和规范名称: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。
参考
规范性标准参考
- RFC 2119 用于指示需求级别的 RFC 中的关键词。https://www.ietf.org/rfc/rfc2119.txt
- ERC-165 标准接口检测。./eip-165.md
- ERC-721 非同质化 Token 标准。./eip-721.md
- ERC-1155 多 Token 标准。./eip-1155.md
- JSON-LD。https://www.w3.org/TR/json-ld/
- 安全哈希标准 (SHS)。https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
其他标准
- ERC-1046 ERC-20 元数据扩展(草案)。./eip-1046.md
- ERC-918 可挖矿 Token 标准(草案)。./eip-918.md
- ERC-1523 标准,用于将保险单作为 ERC-721 非同质化 Token(草案)。./eip-1523.md
- W3C 子资源完整性 (SRI)。https://www.w3.org/TR/SRI/
- “data” URL 方案。https://tools.ietf.org/html/rfc2397
- 统一资源标识符 (URI):通用语法。https://tools.ietf.org/html/rfc3986
- CID [规范](草案)。https://github.com/multiformats/cid
讨论
- JSON-LD 关于引用完整性的讨论。https://lists.w3.org/Archives/Public/public-json-ld-wg/2020Feb/0003.html
- JSON Schema 使用
$schema
键来表示文档。https://github.com/json-schema-org/json-schema-spec/issues/647#issuecomment-417362877
其他
- [0xcert Framework 支持 ERC-2477]。https://github.com/0xcert/framework/pull/717
- [Shattered] 第一个完整的 SHA-1 冲突。https://shattered.io/static/shattered.pdf
- [320 字节文件] 第二个 SHA 冲突。https://privacylog.blogspot.com/2019/12/the-second-sha-collision.html
- [选择前缀] https://sha-mbles.github.io
- 过渡:关于转换密码算法和密钥长度使用的建议。(修订版 1。已取代。)https://csrc.nist.gov/publications/detail/sp/800-131a/rev-1/archive/2015-11-06
- 商业国家安全算法 (CNSA) 套件概况介绍。https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/commercial-national-security-algorithm-suite-factsheet.cfm
- ETSI 分配的 ASN.1 对象标识符。https://portal.etsi.org/pnns/oidlist
- 计算机安全对象注册。https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
- 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.