非正式草案 2024 年 5 月 1 日
本版本:https://www.w3.org/TR/unofficial-did-btc-method-20240501/
最新发布版本:https://microstrategy.github.io/did-btc-spec
最新编辑草案:https://microstrategy.github.io/did-btc-spec/
历史记录:[提交历史](https://github.com/MicroStrategy/did-btc-spec/commits/)
编辑:[Daniel McNally](https://github.com/sangaman)([MicroStrategy](https://www.microstrategy.com/))
作者:[Daniel McNally](https://github.com/sangaman)([MicroStrategy](https://www.microstrategy.com/))
反馈:[GitHub MicroStrategy/did-btc-spec](https://github.com/MicroStrategy/did-btc-spec/)( [pull request](https://github.com/MicroStrategy/did-btc-spec/pulls/),[new issue](https://github.com/MicroStrategy/did-btc-spec/issues/new/choose),[open issues(https://github.com/MicroStrategy/did-btc-spec/issues/)])
版权 © 2024 文档编辑/作者。文本在创作共用署名 4.0 国际公共许可证下可用;可能适用附加条款。
比特币铭文 DID 方案(did:btc)使用比特币区块链来存储和检索 DID 信息。链上的 UTXO 用于控制 DID。在交易的见证部分写入数据,DID 数据具备更大的扩展性 (extensibility) 和详细程度 (verbosity),同时减少费用和占用区块空间。
本规范符合 W3C Credentials Community Group 当前发布的 DID 规范 [DID-CORE]。
本文档是潜在规范的草案。它没有任何标准组织的官方地位或任何种类的代表性,并且不代表任何标准组织的支持或共识。
除了标记为非规范性的部分外,本规范中的所有编写指南、图表、示例和注释都是非规范性的。本规范中的其他所有内容均为规范性的。
本文档中的关键词 MAY(可选)、MUST(必须)和 SHOULD(应当)应如BCP 14 RFC2119 RFC8174中所述解释,仅当它们以全部大写字母出现时,如此处所示。
该方案的目标是仅使用公共比特币区块链作为数据源,提供无需信任、防篡改且长期有效的去中心化身份,同时确保与DID-CORE规范的完全兼容性,并为未来的扩展提供向前兼容性。
did:btc 利用比特币区块链的固有特性,包括其去中心化架构和不可变账本,以确保身份相关数据的防篡改性以及分布式存储和检索。
比特币是世界上第一个、最大和最知名的加密货币及区块链。它采用工作量证明机制——通过将交易数据与元数据和随机数混合后进行哈希运算,直到找到一个足够小的哈希值以形成一个“区块”——以确保其账本的顺序和完整性以及其中的交易。全球数千个比特币节点下载、验证并索引创建并在网络中传播的区块。这些节点通常会永久存储区块并与其他节点共享。
尽管比特币交易通常包含从一个地址到另一个地址的币的移动数据,但它们也可以包含任意数据。一个比特币操作码,OP_RETURN,不仅将一个输出标记为不可花费,而且还允许将最多 80 字节的任意数据添加到交易中。这一直被用来在区块链上添加短消息、链接和哈希字符串。
比特币交易主要由两部分数据组成:
比特币网络 2017 年的协议升级引入隔离见证(SegWit),引入了称为“见证”的第三种数据类型。SegWit 交易将所有满足输入的花费条件所需的数据放在见证中,而不是输入中,且这些数据的权重为所有其他交易数据权重的 25%,用于计算区块空间消耗和所需费用。这使得与例如 OP_RETURN 数据相比,见证数据在经济上更具优势,OP_RETURN 数据是交易输出的一部分。
比特币网络 2021 年的另一次协议升级引入 Taproot(又名 SegWit v1),对见证数据的使用方式进行了多项更改。值得注意的是,它取消了对ScriptPubKey大小为 10,000 字节的限制。
取消这一限制并结合见证数据的压缩,引入了一种称为“铭文”的技术,通过该技术,任意数据被存储在交易的见证数据中。比特币协议故意忽略这些数据,但可以通过包含它们的区块中的铭文感知软件提取和解析这些数据。图像和其他富媒体可以存储在这些任意数据中。
did:btc 采用了与 Ordinals 相似(但略有修改)的铭文方法,但仅存储与 DID 相关的数据和更新。这使得在尺寸和内容方面对 DID 文档的创建和更新几乎没有限制,同时利用了 SegWit 压缩。
也有使用比特币区块链的 DID 方法,但它们引入了额外的外部依赖。本节将这些现有方法与 did:btc 进行比较。
比特币引用 DID 方法(did:btcr)在其声明的目的和设计上与 did:btc 有许多相似之处。然而,它有几个限制,这些限制在 did:btc 得以解决。
首先,did:btcr 默认使用 secp256k1 主题密钥,这些密钥较旧,与比如 ed25519 这样的新密码学曲线相比,性能和安全性被认为较差。相比之下,did:btc 允许使用任何曲线或密钥类型,增强了功能性和向前兼容性。
其次,did:btcr 依赖于引用 URL 来获取 DID 文档数据,这破坏了区块链不可变性的本质,因为 URL 上的内容可能随时间改变或消失。另一方面,did:btc 直接在链上存储 DID 文档的额外元数据,确保了其永久性和完整性。did:btc 可以通过铭文在比特币交易的见证中存储任意数量的数据,这一技术得益于 taproot 脚本路径揭示交易,而 taproot 在 did:btcr 于 2019 年开发时尚不可用。
最后,did:btc 在链上签名比特币交易的“钱包密钥”与可用于认证和作为 DID 主体进行声明的“主题密钥”之间做了区分。这允许 DID 的控制者与其主体不同,使第三方可以代表其主体“管理”DID,甚至要求多个签名。事实上,控制 DID 所需的条件可以像比特币协议控制币一样复杂和安全。因此,更新或撤销 DID 的必要密钥(例如在主题密钥丢失或被泄露的情况下)可以比主题密钥本身持有更高的安全级别。
ION(did:ion)也使用比特币区块链用于其去中心化标识符。然而,与 did:btc 不同,链上的内容仅是指向 IPFS 中文档的指针,解析 ION did 需要索引比特币交易所指向的 IPFS 上的所有数据。虽然这确保了 IPFS 上 DID 操作的顺序和完整性,但它引入了比比特币区块链更多的外部依赖。
还有其他使用非比特币区块链的 DID 方法,本节并未详尽覆盖它们。一般来说,这些方法使用类似的方式与各自的区块链交互,并对其去中心化性质提出类似的声明。然而,比特币是最知名、最成熟、分布最广的区块链。它由最多的工作量证明来保护,且不受任何管理机构的控制。
尽管与使用比特币区块链的先前 DID 方法相比有所改进,但与使用较不安全的区块链或如互联网域名这样的可信数据源的方法相比,did:btc 仍有几个缺点和考虑因素。
即使有 SegWit 压缩,进行比特币交易和消耗比特币区块空间也可能是昂贵的。这种 DID 方法可能是每字节 DID 文档数据使用成本最高的。尽管这对防止女巫攻击提供了一些好处,通过对创建身份设置成本,但这种成本也由用户承担。
区块空间的价格也波动很大,经常导致广播交易被包含在区块中前需要等待数小时或数天。did:btc 操作永远不会是即时的,可能需要数小时。然而,紧急操作可以通过支付额外费用来加速。
解析 did:btc did 需要访问比特币节点。尽管许多区块浏览器和其他公共服务器(如 Electrum)免费提供比特币区块链数据的访问,但它们引入了一定程度的信任和外部依赖——这正是 did:btc 试图消除的。运行自己的比特币节点需要一定程度的计算能力和技术熟练度,并不能期望所有 did:btc 用户都能做到。然而,专用于 did:btc 的软件可以设计成以简单、高效的方式运行——仅从比特币区块链索引相关交易并在处理后丢弃其他非必要内容。
本节定义了本规范中使用的术语。每当这些术语在本规范中出现时,都会包含指向这些术语的链接。
在批量 DID 创建交易中指定 DID 的索引。批量创建交易包含一个公钥的字节向量,可以根据密钥长度将其分成数组,DID 索引是该数组中公钥的位置。
例如,一个包含十个 32 字节 ed25519 公钥的批次将有一个 320 字节的向量,其中前 32 字节代表第一个公钥,接下来的 32 字节代表第二个公钥,依此类推。
用于控制 DID 的 UTXO(未花费比特币交易输出)。它在与 DID 本身相同的交易中同时创建,并可用于未来交易中更新或停用 DID。DID UTXO 是一个支付至 Taproot(p2tr)输出,允许为 DID 定义复杂的花费条件。
一种数据模型,结合了指示密钥类型的前缀和公钥字节,并以MULTIBASE格式编码。更多细节见VC-DATA-INTEGRITY规范。
TxRef 编码提供了一种方便且易于阅读的方法来引用已确认的比特币交易,并可选地引用该交易中的特定输出。did:btc 利用 TxRef 创建了一种标准化、可靠且简洁的方法来引用与 DID 关联的比特币交易。TxRef 在BIP-136中定义。
用于比特币交易的 Opcodes (操作码) 组成的 [脚本语言)(https://en.bitcoin.it/wiki/Script)。
定义输出花费条件的比特币脚本。节点在比特币网络上验证此脚本以确定花费输出的交易是否有效。
将标识此 DID 方法的名称字符串为:btc。使用此方法的 DID 必须以以下前缀开头:did:btc。根据 DID 规范,此字符串必须为小写。
要引用比特币测试网网络上的交易,DID 应使用以下前缀:did:btc:test。
方案特定标识符是一个符合BIP-136的TxRef,它引用了创建 DID 的比特币交易。
示例1:使用TxRef的示例did:btc标识符
did:btc:xg4x-ay5y-q5zq-232
DID 创建交易必须在其第一个输出中包含一个 OP_RETURN,按以下顺序包含字节:
[示例2](https://microstrategy.github.io/did-btc-spec/#example-op_return-output-broken-down-by-bytes):按字节分解的OP_RETURN输出
[BlockStream Testnet Explorer](https://blockstream.info/testnet/tx/5acfba9c13bd92c27e9aa8b8cd75d03730571b2dfcc7f81543e9c15cc1efb961?expand)上可查看的交易
交易的第一个输出的[ScriptPubKey](https://microstrategy.github.io/did-btc-spec/#dfn-scriptpubkey)为6a2664696403ed01ab96ce260bf08a2fc35eda73fee1357b67e50946ca100af0c452ae695ac73053。
- 6a:OP_RETURN操作码。
- 26:一个操作码,指示接下来的36字节应该被推送到栈上——这实际上是OP_RETURN有效载荷的长度,不能超过80字节。
- 646964:ASCII中的did
- 03:一个字节,最低两位设置,表示接下来的密钥应该具有DID的认证和声明验证关系。
- ed01:一个Multicodec前缀ed编码为varint,表示接下来将是一个32字节的ed25519公钥。
- ab96ce260bf08a2fc35eda73fee1357b67e50946ca100af0c452ae695ac73053:一个32字节的ed25519公钥。
它可能包含一个支付至 Taproot(p2tr)作为其第二个输出,可用于未来比特币交易中更新或停用 DID。这个输出称为 DID UTXO。如果交易没有第二个输出,或者第二个输出不是 p2tr 输出,那么 DID 是最终的,不能在以后的时间进行更新或停用。
一旦此交易被确认,其确认的区块高度和交易索引可以编码成 TxRef 以形成 did:btc 标识符。DID 创建者必须等待交易被确认后至少 6 个区块再发布其标识符,以减少链重组的风险,以避免 DID 的区块高度或交易索引被更改。
[示例3](https://microstrategy.github.io/did-btc-spec/#example-txref-encoding):TxRef编码
上述交易在以下位置被确认:
- 区块高度为2582910。
- 交易索引为132。
- 在测试网网络上。
这编码成TxRef为xuh5-ayyy-q3q0-kp0,结果产生一个DID标识符为did:btc:test:xuh5-ayyy-q3q0-kp0。
为了减少交易开销和费用成本,DID 可以批量创建。由于多个公钥很快就会超过 80 字节的 OP_RETURN 限制,因此批量创建交易会将公钥放在揭示交易的见证部分。这需要一个承诺交易 (commitment transaction) 和一个揭示交易 (reveal transaction),但同时增加了开销。然而,对于批次中的任何数量的 DID 和密钥,开销是固定的,因此每个创建的 DID 消耗的虚拟字节成本渐近地接近公钥大小的 25%(考虑到隔离见证压缩)。对于 ed25519 密钥,这个渐近值大约是 8 字节(32 * 0.25)。
批量大小 | Commitment Txn VBytes | Reveal Txn VBytes | 总 VBytes | 每 DID VBytes |
---|---|---|---|---|
2 | 154 | 148 | 302 | 151 |
10 | 154 | 213 | 367 | 36.7 |
100 | 154 | 937 | 1091 | 10.91 |
1000 | 154 | 8178 | 8332 | 8.33 |
10,000 | 154 | 80594 | 80748 | 8.07 |
每批 DID 最多与一个DID UTXO关联,这对于共享公共控制者的 DID 集合来说是一个高效的选择。有关此过程的更多细节,请参见批量更新。
使用以下步骤批量创建 DID:
区块高度 | 交易索引 | DID 索引 | TxRef |
---|---|---|---|
2575424 | 1295 | 0 | xqyx-ay0g-pxhg-hvu |
2575424 | 1295 | 1 | 8qyx-ay0g-ppqq-9x6q-s0 |
2575424 | 1295 | 2 | 8qyx-ay0g-pzqq-rqps-jw |
使用以下步骤可以解析一个 did:btc DID:
示例 4:从创建交易中构建的 did:btc DID 文档
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "x20r-ayaz-qqtl-ljk",
"controller": "did:key:z6DtNrvHVvvKHB7m8LrCmt131TGH7DbzvcPo9mZRoCt5rqms",
"verificationMethod": [
{
"id": "x20r-ayaz-qqtl-ljk#key-0",
"controller": "x20r-ayaz-qqtl-ljk",
"type": "Multikey",
"publicKeyMultibase": "z6MkfNwZ7ncwr54BVWA9taEJLaHAWYEuqMNQfBzrwLEoaoVB"
}
],
"authentication": [
"x20r-ayaz-qqtl-ljk#key-0"
],
"assertion": [
"x20r-ayaz-qqtl-ljk#key-0"
]
}
上述步骤解析了 DID 创建时的状态。以下步骤可以确定 DID 是否已更新,并获取其 DID 文档的最新版本:
did:btc DID 可以在链上更新,保留 DID 标识符,同时修改其对应的密钥和/或 DID 文档的内容。这是通过创建一个新交易来完成的,该交易花费给定 DID 的 DID UTXO。
更新是 JSON 文档,包含 4 个可能的键:
下面的 JSON 文档提供了上述所有类型更新的示例。
{
"vm": [ // 更改验证方法
{ "i": 0 }, // 删除第0个密钥
{ "i": 1, "k": "z6Mkk8UN3tPb4sEhEvTGbv5Q6qXsG2hBwsWNjwya4tBBqLur" }, // 更新第1个密钥
{ "i": 3, "vr": 7 }, // 更新第3个密钥的验证关系
{ "k": "z6Mkr158mX63UMtTWm42jNbkhExBcVqJWwg5uo9vbyoBHGFk", "vr": 3 } // 追加一个新密钥
],
"u": [ // DID文档中密钥的更新
{
"service": [{
"id": "linked-domain1", // 更新id为linked-domain1的服务
"serviceEndpoint": "https://didservice.com" // 更新服务端点
}]
}
],
"d": [ // 从DID文档中删除的密钥
{
"service": [{
"id": "linked-domain2", // 删除id为linked-domain2的服务
}]
}
],
"a": [ // 要追加到DID文档中的密钥
{
"service": [{
"id": "linked-domain3", // 创建id为linked-domain3的服务
"type": "LinkedDomains",
"serviceEndpoint": "https://bar.example.com"
}]
}
]
}
这个 JSON 文档被写入在花费给定 DID 的 DID UTXO 的交易的见证中。文档内的更改被应用于相应的 DID。
更新交易可以在交易的第一个输出索引中创建一个新的 DID UTXO 输出,以允许对 DID 进行未来的更新。如果没有创建新的 DID UTXO 输出,DID 变为最终版本,不能进一步更新或撤销。
对批量创建的 DID 进行更新是上述结构的 JSON 数组中的更新。例如,一个旨在更新批次中第 5 个(基于零)索引的 DID 的交易将按以下方式结构化:
[
{
"i": 5,
"p": {
... // 在[更新](#更新)中描述的结构中的更新
}
}
]
当其 DID UTXO 在一个交易中被花费,且第一个输出是一个 OP_RETURN,其有效载荷为 ASCII 中的单字节 d 时,一个 did:btc DID 被认为是停用的。这表明 DID 应该被视为从停用交易的时间起永久停用。
可以通过揭示一个包含一个对象的 JSON 文档来停用批量创建的一个或多个 DID,该对象在键 d 下有一个 DID 索引位置数组。参见下面的示例:
[
{
"d": [4, 7, 9] // 停用批次中第4个、第7个和第9个索引的DID
}
]
did:btc 继承了比特币本身的安全框架。因此,它对许多常见的互联网攻击具有抵抗力,包括:
然而,与密钥管理相关的安全考虑是存在的。攻击者如果窃取了钱包密钥,可以永久控制 DID 并欺诈性地更新或撤销它们。同样,丢失的钱包密钥会导致永久失去更新或撤销相关 DID 的能力。
因此,DID 创建者和控制者应该考虑使用钱包最佳实践,如多签名钱包和备份种子短语。
did:btc 继承了比特币本身的隐私框架。区块链是公开的,因此所有交易,包括 DID 数据和操作,都是公开的。然而,现实世界的身份并未与比特币地址和交易绑定。因此,区块链上的 DID 可以是匿名的。
根据 DID 最佳实践,个人信息应该避免记录在账本上。这不仅是因为区块链的公开性而引起的隐私问题,而且由于任何人都可以写入区块链,这本质上是不可靠的。像任何其他任意数据一样,关于身份的虚假声明或与现实世界身份的连接可能会被记录在区块链上。
与 DID 创建和更新相关的链上活动是公开的,可能会泄露 DID 控制者的信息。例如,使用 10 BTC 输入创建 DID 的交易表明,DID 的创建者至少拥有 10 BTC。
区块链的观察者也可能使用区块链分析,将 DID 交易与其他 DID 交易或其他金融交易关联起来。例如,具有相同控制密钥的 DID 或同一批次中的 DID 可能会被轻易地链接在一起。