本文将分享 CertiK 对 PSBT 的深入研究和洞察,包括其组件、在比特币 DeFi 中的应用以及不当使用可能带来的安全风险。我们旨在提供安全实施 PSBT 的最佳实践,帮助开发者和 Web3 成员更好地了解其安全性,为加强比特币生态系统的安全性贡献力量。

作者:Certik

近年来,部分签名比特币交易(PSBT)在比特币生态系统中获得了显著关注。随着如 Ordinal 和基于铭文的资产 [1]等创新的兴起,安全的多方签名和复杂交易的需求不断增加,这使得 PSBT 成为应对比特币生态不断发展中不可或缺的工具。

CertiK 致力于推动 PSBT 使用的安全性和完整性。近期,我们对 UniSat Wallet Extension[2]、SwapSats[3]和 Trac’s Tap Protocol[4]等热门项目进行了全面的审计和渗透测试,这些项目广泛使用了 PSBT 来支持其复杂的交易工作流程。通过深入分析,我们识别出与 PSBT 实现相关的漏洞,并提供了切实可行的建议以加强其安全能力。

本文将分享 CertiK 对 PSBT 的深入研究和洞察,包括其组件、在比特币 DeFi 中的应用以及不当使用可能带来的安全风险。我们旨在提供安全实施 PSBT 的最佳实践,帮助开发者和 Web3 成员更好地了解其安全性,为加强比特币生态系统的安全性贡献力量。

PSBT 概述

自比特币网络诞生以来,其不断演进以应对日益增长的安全性、效率和可扩展性需求。在这一发展过程中,PSBT 的出现是交易管理领域的一个重要创新。PSBT 的定义来源于比特币改进提案 174(BIP-174[5]),其通过标准化流程为比特币交易的创建、共享和签名提供了规范,尤其适用于多方或多设备的场景。

在 2017 年 PSBT 推出之前,协调需要多个签名或涉及多方的复杂交易的过程困难又存在安全风险。钱包软件通常采用专有格式来处理部分签名交易,这导致了不同钱包和平台之间的不兼容问题。而 BIP-174 提案为 PSBT 制定通用格式来解决这些问题。此标准化使得不同的钱包软件和硬件设备之间能够无缝兼容通信,从而促进了多方交易的协作创建和签名过程。

随着 2023 年 Ordinal 协议 [6]的出现,PSBT 再次成为焦点。Ordinal 协议为单个聪(satoshi)分配序列号,并允许用户将额外数据附加到聪上。这一协议使用户能够通过在比特币区块链上为聪刻写数据,直接创建非同质化代币(NFT)及其他独特的数字资产(如 BRC-20[7])。管理这些资产需要精确控制交易的入账和出账,以及拥有处理复杂脚本和签名的能力,而 PSBT 都能满足这些需求。因此,PSBT 技术在去年迎来了复兴,并在比特币生态中的多个领域被广泛应用。

1.PSBT 工作流程解析

PSBT 以标准化且安全的方式支持比特币交易的创建、共享和签名,尤其适用于多方参与的场景。

PSBT 工作流程的主要步骤:

1. 发起者通过选择必要的输入和输出来构建未签名的交易,并将其转换为 PSBT 格式。这份 PSBT 包含所有必要的交易细节,但不含任何签名,随后安全地分发给相关各方。

2. 每位参与者独立审核 PSBT,以验证输入、输出、金额和地址是否符合其预期,确保交易细节的准确性和有效性。

3. 随后,参与者在不暴露私钥的前提下,为他们控制的输入添加部分签名。签名完成后,他们可以验证其他人添加的部分签名,以确保其有效性和准确性。该协作过程可能需要多次签名贡献与验证的迭代,直到添加了所有所需的签名为止。

4. PSBT 返回给交易的发起者或协调者,他们会检查是否已收集到所有必要的签名。

5. 一旦所有签名确认收集并验证后,PSBT 将通过替换部分签名和脚本为最终输入脚本(scriptSig 和 scriptWitness)来完成最终化,随后生成一份完整签名的交易,并准备进行广播。

6. 最终完成的交易被广播到比特币网络,等待确认和执行。一旦交易被确认并包含在区块链中,比特币账本将更新以记录交易的输入和输出。

以下图表可以帮助更清晰地理解上述工作流程:

PSBT CoinJoin 工作流程

2.PSBT 与多签交易的关键区别

尽管 PSBT 和多签交易都涉及多个签名,但它们在比特币网络中有着不同的用途。多签交易需要多个私钥来授权一笔交易,在资金可以被花费之前,必须满足指定数量的签名要求。而另一方面,PSBT 则允许多个参与方协作创建和签署交易,无论交易本身是否需要多个签名。

3.PSBT 组件

理解 PSBT 的组件结构对于有效使用它并确保交易安全至关重要。以下是其关键组件的详细说明。

1. 输入

PSBT 中的输入引用了用于资助交易的未花费交易输出(UTXO)。

  • 前一个交易哈希和索引:每个输入引用了一个特定的 UTXO,该 UTXO 通过 txid(前一个交易的哈希)和 vout(在引用交易中的输出索引)来标识。

示例输入:

  • 序列号:表示输入的序列,用于相对时间锁定(Relative Timelock),常见于高级脚本场景中。
  • 非见证未消费的交易输出(Non-Witness UTXO):此组件包含完整的上一笔交易数据。需要用于非隔离见证(non-SegWit)输出,以便根据整个交易验证输入。
  • 见证未消费交易输出(Witness UTXO):对于隔离见证(SegWit)交易,仅包含正在花费的输出。其比非见证 UTXO 更高效,但却提供更少的信息。
  • 可选组件:
    • 支付见证脚本哈希 (P2WSH):包含花费 SegWit 输出所需的见证脚本。
    • 支付脚本哈希 (P2SH):包含花费 P2SH 输出所需的赎回脚本。
    • 签名哈希类型 (Sighash):定义签名哈希类型,指定交易中被签名的范围。

2. 输出

输出定义了资金的发送目标,以 UTXO 的形式存在,通常用于找零或退款。

  • 脚本公钥(ScriptPubKey):是用于指定花费输出的条件的锁定脚本。
  • 金额:以聪为单位,表示输出的价值。

3. 交易元数据

  • 版本:指定交易格式的版本;在 BIP-0370[8]之后,“PSBT 版本 2” 成为标准。
  • 锁定时间(Locktime):表示交易可被纳入区块的最早时间或区块高度。

4. 签名

  • 部分签名:每个签名者根据其私钥添加自己的签名。
  • 公钥标识:将签名与正确的公钥关联以进行验证。

5. 最终化数据

  • 解锁脚本(ScriptSig)和见证数据:满足脚本公钥(ScriptPubKey)中指定条件的最终脚本。

4.PSBT 工具

多种工具和库支持 PSBT 的创建、操作和签名,促进了其在不同平台上的应用。

Bitcoin Core 命令

作为比特币协议的参考实现,Bitcoin Core 提供了多个用于处理 PSBT 的命令:

  • converttopsbt:将原始交易转换为 PSBT 格式。
  • createpsbt:根据提供的输入和输出生成 PSBT,而无须访问钱包。
  • walletcreatefundedpsbt:使用钱包中的 UTXO 为交易提供资金,自动选择输入并计算费用,生成 PSBT。
  • decodepsbt:返回一个 JSON 对象,用于表示序列化的 Base64 编码 PSBT。

PSBT 在比特币生态系统中的应用场景

一些协议例如 Ordinal、Runes 和 BRC-20 代币等的兴起显著扩展了比特币的功能,使得代币资产和 NFT 可以直接在比特币链上实现。PSBT 在这些发展中发挥了关键作用,通过允许对交易输入和输出进行精确控制,这对于安全地管理和转移这些独特的数字资产至关重要。PSBT 还帮助改善了钱包签名过程,特别是在硬件钱包和安全签名设备的集成方面。

比特币 DeFi 的关注度增长也加速了 PSBT 的使用。开发者利用 PSBT 构建去中心化交易所、atomic 交换协议和协作交易平台,确保这些平台的安全性和高效性。通过将涉及多方的交易创建、共享和签名过程标准化,PSBT 促进了以前难以在比特币网络上安全实现的复杂金融操作。

1.Ordinal 市场中的订单簿交易所

PSBT 被 Ordinal 市场用于推进 Ordinal NFT 的交易。买家或卖家可以使用 PSBT 创建一笔订单交易。交易创建者将 PSBT 文件发送给其他参与者。在所有参与者签署 PSBT 文件后,即可被最终确认并广播到比特币网络。

为什么 PSBT 在 Ordinal 市场中不可或缺?

Ordinal 是刻在单个聪上独特的数字资产,需要对交易输入和输出进行精确控制以确保其完整性。PSBT 使买家和卖家等多方能够协作构建和签署交易,同时避免暴露私钥或降低安全性。

其他选项(如原始交易或自定义协议)并不适用,因为它们缺乏必要的功能和安全保证。原始交易不支持部分签名,这意味着整个交易的构建完全由单个交易创建者负责。此方法需要用户手动验证交易,增加了出错和安全漏洞的风险。而自定义协议则可能强迫用户使用市场提供的特定钱包。这种要求限制了用户使用其首选钱包的自由性,同时减少了互操作性,因为这些市场专属钱包可能与其他平台或服务不兼容。此外,一些市场可能会使用中心化托管服务来促进交易,但这引入了第三方风险,因为用户必须授信托管代理能够妥善处理资金。

以下是一个典型用于市场交易的 PSBT 工作流程案例。以下以 msigner[12]为例,展示了一个卖单的创建过程,具体步骤如下:

1. 卖家使用 SIGHASH_SINGLE|ANYONECANPAY 签署 PSBTPSBT 输入 [13]

PSBT 输出 [14]

2. 买家使用 SIGHASH_DEFAULT 签署完整的 PSBT,并根据可用的全部信息完成操作。买家应选择支付 UTXO,并避免包含铭文的支出 UTXO。

输入 [15]

输出 [16]

3. 在 PSBT 工作流程中担任合并角色的交易所执行以下操作:

  • 验证卖家的签名
  • 验证买家的签名
  • 合并卖家和买家的签名
  • 完成交易并运行内存池接受测试
  • 广播交易

2.协作交易

PSBT 通过标准化签名流程,简化多签设置中的工作流程,使多个参与方能够贡献输入与输出达成一致。

  • 联合筹资是一种多个参与者共同集资以实现集体支付的过程。这在共享投资、联合购买或团体捐赠等场景中尤为有用。通过使用 PSBT,这种无须信任的协作机制得以实现。用户使用所有参与方的 UTXO 作为输入创建一个 PSBT,然后每个参与者审核交易内容,确保交易符合其意图。在确认无误后,他们使用自己的私钥对交易进行签名。只有当所有参与者完成签名后,PSBT 才能被最终确认并成为可以广播的有效交易。
  • UTXO 共享管理是指多个参与方对 UTXO 的协作控制和管理,这通常用于企业或组织环境中。PSBT 通过引入资金在多方审批下进行共同管理,从而增强了安全性和监督能力。

3. 哈希时间锁合约(HTLC)与跨链兑换

PSBT 对于实现原子性兑换和不同区块链之间的无须信任的交易所至关重要。通过构建仅在特定条件下有效的交易,PSBT 能够在无须中介的情况下促成跨链交换。在这一过程中,通常会结合使用 PSBT 和哈希时间锁合约(HTLC)来确保兑换的原子性。

HTLC 利用加密哈希函数和基于时间的条件来保证交易的公平性。如果在预定时间内未满足必要条件,交易将自动取消。这一机制确保了双方要么完成兑换交易,要么恢复到原始状态,无任何损失。将 PSBT 与 HTLC 相结合,用户可以在比特币与其他区块链之间进行安全的跨链兑换,实现无须依赖中心化平台或可信第三方的资产交换。

4. 交易批处理与费用优化

PSBT 的独特功能允许批处理交易中的每个输入和输出单独签署。在交易批处理中使用 PSBT 有助于降低交易费用。通过将多个交易合并,用户不仅节省了费用,还能缓解比特币网络的拥堵问题。

5. 离线签名与硬件钱包集成

PSBT 通过标准化未完成交易的表示方式,为离线签名提供了更安全且高效的工作流程。在引入 PSBT 之前,用户需要手动处理原始交易数据并自行验证输入和输出。在多方交易中,通常由一方参与者组装完整交易,其他参与者再进行验证。这种方法依赖可信的第三方,或要求用户仔细验证交易。借助 PSBT,每方都可以独立添加自己的输入和输出,并验证所有组件,而无须联网。这使签名和验证过程保持离线状态,对硬件钱包来说是一项重要的安全优势。此外,标准化的 PSBT 格式确保了与各种硬件钱包的兼容性,即使是隔离网络的设备,也能轻松解析并签署交易。

安全问题与常见误用

尽管 PSBT 有诸多优势,但对于急于推出新型比特币 DeFi 解决方案的新手来说可能并不熟悉。不当使用可能会导致严重的安全漏洞,从而引发数据泄露和资金损失。

我们将通过以下的实际案例分析误用 PSBT 的场景。这些例子旨在为开发者提供关键见解,帮助其保护资产安全并确保比特币 DeFi 生态系统中交易的完整性。

1. 错误使用 Sighash 标志

Sighash 标志决定了一笔交易在签名后哪些部分不可更改。不正确地使用 Sighash 标志可能导致交易容易被黑客篡改。以下是不同 Sighash 标志及其影响的解释:

  • SIGHASH_ALL (0x01):对所有输入和输出进行签名;提供最高的安全性,防止任何修改。
  • SIGHASH_NONE (0x02):对所有输入签名,但不签名任何输出;允许更改输出。
  • SIGHASH_SINGLE (0x03):对所有输入和一个对应的输出签名;如果输出顺序被重排,风险较高。
  • SIGHASH_ANYONECANPAY (0x80):修改上述标志,使其仅对当前输入签名;允许添加其他输入。

Sighash 标志误用的实际案例:Atomicals Market 事件

2023 年 11 月 15 日,Atomicals Market 发生了一起 “零元购” 事件。卖家在市场上挂单出售 $ATOM,但却被黑客以零成本购买。Atomicals Protocol 表示,事件的根本原因在于 Atomicals Market 使用了 SIGHASH_NONE|ANYONECANPAY 标志,导致用户资金被窃取。

SIGHASH_NONE|ANYONECANPAY 标志只对签名者的输入进行签名,可以添加其他输入,并允许修改输出。黑客可能会利用这一点,在输入签名后更改资金的去向。用户和开发者必须了解并正确实现 Sighash 标志,以避免误用导致资产损失。

在这种情况下,卖家的挂单应使用 SIGHASH_SINGLE|ANYONECANPAY[17]进行签名,以确保交易安全。

SIGHASH_NONE|ANYONECANPAY 标志表明仅对卖方的输入进行签名,而交易输出部分是可变的。如果黑客获得了卖方的签名,并将交易重新构建为输出值为零,再对其签名并广播交易,就会导致卖方的代币以零支付的方式被出售。

其他潜在攻击向量:

  • 输出修改:如果输出未被正确签名,攻击者可能会篡改输出信息,将资金重定向到自己账户或更改支付金额。例如,在多签钱包的实现中,如果错误地使用了 SIGHASH_SINGLE 且未确保输出索引与输入索引匹配,则可能会使攻击者在部分签名后篡改输出。
  • 重放攻击:攻击者可能会在不同的上下文或时间内重新提交有效的 PSBT,通过利用不当的 SIGHASH 或交易缺乏唯一性进行攻击。

安全使用 SigHash 标志的最佳实践:

  • 默认使用 SIGHASH_ALL:确保在签名后,所有交易细节都不可更改。
  • 避免复杂的 Sighash 组合:除非确有必要并完全理解其用途,否则避免将 SIGHASH_ANYONECANPAY 与其他 Sighash 标志组合使用。
  • 彻底验证:在签名前,核实所有交易细节,包括输入、输出和脚本,以确保交易的完整性和安全性。

2. 不正确的 UTXO 选择策略

高效的 UTXO 选择对 PSBT 交易的安全性和效率至关重要。不当的 UTXO 选择可能导致各种问题,例如,暴露用户隐私风险,不必要地增加交易费用和潜在地导致交易失败。

在构建交易时,钱包会选择 UTXO 来为交易输出和费用提供资金。而这些 UTXO 选择策略可能产生重要影响:

  • 隐私问题:合并来自不同地址的 UTXO 可能会将这些地址关联起来,降低用户匿名性。
  • 费用优化:选择较小的 UTXO 可能需要包含更多的输入,增加交易大小和费用。
  • 粉尘输入(Dust Inputs):包含非常小的 UTXO(称为 dust)会增加交易大小,却不能显著增加价值,从而导致交易效率低下。

优化 UTXO 选择策略的最佳实践

为降低因 UTXO 的不当选择带来的风险,可采用以下最佳实践:

  • 优化 UTXO 管理:优先使用较大的 UTXO 来尽量减少输入数量,从而降低交易大小和费用。采用能够自动平衡隐私和费用效率的算法。
  • 关注 dust 限制:确保找零输出高于 dust 限制,以便在未来交易中保持其有效性。

3. 意外资产焚毁

要防止意外丢失或烧毁,必须妥善处理 Ordinal 和其他代币化资产。Ordinal、Runes、ARC-20 等协议通过将数据与单个聪关联,可以直接在比特币链上展示非同质化代币(NFT)和其他数字资产。在 PSBT 处理中对这些资产管理不当可能导致不可逆的损失。

防止基于 Ordinal 资产焚毁的最佳实践

  • UTXO 管理:避免将 Ordinal 与常规 UTXO 混合。将包含 Ordinal 的 UTXO 与常规资金分开管理。对每个 Ordinal 资产使用单独的代码逻辑。
  • 谨慎处理 dust 限制:低于最小输出值(通常为标准 P2PKH 输出的 546 satoshi)的输出被认为是不经济的,可能会被网络拒绝。开发者应确保包含 Ordinal 的输出高于 dust 限制,以保持其有效性和可支出性。如果 Ordinal 被发现包含在低于 dust 限制的输出中,它可能会被 “焚毁”,因为它无法被花费或可能被节点忽略。
  • 明确定义输出:确保 Ordinal 被分配到特定的输出中,而不会意外地包含在找零输出中。

用户的 UTXO 管理策略

  • 为不同的 Ordinal 资产使用专用钱包:为 Ordinal 资产使用独立的钱包,以防止其与常规交易混合。通过将 Ordinal 资产隔离在专用钱包中,可以降低其与常规 UTXO 混合的风险。
  • 标记和追踪:详细记录包含 Ordinal 的 UTXO,包括交易 ID、地址和相关元数据,以便于管理和追踪。
  • 签名前的验证:在为 PSBT 签名前,反复检查所有交易输出并确保 Ordinal 资产被正确分配。

PSBT 安全检查清单

为了在审计过程中系统地识别 PSBT 实现中的潜在安全问题,我们基于以往审计 PSBT 项目的经验,为开发者制定了一份全面的安全检查清单作为实用指南,提供在比特币 DeFi 项目中安全使用 PSBT 的必要见解和最佳实践。

1.PSBT 输入

  • 过滤 dust UTXO:排除低于 dust 限制的 UTXO,避免生成无法使用的输出,并防止资产意外被销毁。这对包含 Ordinal 和代币化资产的交易尤为重要。
  • 总 UTXO 值匹配:验证输入值的总和是否覆盖输出值和交易费用的总和,以防止资金不足的交易,这可能导致交易失败或被网络拒绝。
  • 避免混合 Ordinal 和常规 UTXO:保持包含 Ordinal 或代币化资产的 UTXO 与常规 UTXO 分离,防止意外转移或资产丢失。
  • Taproot 钱包使用 tapInternalKey:在处理 Taproot 地址时,加入 tapInternalKey 以确保正确的花费条件,并增强 Taproot 提供的隐私防护功能。
  • 制定合适的 UTXO 策略:根据具体情境选择 UTXO,优先考虑隐私、费用优化,以及避免不必要的地址关联等因素。
  • 检查交易版本:在使用如 OP_CHECKSEQUENCEVERIFY 等高级脚本功能时,确保使用交易版本 2。

2.PSBT 输出

  • 退回多余的聪(satoshi):设置找零输出,将多余的资金退回给发送者,确保没有价值被意外遗留而未被认领。
  • 找零金额高于 dust 限制:确保找零输出金额高于 dust 限制,使其有效且可支出,避免生成无法使用的 “粉尘(dust)” 输出。

3. 费用管理

  • 精准费用估算:利用实时网络数据或 API,结合交易大小和复杂性计算准确的费用,确保交易能及时确认且不会支付过高费用。
  • 内存池接受性检查:验证最终交易是否符合网络接受标准,如标准规则和最低费用要求。

4.PSBT 签名

默认使用 SIGHASH_ALL:默认采用 SIGHASH_ALL 标志,提供最高级别的交易完整性,签署所有输入和输出,防止未经授权的修改。

谨慎变更 Sighash:在偏离默认 Sighash 标志前,充分了解其安全影响。除非绝对必要且正确实现,否则避免使用诸如 SIGHASH_ANYONECANPAY 等复杂组合。

验证部分签名:确认每个部分签名正确地签署了对应的输入。识别并处理针对同一输入的任何重复或冲突签名。

5. 正确完成 PSBT

  • 填写所有字段:在完成之前,核实所有 PSBT 必填字段,包括输入、输出和全局交易数据等。
  • 信息完整性检查:检查 PSBT 是否缺失必要的数据(如赎回脚本、见证脚本)。
  • 锁定 PSBT:在合并并验证所有签名后,最终确定 PSBT,防止进一步修改。

总结

部分签名比特币交易(PSBT)已被广泛应用于比特币生态系统,以实现对 DeFi 应用至关重要的安全、复杂且协作的交易流程。然而,不当使用 PSBT 可能导致严重的安全漏洞,包括交易的可篡改性和资产的意外损失。

CertiK 凭借对 PSBT 安全方面的丰富的技术经验和专业,帮助项目解决安全实施中的复杂挑战。通过审计服务和全面的最佳实践,我们为开发者和组织机构提供开发知识以确保 PSBT 的安全高效使用。

如果您需要对协议代码进行深入审计,或希望与经验丰富的审计师和安全专家团队进行咨询,请点击 “阅读原文” 或访问 CertiK.com 与我们联系。

[1] Ordinal 和基于铭文的资产: https://www.certik.com/resources/blog/ordinals-and-the-brc-20-standard-overview-and-risk-analysis

[2] UniSat Wallet Extension: https://unisat.io/

[3] SwapSats: https://swapsats.io/

[4] Trac’s Tap Protocol: https://trac.network/tap/

[5] BIP-174: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki

[6] Ordinal 协议: https://docs.ordinals.com/overview.html

[7] BRC-20: https://www.coindesk.com/learn/brc-20-explained-how-tokens-on-bitcoin-work-and-why-they-are-controversial

[8] BIP-0370: https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki[9] BitcoinJS: https://github.com/bitcoinjs/bitcoinjs-lib

[10] Libwally: https://github.com/ElementsProject/libwally-core

[11] BTCD: https://github.com/btcsuite/btcd[12] msigner: https://github.com/me-foundation/msigner

[13] PSBT 输入:https://github.com/me-foundation/msigner/blob/30499e1a8b352b8e4b6007450932be1a15b92955/src/signer.ts#L70

[14] PSBT 输出:https://github.com/me-foundation/msigner/blob/30499e1a8b352b8e4b6007450932be1a15b92955/src/signer.ts#L89

[15] 输入: https://github.com/me-foundation/msigner/blob/30499e1a8b352b8e4b6007450932be1a15b92955/src/signer.ts#L416

[16] 输出: https://github.com/me-foundation/msigner/blob/30499e1a8b352b8e4b6007450932be1a15b92955/src/signer.ts#L458

[17] SIGHASH_SINGLE|ANYONECANPAY: https://twitter.com/atomicalsxyz/status/1727771786287206717

免责声明:作为区块链信息平台,本站所发布文章仅代表作者及嘉宾个人观点,与 Web3Caff 立场无关。文章内的信息仅供参考,均不构成任何投资建议及要约,并请您遵守所在国家或地区的相关法律法规。