FEATURED · 精选文章

fhEVM 智能合约 ACL 实战指南:密文授权、访问校验与用户解密权限管理

发布时间 / 2026/9/12 11:10:49
来源 / 创域科博编辑部
栏目 / 资讯中心
fhEVM 智能合约 ACL 实战指南:密文授权、访问校验与用户解密权限管理 fhEVM 智能合约 ACL 实战指南密文授权、访问校验与用户解密权限管理【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm本文基于 fhEVMFully Homomorphic Encryption EVM全同态加密框架的官方开发文档系统讲解在 Solidity 合约中如何通过 ACLAccess Control List访问控制列表管理密文的访问权限包括永久授权allow、瞬时授权allowTransient、当前合约授权allowThis、公开可解密makePubliclyDecryptable以及发送方权限校验isSenderAllowed。读完本文你将掌握如何在 fhEVM 合约中正确授权与校验密文句柄handle并能在用户解密场景下为合约与用户双方正确配置 ACL 权限有效抵御针对密文的推理攻击inference attack。ACL 权限模型概述两种授权类型fhEVM 的 ACL 是一套密文权限管理系统用于控制谁可以对某个密文进行计算、操作或解密。由于 FHE 加密数据完全保密即使持有密文的合约自身未经授权也无法使用该密文因此 ACL 是保障「密文可组合、权限可控」的核心基础设施。ACL 提供两类授权方式开发者应根据权限的生命周期需求选择授权类型函数存储位置适用场景永久授权Permanent allowanceFHE.allow(ciphertext, address)专用 ACL 合约中的持久化存储跨交易有效需要长期访问某个密文的合约或用户瞬时授权Transient allowanceFHE.allowTransient(ciphertext, address)基于 EIP-1153 的 transient storage仅当前交易有效在单笔交易内把密文传给外部函数或做临时计算节省 Gas永久公开授权FHE.makePubliclyDecryptable(ciphertext)专用 ACL 合约中的持久化存储需要任何账户都能解密密文的场景如公开审计结果关于 EIP-1153 transient storage 的说明allowTransient的权限记录在交易结束后自动清除不会写入合约长期存储因此写入成本远低于普通SSTORE非常适合「仅在当前调用链内临时共享密文」的场景。永久授权FHE.allow基本用法FHE.allow(ciphertext, address)为指定地址授予对某个密文的持久访问权。权限被保存在专用的 ACL 合约中跨交易长期有效适合需要反复处理该密文的合约或账户。// 为 address1 授予对 ciphertext 的永久访问权 FHE.allow(ciphertext, address1);链式调用语法方法链由于FHE是一个 Solidity library库你可以用using FHE for *;引入后直接在密文对象上调用授权函数形成流畅的链式写法using FHE for *; ciphertext.allow(address1).allow(address2);上述写法等价于依次调用FHE.allow(ciphertext, address1)与FHE.allow(ciphertext, address2)。瞬时授权FHE.allowTransientFHE.allowTransient(ciphertext, address)为指定地址授予仅限当前交易内有效的访问权权限存放在 transient storage 中用于在交易内把加密值在函数或合约之间传递以显著节省 Gas 成本。using FHE for *; ciphertext.allowTransient(address1).allowTransient(address2);与永久授权一样瞬时授权同样支持方法链语法。语法糖FHE.allowThisFHE.allowThis(ciphertext)等价于FHE.allow(ciphertext, address(this))用于快速为当前合约自身授予永久访问权简化「合约需要跨交易管理密文」时的写法using FHE for *; ciphertext.allowThis();典型场景合约在transfer等函数中计算出一个新的加密余额如newBalanceTo写入状态后必须在函数结束前调用FHE.allowThis(newBalanceTo)否则下一笔交易中合约自己都无法使用这个新句柄详见下文用户解密示例。公开可解密FHE.makePubliclyDecryptableFHE.makePubliclyDecryptable(ciphertext)为密文授予任何人可解密的权限适用于希望对外公布加密结果或数据的场景// 授予密文公开解密权 FHE.makePubliclyDecryptable(ciphertext); // 或使用方法语法 ciphertext.makePubliclyDecryptable();函数FHE.makePubliclyDecryptable(ciphertext)目的使密文可以被任何账户解密使用场景发布加密的计算结果或数据例如密封式拍卖sealed-bid auction结束后公开最终成交价供所有人验证。从底层实现看该函数将句柄封装为数组后调用 ACL 合约的allowForDecryption(handlesList)为句柄设置allowedForDecryption标记见 Impl.sol 与 ACL.sol。组合授权单条流畅语句授予多个对象fhEVM 允许在密文对象上组合多种授权方法.allow()、.allowThis()、.allowTransient()一条语句即可为多个地址或合约授予不同性质的访问权// 给 address1 瞬时访问权同时给 address2 永久访问权 ciphertext.allowTransient(address1).allow(address2); // 给当前合约永久访问权同时给 address1 永久访问权 ciphertext.allowThis().allow(address1);这种组合写法在「一次计算产生多个新密文、且每个密文需要同时授权给合约与持有人」的场景中尤为实用。最佳实践验证发送方访问权限为什么必须校验isSenderAllowed当合约把密文作为输入处理时必须验证发送方msg.sender确实有权使用该密文。如果跳过这一步合约将暴露在推理攻击inference attack之下——恶意参与者可以通过构造交易逐步推断出他人的私密信息。攻击场景机密 ERC20 的泄露假设一个机密 ERC20 代币提供如下函数但没有调用FHE.isSenderAllowed(encryptedAmount)合约盲目信任调用者传入的加密金额function transfer(address to, euint64 encryptedAmount) public { ... }攻击者控制两个自己拥有的账户——账户 A持有 100 枚代币与账户 B——目标是不通过解密获知受害者账户 V的余额。攻击步骤如下读取受害者余额句柄受害者的加密余额句柄在链上公开可读它存在于合约存储balances[V]中攻击者直接读取该句柄。伪造传入受害者句柄攻击者用账户 A 调用transfer(B, balances[V])——把受害者的余额句柄当作encryptedAmount传入。由于合约没有isSenderAllowed校验合约无法察觉这个句柄并非攻击者自己产生的。条件转移transfer内部执行canTransfer FHE.le(encryptedAmount, balances[A])并借助FHE.select有条件地转移金额。最终是否真的转移取决于balance[V] 100是否成立。观察结果攻击者读取交易后的balances[B]——新句柄要么反映余额增加转移成功 ⇒balance[V] 100要么不变转移被跳过 ⇒balance[V] 100。每一次成功或失败的转移都泄露受害者余额的1 bit信息。攻击者用不同的发送方余额反复执行该攻击即可用二分法精确锁定受害者的余额——全程无需任何一次解密。修复方案一行校验修复只需一行代码要求FHE.isSenderAllowed(encryptedAmount)使合约只接受发送方确实被授权使用的句柄function transfer(address to, euint64 encryptedAmount) public { // 确保发送方被授权访问该加密金额 require(FHE.isSenderAllowed(encryptedAmount), Unauthorized access to encrypted amount.); // 继续后续逻辑 ... }通过强制执行这一检查可以抵御推理攻击确保加密值只能被授权实体操作。仓库中真实的 EncryptedERC20.sol 示例即采用了同样的防护模式在transfer、transferFrom、approve等入口统一require(FHE.isSenderAllowed(amount))。用户解密场景下的 ACL为「用户 合约」双重授权用户解密user decryption机制有一个关键约束一个密文若想被某用户解密必须显式授予该用户访问权同时由于用户解密需要签署与合约地址关联的公钥该密文还必须被授权给对应合约。具体而言用户解密流程要求用户对「与某个特定合约关联的公钥」进行签名因此密文必须同时为用户和合约双方开启权限二者缺一不可。示例ConfidentialERC20 中的安全转账function transfer(address to, euint64 encryptedAmount) public { require(FHE.isSenderAllowed(encryptedAmount), The caller is not authorized to access this encrypted amount.); euint64 amount FHE.asEuint64(encryptedAmount); ebool canTransfer FHE.le(amount, balances[msg.sender]); euint64 newBalanceTo FHE.add(balances[to], FHE.select(canTransfer, amount, FHE.asEuint64(0))); balances[to] newBalanceTo; // 同时为新余额授予合约与收款人的访问权 FHE.allowThis(newBalanceTo); FHE.allow(newBalanceTo, to); euint64 newBalanceFrom FHE.sub(balances[from], FHE.select(canTransfer, amount, FHE.asEuint64(0))); balances[from] newBalanceFrom; // 同时为新余额授予合约与转出方的访问权 FHE.allowThis(newBalanceFrom); FHE.allow(newBalanceFrom, from); }这段代码的要点入口校验先通过FHE.isSenderAllowed(encryptedAmount)确认调用者有权使用传入的密文句柄计算新余额用FHE.le判断余额是否充足、用FHE.select做条件选择全程在密文上进行双重授权每个新产生的余额句柄都必须同时执行FHE.allowThis(...)授权给合约自身与FHE.allow(..., owner)授权给余额归属方否则后续交易中合约无法继续操作、用户也无法发起解密。仓库中的真实实现 EncryptedERC20.sol 与上述模式完全一致在transfer内为新余额同时调用FHE.allowThis(newBalanceTo)与FHE.allow(newBalanceTo, to)。底层实现从库函数到 ACL 合约理解 ACL 的底层调用链有助于把握权限系统的行为边界。整个流程分为三层第一层FHE.sol库用户入口FHE.sol 为每种加密类型euint8、euint16、euint32、euint64、euint128、euint256、eaddress、ebool都重载了全套 ACL 函数。以euint64为例isAllowed(euint64 value, address account)内部解包句柄后调用Impl.isAllowed(handle, account)返回该账户是否有权使用该值isSenderAllowed(euint64 value)即Impl.isAllowed(euint64.unwrap(value), msg.sender)——以msg.sender为账户参数的便捷校验allow/allowThis/allowTransient/makePubliclyDecryptable统一先处理「未初始化值」未初始化的句柄会被替换为零值密文再转发给Impl层。第二层Impl.sol内部库路由转发Impl.sol 负责将调用路由到 Coprocessor 配置中记录的 ACL 合约地址allow(handle, account)→IACL($.ACLAddress).allow(handle, account)allowTransient(handle, account)→IACL($.ACLAddress).allowTransient(handle, account)makePubliclyDecryptable(handle)→ 将句柄装入单元素数组后调用IACL($.ACLAddress).allowForDecryption(handleArray)isAllowed(handle, account)→IACL($.ACLAddress).isAllowed(handle, account)该结果同时覆盖瞬时授权与持久授权。第三层ACL.sol合约权限状态与强制ACL.sol 是权限的最终执行者几个关键行为值得注意allow的双重校验调用者不得在拒绝名单上否则revert SenderDenied且调用者必须已被允许使用该句柄否则revert SenderNotAllowed随后写入持久化的persistedAllowedPairs[handle][account]allowTransient的特殊豁免FHEVMExecutor与ConfidentialBridge两个系统合约可以无条件调用allowTransient普通合约则仍需通过上述校验权限通过内联汇编的tstore/tload写入 EIP-1153 transient storage交易结束后自动清空cleanTransientStorage提供手动清除瞬时授权的入口可用于账户抽象Account Abstraction场景下在同一区块批量打包多个 UserOp 时隔离权限状态见 ACL.sol。仓库测试也印证了这些行为例如 acl.t.sol 覆盖了「未授权发送方调用allowTransient会 revert」「FHEVMExecutor 地址可调用allowTransient直至 transient storage 被清理」等用例acl.ts 则验证了allowTransient()的非持久性与 revert 行为可作为阅读与回归验证的参考。小结ACL 是 fhEVM 安全模型的核心支柱。掌握以下要点即可在实战中正确使用按生命周期选授权方式跨交易长期访问用FHE.allow/FHE.allowThis单笔交易内临时共享用FHE.allowTransient全员可解密用FHE.makePubliclyDecryptable输入密文必须校验发送方凡接收外部密文的入口函数都应require(FHE.isSenderAllowed(...))这是抵御推理攻击的第一道防线用户解密需双重授权密文必须同时授权给目标用户与相关合约二者缺一不可新产生的密文句柄要及时授权任何写入状态的新句柄都应在交易内完成授权否则后续交易无法使用。如需进一步深入可继续阅读 ACL 概念总览含 transient 与 permanent 的对比、验证函数总表、用户解密委托后端服务/中继代理解密的完整约束与模式以及 FHEVM API 参考。【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻