加密规范:Keybase 文件系统 (KBFS)
版本 2.0
更新日志
- 版本 2.0
- 描述新的块加密/哈希方案,解决了 NCC 审计 中的低风险问题 NCC-KB2018-005。我们最终将停止支持使用旧方案生成新块。
- 版本 1.10
- 指向新的团队文档。
- 版本 1.9
- 在我们重构文档时暂时移除关于组织的讨论。
- 版本 1.8
- 关于 KBFS Merkle 树的更多细节和日期。
- 版本 1.7
- 威胁模型
- 版本 1.6
- 说明哪些已实现,哪些正在进行中。
- 最后的写入者未加密。
- 版本 1.5
- 移除成对 HMAC,仅使用签名。
- 将文件从 crypto 重命名为 kbfs-crypto。
- 移除浏览器/确定性密钥。
- 版本 1.4
- 恢复基于 PRF 的每块密钥生成
- 提出 Jeremy 反对对具有只读成员的 TLF 进行 MAC 处理的意见。
- 提供系统概述
- 更好的密钥交换细节
- 版本 1.3
- 具有每时期文件夹密钥的基于 PRF 的每块密钥生成系统
- 尝试在各处一致地使用 "TLF" 而不是 "folder" 或 "directory"
- 版本 1.2
- 描述目录 ID
- 详述 \((M_f, m_f)\) 生成
- 版本 1.1
- 组织
- 读者可以推送到读者列表
- 用于公共和私有数据的 Merkle 树
- 版本 1.0: 初始修订
威胁模型和安全声明
端到端安全性:Keybase 承诺即使在服务器完全受损的情况下,也能保证文件系统数据和元数据的保密性和完整性。
我们的关键加密假设是:(1) SHA256 的弱抗碰撞性;(2) NaCl 加密库的 Go 实现 的安全性。
通过访问控制尽力而为:如果我们的服务器基础设施未受损,我们仅通过访问控制提供:
- 丢失或退役设备的前向保密性。
- 关于哪些私有文件夹有数据,哪些为空的保密性。
- 配额数据的保密性。
换句话说,能够访问 Keybase 服务器数据的对手可以: 了解谁在通过 KBFS 与谁通信;拥有我们将最终用于计费的相同使用详情;如果他们额外恢复了那些设备,将能够恢复为丢失或退役设备加密的数据。
当然,我们也是凡人,不相信我们可以无限期地抵御针对我们基础设施的协同攻击,所以我们鼓励我们的用户仅依赖我们的端到端安全声明。
此外,在服务器受损的情况下,我们不保证数据或元数据的可用性。
系统概述
兄弟密钥和子密钥。 Keybase 中的每个用户每台设备保留两个密钥对;一个密钥对用于签名,一个用于加密。私钥永远不会离开设备。签名密钥被称为"兄弟" (siblings),因为它们都同样强大。任何活动的兄弟密钥都可以配置或撤销另一个设备。子密钥由活动的兄弟密钥签名,但不能委托给其他密钥。一系列兄弟密钥中的第一个被称为"元老" (eldest) 密钥,可以被撤销而不影响其他活动的兄弟密钥。
私有个人目录 每个 keybase 用户都有一个私有个人目录,经过密钥处理,以便她的所有设备都可以读写它。
公共目录 一个或多个用户的组可以创建公共目录。公共目录中的项目由目录的一个写入者的设备之一签名;它们未加密。公共目录是发布软件或经过验证的声明的好地方。
私有组目录 最有趣的情况是,一群拥有读/写权限的人与一些拥有只读权限的人一起共享一个目录。该目录应使用认证加密来保证只有组内的人可以写入它。它应该进一步使用某种机制(目前是普通签名)来确定哪个写入者对哪个写入负责,以便用户不能把话塞进别人的嘴里。
Merkle 树森林 [未实现] Keybase 保留公共 Merkle 树用于管理:(1) 每个用户的密钥对和公共身份集合;以及 (2) 文件系统状态的进展,以便服务器不能恶意回滚到以前的状态。
密钥
元老密钥 (Eldest Key)
当用户 Alice (\(A\)) 加入时,她首先生成或导入一个密钥对。对于我们当前的用户,这是一个 PGP 密钥对,表示为 (\(P_A,p_A\))。但 PGP 密钥没有什么特别之处,我们可以自由地在未来更改格式。我们称这个密钥对为 Alice 的 元老 密钥对,因为它是潜在的许多兄弟密钥中的第一个。
每设备密钥 (Per-Device Keys)
对于她的每台设备,Alice 生成两个每设备密钥对。 签名密钥成为兄弟密钥 (sibkey),加密密钥对只是一个子密钥 (subkey)。
对于 Alice 的第 \(i\) 个设备,过程如下:
- 随机生成一个 Ed25519 密钥对,产生对 \((E^i_A, e^i_A)\)。在 Ed25519 中,私钥是一个 64 字节的字符串,公钥是一个 32 字节的(派生)字符串。
- 生成 一个适合与 NaCL 的 Box 功能(或 Go Crypto 的 box.Seal 功能)一起使用的 Curve25519 密钥对。称之为 \((M^i_A,m^i_A)\)。在 Curve25519(蒙哥马利形式)中,公钥和私钥都是 32 字节的字符串。
- 使用有效的兄弟密钥签署 \(E^i_{A}\);就像在 PGP 中一样,包含由新密钥签署的委托密钥的"反向"签名。将此 sibkey 签名推送到 Alice 的签名链中。有关更多细节,请参阅 我们的文档 关于密钥交换。
- 使用 \(e^i_{A}\) 签署 \(M^i_{A}\)。将此 subkey 签名推送到 Alice 的签名链中。
- 将 \(e^i_{A}\) 和 \(m^i_{A}\) 存储在设备 \(i\) 上
密钥 ID (kids)
Keybase 有一个 "Key ID" 的概念。在 PGP 密钥的情况下,它是公钥材料的哈希。在 ECC 密钥的情况下,它是公钥本身。我们在这里描述如何在版本 1 中构建它们:
- 对于 PGP 公钥 \(P\),计算序列化 \(s(P)\),就像计算 PGP 指纹一样。设 \(t\) 为相关密钥的一个字节类型。例如,对于 RSA,\(t = 1\);对于 DSA \(t = 17\)。有关完整列表,请参阅 RFC 4880 和 RFC 6637。
然后:
kid(\(P\)) = 0x01 || \(t\) || SHA-256(\(s(P)\)) || 0x0a
- 对于 NaCl 加密密钥,\(E\):
kid(E) = 0x01 || 0x21 || E || 0x0a
- 对于 NaCl EDDSA 密钥,\(M\):
kid(M) = 0x01 || 0x20 || M || 0x0a
KBFS 中的顶层文件夹 (TLFs)
KBFS 中的顶层文件夹 (TLF) 具有一组固定的读取者和写入者,由文件夹名称指定。TLF 中递归包含的每个文件和文件夹都与其父级具有相同的权限。这种组织方式感觉与正常的 POSIX 语义略有不同,但极大地简化了系统。
私有 TLFs
我们首先涵盖具有多个读取者和写入者的私有 TLF 的情况,因为这是最通用的。主目录是通用私有组 TLF 的一个简单子例。
为私有组 TLF 设置密钥
假设 Alice (\(A\)) 正在为 Bob (\(B\)) 和 Charlie (\(C\)) 创建一个新的 TLF。Bob 拥有读/写权限,而 Charlie 只有只读权限。Alice 在创建文件夹(称之为 \(f\))时为所有其他用户设置密钥。过程如下:
- 生成一个随机的 15 字节目录 ID,后缀为 0x16
- 生成一个每 TLF Curve25519 DH 密钥对,用于在站点的私有数据 Merkle 树中包含此文件夹的元数据;称之为 \((M_f, m_f)\)。
- 生成一个 32 字节的随机密钥(第一个版本为 0):\(s^{f,0}\) = rand(32)
- 生成一个临时 Curve25519 Diffie-Helman 密钥对。称之为 \((M_e,m_e)\)。
- 对于 \(\{A,B,C\}\) 中的每个用户 \(u\):
- 对于 \(u\) 的设备集中的每个设备 \(i\):
- 生成 \(s^{f,0,i}_{u} = \) rand(32)。 这将是密钥的服务器端部分。
- \(t^{f,0,i}_{u} = s^{f,0,i}_u \oplus s^{f,0}\)。即,将全局每 TLF 密钥与每用户每设备密钥进行异或运算,得到掩码密钥。
- \(S^{f,0,i}_{u} = (M_e, \)Box\((m_e, M^i_u, t^{f,0,i}_u))\)。 即,运行 NaCl Box 函数,使用临时私钥、用户的公钥设备密钥,以及消息 \(t^{f,0,i}_u\)。 这个新密钥 \(S^{f,0,i}_u\) 现在可以公开发布。它只能由 \(u\) 的私有设备密钥解密,并需要一些服务器辅助(通过 \(s^{f,0,i}_u\))。注意,我们将公钥 \(M_e\) 附加到 Box 的输出之前。最终,我们可能需要添加新密钥或替换现有密钥,我们将使用新的临时密钥对这样做。所以 \(M_e\) 最终可能会被替换。
- 对于 \(u\) 的设备集中的每个设备 \(i\):
- 以明文形式发布以下元数据 (\(md_c\)):
- 读取者密钥块。在这种情况下,只有 Charlie 是只读的:
readers = \([ S^{f,0,1}_{C}, S^{f,0,2}_{C}, S^{f,0,3}_{C} ]\)
-
写入者密钥块。在这种情况下是 Alice 和 Bob:
writers = \([ S^{f,0,1}_{A}, S^{f,0,2}_{A}, S^{f,0,1}_{B},S^{f,0,2}_{B} ]\)
- 公钥 \(M_f\)
- 读取者密钥块。在这种情况下,只有 Charlie 是只读的:
- 一些元数据是加密的。构造明文 \(md_{e}\) 为:
- 根 TLF 块(下面详细描述)。
- 私钥 \(m_f\)。
然后,加密计算为:SecretBox(\(s^{f,0}, md_{e}\))
注意,服务器可以看到明文的读取者和写入者块,因此可以对它们的更新进行完整性检查。例如,服务器可以检查读取者和写入者是否对应于 TLF 名称,以及在更新期间读取者和写入者是否没有被恶意删除。
同样,服务器知道最后的写入者,因为服务器应该检查传入更新的签名。
写入者显然可以更新 TLF 的所有元数据和数据。 读取者可以更改文件夹元数据中的两个字段:他们可以将新密钥推送到读取者密钥列表的末尾;他们可以将文件夹的 "rekey"(重新密钥)位翻转为 "on"。在这两种情况下,他们使用任何有效的签名兄弟密钥签署这些更改。服务器和客户端可以检查对元数据的所有更新是否都经过授权。服务器拒绝未经授权的更新,客户端忽略它们。
加密块
一旦她如上所述建立了密钥,Alice 就可以开始加密块了。 取 TLF \(f\) 中的任意明文块,如 \(b_j\)。 假设密钥版本为 0。加密步骤:
- 生成一个随机的 32 字节每块密钥 \(s_{j}\)。
- 计算 \(h_{j} = HMAC512(s^{f,0}, s_{j})\)。
- 让 \(h^{[0,31]}_{j}\) 为 \(h_{j}\) 的前 32 个字节,用作块加密密钥。
- 让 \(n\) 为 \(h_{j}\) 的接下来的 24 个字节,用作 nonce。
- 计算:\(B_j = \) SecretBox\((h^{[0,31]}_{j}, n, b_j)\)
- 对于初始发布,将 \(\{n,s_j\}\) 与 \(B_j\) 一起存储在托管存储提供商处。在未来,我们希望将 \(s_{j}\) 存储在我们托管的机器上,以获得更安全的块删除。
某种每块密钥的想法是我们希望在未来保留并扩展的。它允许我们在向 CDN 和本地缓存分发加密块时非常自由,而不用担心它们可能永远不会被丢弃。如果我们对每块密钥 \(s_j\) 应用更严格的访问控制,我们仍然保留了一些丢弃块的能力,即使在客户端密钥受损之后。
我们没有使用收敛加密或类似的任何东西,所以被使用两次的块两次加密都会不同。然而,客户端将保留每文件夹缓存,将块明文的哈希映射到加密的块 ID。所以他们不应该重新加密/重新上传他们知道是重复的块。实际上,这种本地查找可能已经足够好了,因为通常数据在被复制之前会被读取,许多块副本会命中这个缓存。出于隐私原因,我们不想允许跨顶层目录的块去重。
FS 结构
TLF 中的文件形成一个 Merkle 树,就像在其他安全分布式文件系统中一样(包括 SFSRO, SUNDR 和 Tahoe-LAFS)。 然而,KBFS 做了与 ORI 文件系统 相同的简化,取消了 iNode 风格的间接引用。因此,如果不进行更深层次的架构更改,KBFS 无法实现硬链接。
块 ID 计算为加密块及其 nonce 的 SHA-256 哈希。使用 nonce \({n}\)(它源自块的密钥)可以防止服务器与文件夹中的另一个写入者勾结,计算出密钥和明文数据的另一种组合,从而导致相同的块密文,进而允许服务器向部分读取者提供替代块(具有相同的块 ID)。通过从密钥派生 nonce,我们保证即使攻击者找到复制密文的方法,块 ID 也会不同,因此攻击会被客户端检测到。有关更多详细信息,请参阅 NCC 审计 中的 NCC-KB2018-005。
目录节点反过来是文件名到块 ID 的映射。它们被打包成块,并获得与数据块相同的加密处理。这种结构递归向上直到 TLF 根。
签署根块
私有共享 TLF 中的读取者和写入者通过认证加密知道,拥有 \(s^{f,0}\) 访问权限的人写入了 \(f\),但他们不知道是谁。Alice 可能会试图窃取 Bob 工作的功劳,或者 Bob 可能会陷害 Alice 说了些淘气的话。
解决这个问题的一个强硬方法是让 Alice 在每次更新时签署 \(f\) 的根块。但这声明太强了。如果 Eve 后来破坏了 Charlie 的密钥,她可以勒索 Alice,因为 Alice 向 Bob、Charlie 和其他所有人证明了她向 \(f\) 写入了特定内容。
我们尝试了各种成对对称 MAC 方案,以实现像 OTR 协议中的可否认性。然而,这种方案对于具有非写入读取者的文件夹不起作用。所以我们做了简单的事情,就是用写入者的每设备 EdDSA 签名密钥签署根块的哈希。在所有三种情况下都使用相同的技术:公共目录、没有非写入读取者的私有目录,以及有非写入读取者的私有目录。
公共目录
如果用户 \(u\) 用他的第 \(i\) 个设备更新 KBFS 文件夹,他必须通过签署其根块来签署他对整个文件夹状态的更改。这实际上将签署此文件夹中递归包含的所有数据和元数据。
为了签名,\(u\) 计算完整的元数据 \(md\),如上所述,只是不加密 \(md_e\)。然后他签署该块:
\(\sigma(md) = \) Sign(\(e^i_{u},md\))
Sign 函数输出签名以及用于生成它的密钥的 KID。这样,验证者就知道使用哪个密钥。
主目录 (Home Directories)
如上所述,主目录是 TLF 组目录的特例。当 Alice 为她的所有设备设置加密密钥时,她使用 4.1.1 中描述的协议,迭代她所有的每设备密钥。Alice 可以跳过 4.1.3 中描述的签名步骤,因为她不担心 "混淆作者身份" 攻击,但她仍然需要像公共目录一样签署 \(md\),以防止服务器欺骗重新密钥。
保持服务器诚实
除非我们小心,否则服务器可以选择性地保留文件系统更新,或者向两个不同的客户端提供两个不同版本的 FS。在本节中,我们描述了我们为防止此类攻击而采取的预防措施。
我们的总体方法是,服务器从所有敏感的站点数据中创建一个 Merkle 树,然后签署并公布这棵树供所有人查看。我们邀请第三方监视器检查站点 Merkle 树的进展,并检查它们是否遵守指定的加密一致性约束。客户端将它们的文件系统视图与 Merkle 树中发布的视图进行检查,以确服务器没有回滚状态或尝试分叉。
有三个独立的 Merkle 树需要考虑:(1) Keybase 核心 Merkle 树,它公布兄弟密钥、公共身份证明和 "关注者" 声明; (2) 一个公共数据 Merkle 树,捕获 KBFS 上的所有公共数据;和 (3) 一个私有数据 Merkle 树,封装 KBFS 上所有私有数据的状态。
Keybase 核心 Merkle 树
如 我们的服务器安全 文档中所述,用户签署关于他们的密钥、他们的身份和他人的身份的声明。他们将这些签名提交给单调增长的签名链,这些签名链被收集到一个全站范围的 Merkle 树中。正如我们在本文档后面描述的那样,除了单个用户之外,这些签名链最终还将覆盖组织。这些结构都存在于 KBFS 之外,应该可以在没有 KBFS 软件的情况下访问。
公共数据 Merkle 树
KBFS 上的所有公共目录都被收集到一个全站范围的 Merkle 树中。这棵树的叶子是键值对字典。键是 TLF 的 ID,值是 TLF RootMetadata 块的最新签名。此签名递归地包含:此目录的写入者密钥、此目录的根目录条目以及前一个 RootMetadata 块的哈希。
Merkle 树的内部节点是向上构建的,覆盖叶子中列出的目录 ID 的较短前缀。最终的根被签名,并定期发布,也许每小时一次。
私有数据 Merkle 树
私有数据值得与公共数据同等的待遇,但我们必须稍微小心一点,不要泄露:(1) 私有目录修改的频率;或 (2) 更糟糕的是,谁在与谁合作。简单的解决方案可能会允许对手将公共签名链中的设备添加与私有 TLF 中的更改相关联,从而关联共享成员身份。我们采取了一种相当生硬的方法,应该可以解决从服务器到公众的数据泄露问题。
当用户 Alice 创建私有 TLF \(f\) 时,她生成一个 Curve25519 密钥对 \((M_f, m_f)\)。她将 \(M_f\) 存储在文件夹的公共元数据中,将 \(m_f\) 存储在文件夹的私有元数据中。
每小时,服务器都会为整个站点的私有数据制作一个新的 Merkle 树。算法是:
- 生成一个临时 Curve25519 密钥对 \((M_S, m_s)\)
- 对于每个私有文件夹 \(f\):
- 执行加密 \(C_f \leftarrow\) Box(\(m_s,M_f,\sigma_f\)),其中 \(\sigma_f\) 是 \(f\) 元数据的最新签名。
- 制作 \(f\) 的 ID 到 \(C_f\) 的映射。
- 像在公共数据情况下一样,从这些叶子构建一个 Merkle 树,并将该树与公共临时 Curve25519 密钥 \(M_s\) 一起发布。
当 Alice 的客户端去获取 TLF \(f\) 时,她从服务器获取最新的根,以及服务器最新发布的 Merkle 树。她沿着从根到 \(f\) 的叶子的路径追踪,然后使用 \(m_f\) 解密 \(\sigma_f\)。最后,她检查当前根是否链接回 Merkle 树中发布的根。当然,如果最后一小时内有很多写入,她可能需要遍历数百或数千个链接,但服务器应该批量处理做出此决定所需的所有数据,只需几次 RPC 调用。未来的实现可能还会实现 "跳表" 风格的快进链接,以加快写入繁重期间的这一过程。
Merkle 树集成
两个 KBFS Merkle 树的根将被插入到主 Keybase Merkle 树的根块中。这样做在密钥操作和 KBFS 写入之间建立了顺序关系。反过来,这种知识允许 KBFS 客户端确定对 KBFS 的写入是在密钥被撤销之前还是之后发生的,从而确定腐败的服务器是否利用了暴露的密钥。
密钥设置、重新密钥和撤销
添加新设备
想象一下 Bob 得到了一台新设备。他现在想为它配置访问所有相关 KBFS 文件夹的权限。以下是他将采取的高级步骤:
- 密钥生成
- 密钥认证:用现有的兄弟密钥签署新密钥
- TLF 密钥设置:将密钥添加到相关的读取者和写入者块中
第一步,密钥生成,在上面已经涵盖,这里也是一样的。 密钥认证在我们的 密钥交换 文档中有涵盖。
TLF 密钥设置
现在 Bob 必须检查并为他的设备添加对他可以写入的所有加密 Keybase 目录的写入访问权限。称他的新设备为 \(n\),他的旧设备为 \(d\)。设备 \(d\) 执行以下操作:
- 生成一个临时 Curve25519 Diffie-Helman 密钥对。称之为 \((M_e,m_e)\)。
- 对于 Bob 可以读取的每个 TLF \(f\):
- 使用 \(m^{d}_{B}\) 解密 \(t^{f,0,d}_B\)
- 向服务器查询 \(s^{f,0,d}_{B}\) 并进行异或运算以恢复 \(s^{f,0}\)
- 使用发送方密钥 \(m_e\) 和接收方密钥 \(M^{n}_{B}\) 加密 \(s^{f,0}\), 后者是在设备 \(n\) 上生成的,并在之前的步骤中安全地传输到 \(d\)。
- 将 \(S^{f,0,n}_B\) 添加到 \(f\) 的写入者(或读取者)列表中,并用 \(e^{d}_B\) 签名
Bob 将 \((M_e, S^{f,0,n}_B)\) 推送到 TLF \(f\) 的读取者或写入者列表。如果他是读取者,他被允许推送到元数据中的读取者列表。如果他是写入者,他可以随意编辑 \(f\) 的元数据。
冻结设备 [未实现]
如果 Alice 丢失了设备 \(d\),要做的第一件事是通过服务器 "冻结" 对该设备的访问。任何可以作为用户建立会话的设备都可以这样做。一旦设备被冻结,服务器将拒绝接受形式为 \(s^{f,0,d}_{A}\) 的密钥半部分的请求。除了 \(d\) 之外的任何设备都可以请求解冻。
Alice 可以采取额外的(可选)步骤。她可以为丢失设备上的每个签名密钥在其签名链中签署一个 密钥冻结。其他客户端应拒绝在冻结窗口期间接受来自冻结密钥的签名。Alice 稍后可以使用下令冻结的同一密钥取消冻结。服务器在这里无法提供帮助,所以 Alice 只有在拥有另一个已配置设备的情况下才能冻结特定密钥。
退役设备(并可选地添加新设备)
要退役设备,Alice 首先应如上所述将其冻结,向她的签名链发布最终撤销声明。然后,她的客户端应遍历她具有读或写访问权限的所有 TLF,从密钥块中删除丢失的密钥,然后重新密钥。当然,她需要一个活动的密钥对才能做到这一点。 假设 \(r\) 是 Alice 丢失的设备,\(d\) 是她当前活动的设备。此外,作为此过程的结果,Alice 可以选择性地配置新设备 \(n\):
- 对于 Alice 可以写入的每个 TLF \(f\):
- 生成一个临时 Curve25519 Diffie-Helman 密钥对。称之为 \((M_e,m_e)\)。
- 删除 \(S^{f,0,r}_{A}\)
- 要求服务器删除 \(s^{f,0,r}_A\)。
- 生成一个新的 32 字节随机密钥(下一个版本为 1):\(s^{f,1}\) = rand(32)
- 对于可以访问 \(f\) 的每个用户 \(u\)
- 对于 \(u\) 拥有的每个设备 \(i\):
- 如前所述,生成 \(s^{f,1,i}_{u} = \) rand(32),作为密钥的服务器端部分
- 如前所述,加密: \(S^{f,1,i}_{u} = \)Box\((m_e, M^i_u, s^{f,1,i}_u \oplus s^{f,1})\)
- 对于 \(u\) 拥有的每个设备 \(i\):
- 如果正在配置 \(n\),生成并加密 \(S^{f,1,n}_{A}\)。
- 将重新密钥后的密钥块存储到服务器,用 \(e^d_A\) 签名
- 将 \(M_e\) 存储到服务器
- 不要费心重新加密旧块,所以保留旧的解密材料(受损密钥除外)
- 对于 Alice 可以读取的每个 TLF \(f\):
- 要求服务器删除 \(s^{f,0,r}_A\)。
- 将 TLF \(f\) 上的 rekey 标志翻转为 "on"。更新目录的下一个写入者将执行 Alice 对其可写目录使用的上述协议。
- 对 Alice 所属的任何组织重新密钥(见下文)。
元老密钥更新(或删除)[未实现]
如果 Alice 担心她所有的兄弟密钥都已受损,她应该从头开始。协议是:
- 生成一个新的元老密钥对。
- 为当前设备生成新的每设备密钥。
- 退役所有旧密钥,同时配置设备密钥。
如果只是删除她的账户,Alice 将如上所述操作,但不会生成新密钥或配置新设备。
组织
请参阅我们关于 团队 的讨论。
其他主题
文件擦除 [未实现]
服务器维护每个文件夹正在使用哪些特定于块的密钥的列表。它不知道哪个密钥对应于哪些文件,因为没有解密密钥无法重新创建 TLF 结构。
使用已配置设备
假设用户想要删除文件 \(f\)。 已配置的设备可以计算一个集合 \(I\),使得对于任何 \(i \in I\),\(b_i\) 是或曾经是 \(f\) 的一部分。然后客户端要求服务器删除 \(i \in I\) 的 \(s_i\)。只要用户可以写入父 TLF,服务器就会满足此请求。
没有已配置设备
如果用户丢失了所有已配置的设备,他可以要求服务器通过删除该 TLF 中所有块的密钥来擦除 TLF。服务器保留一个列表,因此可以执行该任务。当然,只有当用户可以写入此 TLF 时,服务器才会满足此类请求。