Apple File System的软件加密分析
AFPS(Apple File System)是 Apple 平台上使用的默认文件格式。APFS 继承自 HFS+,因此其设计的某些方面有意遵循 HFS+ 以便于历史数据的迁移。
Apple File System 支持对容器、卷和文件使用的数据结构进行加密。当一个卷被加密时,它的文件系统树和该卷中的文件内容都被加密。根据设备的能力,苹果文件系统使用硬件或软件加密:
- 硬件加密:用于支持硬件加密的设备的内部存储,包括macOS(带T2安全芯片)和iOS设备。
当使用硬件加密时,只有内核(安全隔区)可以与内部存储交互。
既支持 FDE 单密钥模式,也支持 FBE 多密钥模式。 - 软件加密:用于外部存储(U盘或外接硬盘),以及不支持硬件加密的设备(Intel CPU的Macbook)上的内部存储。
当使用软件加密时,仅支持 FDE 单密钥模式。
大多数应用程序可以使用 Apple 提供的高级接口与文件系统交互,无需自行处理加密和解密,但为了支持跨操作系统的应用(如磁盘备份恢复、Linux系统读取APFS磁盘数据),Apple 提供了Apple File System Reference,公开了技术实现细节,开发者可以自行实现加密和解密处理。
一、总体架构
APFS 在概念上分为两层,容器层(Container Layer)和文件系统层(Filesystem Layer)。
1. 容器层 - Container Layer
一个 APFS 分区有一个单独的容器,容器可以包含多个 volume(也称为 filesystem),每个卷都包含一个目录结构,用于管理 file 和 folder。

- Superblock:一个容器有多个超级块的副本,这些副本保存了容器在过去时间点的状态。Block 0 通常是最新的副本,用于在挂载过程中查找检查点。
- Checkpoint:建立崩溃保护机制,每个事务结束时将临时对象写入磁盘并存储超级块的副本
- Space manager:跟踪容器内的可用空间,并用于分配和释放存储对象和文件数据的块
- OMAP(Object Map):基于B-树管理虚拟对象标识符和事务标识符的物理地址映射
- Reaper:一种允许在跨越多个事务的时间段内删除大型对象的机制,单一容器内唯一实例
Container Superblock
1 | struct nx_superblock { |
2. 卷宗层 - Volume Layer
Volume 是真正存储数据的,每个卷宗都有一个文件系统,核心组件包括:
- Superblock:负责管理 volume 自己的一些配置信息,包含了各个组件的入口
- Root Directory:负责以 B-树 方式存储文件结构信息,如目录结构、文件元数据和文件内容
- OMAP:卷宗的大部分数据都是基于对象存储,因此每个卷宗都需要自己管理 OMAP
- SNAP META Tree:负责管理快照的元数据,也是一个 B-树
- Extentref Tree:负责管理快照扩展数据,还是一个 B-树
Volume Superblock
1 | struct apfs_superblock { |
至少有 4 个物理对象的 B-树 :ROOT DIRECTORY、EXTENT REFRENCE、SNAP METADATA、FILE EXTENT;还有一个虚拟对象的 OMAP B-树。
关于 ExtentRef Tree 的讨论
此问题已解决。ExtentRef Tree(范围参照树是)一个物理对象,就是当前正在构建的快照!
APFS 技术白皮书指出:
When a snapshot is created, the current extent-reference tree is moved to the snapshot.
A new, empty, extent-reference tree is created and its object identifier becomes the new value of this field.
当一个快照被创建时,当前的范围参照树就被移动到这个快照;同时,一个新的、空的范围参照树被创建,并将 volume superblock 的apfs_extentref_tree_oid置为这个新的 oid。
- Object Type 定义 extent-reference tree 为
OBJECT_TYPE_EXTENT_LIST_TREE - Volume Flag 的定义中,也有一个标记
APFS_FS_ALWAYS_CHECK_EXTENTREF - j_snap_metadata_val_t 的结构中,包含
extentref_tree_oid和extentref_tree_type字段 - volume superblock 的结构中,包含
extentref_tree_oid和extentref_tree_type字段
此外,APFS 白皮书还有一个勘误信息。
Corrected the discussion of object identifiers in j_snap_metadata_val_t.
The extentref_tree_oid and sblock_oid fields contain a physical object identifier, not a virtual object identifier.
二、通用组件
1. Object - 对象
APFS 的对象(Object)都有一个用于查找的唯一标识符oid,有三种不同的存储方法:
- Ephemeral object(临时对象):当一个容器被加载后,临时对象存储在内存中。临时对象通常用于一些很少更新的数据,出于性能考虑允许在内存中修改,并在 checkpoint 时被持久化存储
- Phycial Object(物理对象):存储在磁盘上的一个已知的物理块地址。物理对象被修改时,一个新副本将写入磁盘上的新位置,并携带一个不同的
oid - Virtual Object(虚拟对象):同样存储在磁盘上的一个物理块地址。虚拟对象被修改时,一个新副本也将写入磁盘上的新位置,但是
oid保持一致;通过 OMAP 可以查询虚拟对象,但必须提供一个事务标识符xid以指定您想要的时间点。
1 | /* 所有对象的 header 定义 */ |
当对象存储在磁盘上时,APFS 规定统一采用小端字节顺序,但设计思路有一些不同。容器对象以 block 为单位,并且包含填充字段使得数据长度是64的倍数,以避免内存访问对齐的性能损失;而文件系统对象以 byte 为单位,并且尽量最小化所使用的空间,因此很多 struct 定义都有__attribute__((aligned(8),packed))的编译标识。
2. B-Tree
B树(B-tree)是一种泛化的二叉搜索树(binary search tree),特点是每个节点具有两个以上的子节点,从而增加了键/值对的数量,减少定位记录时所经历的中间过程,从而加快访问速度;此外,B-树具备自平衡性,可以自动调整其结构以保持特定的平衡因子,从而保证在对数时间内进行操作,因此广泛应用于读写相对较大的数据块的存储系统。
HFS+ 是基于 B-树 设计的,APFS 也继承下来,其系统组件大量采用 B-树,例如 Filesystem、OMAP 和 snapshot 等。在 APFS 中,B-树 的节点对象称为 Node,分为根节点、中间节点和叶子节点,根节点 Root 是遍历整个树的起点。
Node 的内部存储空间分为3个部分:TOC(table of content,表空间)、key area 和 vaule area,其中表空间保存了每个键值对的位置信息,Key 和 Value 从节点内部存储区域的首端和尾端开始分别存储,两者之间是共享的自由空间,这种以 offset 的形式存储,比存储完整位置使用更少的磁盘空间。
root 节点尾部增加了统计信息
btree_info_t,为此可用存储空间少了 0x28 个字节。

1 | /* B-树的定位信息 */ |
B+树是一个变种,区别是内部节点不存储任何指向记录的指针,这些指针仅存储在叶子节点,因此节点容量更大,树也更浅
三、 OMAP
在 APFS 中,OMAP(Object Maps,对象映射)扮演两个重要角色。一是负责根据 oid(虚拟对象标识符)和 xid(事务标识符)找到磁盘物理地址,二是提供快照功能,可以立即将虚拟对象回滚到较早的时间点。
Object Map 的定义如下:
1 | struct omap_phys { |
容器和每个卷都维护自己的 OAMP,每个 OMAP 都有自己的虚拟地址空间,因此对象定义要明确归属哪一个 B-Tree !
OMAP 使用 B-树 存储映射关系,其 Key / Value 的定义如下:
1 | struct omap_key { |
有意思的是,OMAP 本身也有一个快照,定义如下:
1 | struct omap_snapshot { |
OMAP 的查询流程
使用 OMAP 访问虚拟对象时,应遵循如下流程:
- 确定对象映射的入口。
volume 的对象使用该卷宗的 OMAP,入口是apfs_superblock_t的apfs_omap_oid字段;
否则,所有其他对象应使用容器的 OMAP,入口是nx_superblock_t的nx_omap_oid字段 - 读取
omap_phys_t的om_tree_oid字段用于定位对象映射的 B-树 - 在 B-树 中搜索
ok_oid== 期望的oid,而且ok_xid<= 期望的xid的 key。如果有多个 key 满足要求,则使用具有最大xid的 key - 使用 Node 节点的 TOC,读取这个 key 对应的 value,其中包含物理地址
ov_addr和ov_size - 从磁盘的物理地址获得对象数据
四、File System
每个 APFS 卷宗(Volume)都有一个文件系统(Filesystem)。
与其他 APFS 对象(Object)不同,文件系统对象由一个或多个文件系统记录(Record)组成,这些记录存储在 Volume 的 FileSystem Tree 上,每条记录都存储有关 file 或 directory 的特定信息。
所有文件系统对象是基于一个专用的 B-Tree 来组织的,并具有以下特点:
- 文件系统树是虚拟的,其每个节点都是基于 Volume 的 OMAP 映射出来的虚拟对象。这意味着,检索文件系统树必须依赖 OMAP 定位以查找每个节点
- 文件系统树支持快照功能,即充分利用 OMAP 的快照功能将其状态恢复到以前的时间点,Time Machine 的增量备份功能就是一个典型应用
- 可以选择对文件系统的节点进行加密,不仅可以加密文件内容,还可以加密文件元数据
- 文件系统树存储了一组异构记录,也即是说,多种类型的键和值都存储在同一树中
文件系统树的每个节点都有唯一标识j_key。
1 |
|
为了充分利用内存空间,前 4 个字节是记录(Record)的类型定义,包括:
1 | typedef enum { |
1. 文件和目录
文件系统树的每个节点都必须有 inode 记录,第一条记录就是 Root Directory。
INODE 记录
inode 负责管理最核心的元数据,例如时间戳、类型、所有者和权限等,都是固定长度的标准格式,其他信息将被存入 inode 的扩展字段,或者其他类型的 Record 中
1 | /* inode 数据结构 */ |
Extended Fields(扩展字段)
inode 记录支持有限的扩展字段(Extended Fields),入口就在uint8_t xfield[],其类型定义包括:
1 |
inode 记录的扩展字段
INO_EXT_TYPE_NAME,存储的并不是该节点的文件名,而是在该节点是一个硬链接的场景下,其对应的源目标文件名
DIR_REC 记录
当我们新建一个文件目录时,当然必须创建一个 inode 记录,此时它是一个空目录。
然后,我们继续在该目录下新建一个文件时,需要新增 2 条记录,一是新文件的 inode 记录,二是 DIR_REC 记录,用于该目录管理其子对象,也就是说,一个目录下有几个文件或子目录,就有几条 DIR_REC 记录。
1 | struct j_drec_hashed_key { |
- 找了很久 filename 的存储方式,最后发现不在 File 的 inode 记录中,而是藏在归属目录的 DIR_REC 记录中!因为操作系统处理时只需要唯一标识符
j_key,其实文件名只是提供用户查询显示的 - 早期版本的 APFS 使用
j_drec_key,后来升级为j_drec_hashed_key,区别就是增加了文件名的哈希值,这个变化非常有利于提高长文件名的搜索效率,即不用逐一比较字符串,而是直接比较哈希值即可 - DIR_REC 记录同样支持扩展字段,其定义与 inode 记录保持一致
2. 数据流
类似 filename 的短数据可以存储在 metadata 之中,但是文件内容和一些属性值的数据量不固定而且可能很大,基于性能考虑,APFS 将这些数据存储在 Data Stream 数据流之中。
DSTREAM 记录
每个文件都有一个默认数据流,存储我们通常所说的文件内容。
还记得 inode 记录中的private_id吗?这就是每个文件的默认数据流(Data Stream)。
1 | struct j_dstream_id_key { |
默认数据流的统计信息保存在 inode 记录的APFS_TYPE_EXTENT扩展字段。
数据流的占用空间和分配空间可能不一致,例如文件内容没有完全填满最后一个块,此外,由于 AFPS 支持稀疏分配,重复出现的零字节可能不会实际占用存储空间。
对于使用软件加密的 volume,default_crypto_id字段的值始终为CRYPTO_SW_ID=4。
1 | struct j_dstream { |
XATTR 记录
古老的 HFS+ 提供了文件系统的fork功能,最初设计是为了保存 GUI 使用的非编译数据,例如文件图标、缩略图和应用程序相关的菜单提示信息等,这个功能 AFPS 继承下来,并基于APFS_TYPE_XATTR记录实现。
微软的 NTFS 也有类似功能,称为 ADS(Alternate data stream,替代数据流)
1 | struct j_xattr_key { |
3. 密钥管理
早期的 HFS+ 采用 AES-CBC 工作模式,存在明文和密文不等长、需要额外存储初始变量等诸多问题,后续改为 AES-XTS 磁盘加密模式,APFS 也是如此,这就需要妥善保管好 Ciper 分组密钥和 Tweak 可调整密钥。
CRYPTO_STATE 记录
请注意!本文讨论的是软件加密,也就是单一密钥的 FDE,并不需要管理每个文件的 AES-XTS的主密钥,但 APFS 的设计目标是原生支持 FBE(当然前提是采用硬件加密),因此数据结构的设计目标就是每个文件都有独立的 per-file key,就保存在APFS_TYPE_CRYPTO_STATE记录。
1 | struct j_crypto_key { |
进一步,我们来分析wrapped_crypto_state_t的数据结构,可以看到 per-file key 始终是以包裹状态存储的,需要通过安全隔区保存的 Class Key 来解密。
1 | /* 持久化存储 per-file key,包含:版本信息 + warpped key data */ |
FILE_EXTENT 记录
还记得 HFS+ 是如何实现 HBE 的吗?就是将per-file key保存在文件扩展信息中。APFS 继承了这种方式,将 Tweak key 保存在APFS_TYPE_FILE_EXTENT记录中。
需要注意的是,由于APFS 支持 COW(Copy On Write,写入时拷贝),可以实现零损耗的大文件快速克隆。但是,如果一个文件被 Clone 以后,每个副本都会获得一个新密钥以接受后续可能的数据写入,久而久之,一个文件可能会由不同的范围(或片段)组成,每个映射到不同的密钥,为此可能需要多个AFPS_FILE_EXTENT记录。
此外,由于 Tweak Key 属于密钥白化技术,不允许重复使用,但可以被公开,因此 crypto_id 可以明文存储。
1 | struct j_file_extent_key { |
关于 crypto_id 的讨论
- 该字段的默认值是此区段所属的数据流的
j_dstream_t的default_crypto_id字段的值 - 如果在 Volume 设置了
APFS_FS_ONEKEY标志,即单一密钥模式,该字段存储 AES-XTS 的 Tweak key - 否则,该字段存储数据与
j_crypto_key_t记录的obj_id字段保持一致,表明将采用 FBE 模式,此时这里不需要存储 Tweak key
根据 Apple 安全隔区白皮书的说明:
在搭载 A14 和 M1 的设备上, 加密在 XTS 模式中使用 AES-256, 其中 256 位文件独有密钥通过密钥派生功能 (NIST Special Publication 800-108) 派生出一个 256 位 tweak 密钥和一个 256 位 cipher 密钥。
采用 A9 到 A13、 S5 和 S6 的每一代硬件在 XTS 模式中使用 AES-128, 其中 256 位文件独有密钥会被拆分, 以提供一个 128 位 tweak 密钥和一个 128 位 cipher 密钥。
五、Keybag
APFS 的设计原生支持加密,不再需要 HFS+ 上叠加的 CoreStorge 虚拟存储层,但具体加密方式取决于硬件设备的功能。硬件加密用于具备 Secure Encalve 安全隔区的内部存储设备,软件加密用于不支持硬件加密的外部和内部存储设备。需要注意的是,当使用硬件加密时,数据无法在任何其他设备上解密,安全芯片必须代理所有解密操作。
对于 macOS,APFS 使用单一密钥 VEK(Volume Encryption Key,卷宗加密密钥)访问宗卷上的加密内容(也就是所有文件的 AES-XTS 分组密钥),VEK 以 Warpped 状态存储在磁盘,封装在多层加密中。
KEK(Key Encryption Key,密钥加密密钥)是用于打开 VEK 的包裹密钥,以加密形式存储在磁盘上。每个 Volume 都有自己的 KEK ,而且还有多个副本以提供不同场景下的用户访问,这些副本都使用不同的密钥进行加密(包装),包括:
- User Password:用户输入登录密码
- Personal recovery key:个人备份密钥,该密钥在驱动器格式化时生成,并由用户纸质保存
- Institutional recovery key:授权的外部机构恢复密钥
- iCloud recovery key:客户与 Apple 技术支持配合使用

1. Keybag 的存储方式
早期的 iOS 将密钥包存储在一个普通的数据文件中(/private/var/keybags/systembag.kb),虽然做了很复杂的加密处理,但由于缺少防重放机制,无法有效抵御暴力破解。APFS 是基于文件系统的全新设计,密钥包不再依赖于数据文件,而是被设计为一个特殊的对象(Object)。
Container Keybag 的入口在其超级块nx_superblock_t的prangnx_keylocker字段,数据类型是prange_t,保存着容器密钥包的物理地址,其数据结构是:
1 | /* keybag 的头部 */ |
对于 Container Keybag,容器包含了几个加密的 Volume,就有几个 entry:
- 每个 entry 的
ke_uuid存储了这个 volume 的 UUID,也是后续用于解封 volume keybag 的钥匙 - 每个 entry 的
ke_keydata存储了这个 volume keybag 的物理地址
对于 Volume Keybag ,卷宗包含了几个 User,就有几个 entry
- 每个 entry 的
ke_uuid存储了这个 User 的 UUID - 每个 entry 的
ke_keydata存储了这个 User 的 wrapped KEK
2. VEK 的解封流程
要完成数据文件的解密,是一个漫长而复杂的流程。
Step 1: 解封 Container Keybag
- 读取容器超级块的
nx_keylocker字段,找到容器密钥包的物理位置。然而你不能直接看到数据,因为密钥包的内容被加密了。 - 执行解密算法RFC 3394 - AES密钥包裹算法,密钥就是该容器的 UUID,即容器超级块的
nx_uuid字段。
现在,你就能看到容器密钥包的数据内容了。
此处JOE 的参考文档和 APFS 官方文档不一致
Step 2: 找到 wrapped VEK
分析容器密钥包,找到一个标记为KB_TAG_VOLUME_KEY的 entry,其ke_keydata字段就是 wrapped VEK。
先保存下来,后面还要用。
Step 3: 解封 Volume Keybag
- 继续分析容器密钥包,找出标记为
KB_TAG_VOLUME_KEY的 entry,可能有多个分别对应不同的卷宗.
每个 entry 的ke_uuid字段是 volume UUID,ke_keydata字段是 volume keybag 的物理地址 - 根据 Volume keybag 的物理地址读取数据,然而你还是看不到内容,因为又被加密了。
仍然执行解密算法 RFC 3394,密钥是该 volume 的 UUID - 标记为
KB_TAG_VOLUME_PASSPHRASE_HINT的 entry,其ke_keydata存储人类可读的密码提示信息
现在,你就能看到卷宗密钥包的数据内容了,示例如下:
| 名字 | UUID |
|---|---|
| INSTITUTIONAL_RECOVERY_UUID | {C064EBC6-0000-11AA-AA11-00306543ECAC} |
| INSTITUTIONAL_USER_UUID | {2FA31400-BAFF-4DE7-AE2A-C3AA6E1FD340} |
| PERSIONAL_RECOVERY_UUID | {EBC6C064-0000-11AA-AA11-00306543ECAC} |
| ICLOUD_RECOVERY_UUID | {64C0C6EB-0000-11AA-AA11-00306543ECAC} |
| ICLOUD_USER_UUID | {EC1C2AD9-B618-4ED6-BD8D-50F361C27507} |
Step 4: 找到 wrapped KEK
分析卷宗密钥包,包含了多个 entry,分别对应不同的 User,也是不同的业务场景。
以用户密码方式为例,你需要找出一条 entry,其ke_uuid是某个User Open Directory UUID,而且标记为KB_TAG_VOLUME_UNLOCK_RECORDS,其ke_keydata字段就是这个场景的 wrapped KEK。
Step 5: 解封 KEK
KEK 是基于 DER 编码的数据块,其结构为:
1 | KEKBLOB ::= SEQUENCE { |
数据块的头部有一个 基于 HMAC-SHA256 算法的校验值,算法是:hmac_key := SHA256("\x01\x16\x20\x17\x15\x05" + salt)
Flags 标记了 KEK 的包裹方式,格式如下:
| Name | Value | Description |
|---|---|---|
| KEK_FLAG_CORESTORAGE | 0x00010000’0000000000 | Key is a legacy CoreStorage KEK |
| KEK_FLAG_HARDWARE | 0x00020000’0000000000 | Key is hardware encrypted |
解密算法是 PBKDF2 和 RFC 3394,你必须知道 User Password 并计算出 Passcode Key,才能正确解封 wrapped KEK,算法是:
1 | // Calculate size of wrapping key (in bytes) |
Step 6: 解封 VEK
KEK 也是基于 DER 编码的数据块,结构更简单:
1 | VEKBLOB ::= SEQUENCE { |
解密算法就是简单的 RFC 3394。vek = rfc3394_unwrap(vek, wrapped_key)
至此,我们终于获得了核心密钥 VEK !!!
3. 文件解密的流程
APFS 采用 XTS-AES-128 磁盘加密模式,该密码使用 256 位分组密钥和 64 位调整值。此调整值取决于位置。它允许对相同的明文进行加密并存储在磁盘上的不同位置,并且在使用相同的 AES 密钥时具有截然不同的密文。每 512 字节的加密数据使用基于块初始存储的容器偏移量的调整。
要顺利完成文件内容解密,前提条件包括:
- 准确解析文件系统的B-Tree
- 解析密钥包,找到分组密钥 Ciper Key,也即是 VEK
- 找到文件密钥,也就是 Tweak key
文件元数据的解密
卷的对象映射永远不会加密,但其引用的虚拟对象可能会加密,就像加密卷上的 FS 树节点一样。
1 | typedef struct omap_val { |
如果ov_flags设置了OMAP_VAL_ENCRYPTED标志位,则位于ov_paddr的虚拟对象已经被加密,
对于第一个512字节的数据块,可以基于物理位置确定 Tweak value,后续512字节的数据块则依次递增。
uint64_t tweak0 = (ov_paddr * block_size) / 512;
文件内容的解密
- 基于 Volume Superblock 的
apfs_root_tree_oid字段找到 Root Directory 的对象映射 - 使用 VEK 作为AES-XTS 主密钥,解封并访问文件系统树
- 查找加密文件的文件范围记录
APFS_TYPE_FILE_EXTENT - 查找加密状态记录
APFS_TYPE_CRYPTO_STATE,其标识符等于j_file_extent_val.crypto_id - 使用 VEK 作为主密钥,
Crypto_id的值作为 Tweak key,执行 AES-XTS 解密相应的数据块
TODO: 第四步来自 APFS白皮书,似乎 FDE 模式不需要?
六、Snapshot
快照(Snapshot)是现代文件系统的重要功能,可以在给定时间点获得一个稳定的、只读的文件系统副本,例如用于硬盘的增量备份。快照的设计目标是可以快速而且低成本的创建,但付出的代价是删除快照需要更多的工作。
1. Snapshot Metadata Record
快照也是一个基于 B-树 的应用,鉴于快照的数据量可能较大,因此又建立了一个名为Extent Reference的 B-树 用于保存实际的内容数据,而在 snapshot 记录中仅保存其元数据 metadata ,定义如下:
1 | struct j_snap_metadata_key { |
2. Snapshot Name Records
快照名称记录用于将快照名称映射到其事务标识符。
1 | struct j_snap_name_key { |
3. Snapshot Extended Reference Metadata Object
每个快照都有一个虚拟对象,用于保存快照扩展信息的元数据,其 oid 保存在该卷宗超级块的apfs_snap_meta_ext_oid字段中,映射关系记录在该卷宗的 OMAP 上。快照的虚拟对象有多个版本,其事务标识符 xid 对应每个版本。
Each snapshot has a virtual Snapshot Extended Metadata Object in the volume’s Object Map. The virtual object identifier of this object is stored in the apfs_snap_meta_ext_oid field of the Volume Superblock. There are multiple versions of this object whose transaction identifiers correspond to each snapshot.
1 | struct snap_meta_ext_obj_phys { |
七、遗留问题
1. AFPS 白皮书中介绍的 media_keybag 是什么?
1 | struct media_keybag { |
2020年6月,增加定义:#define OBJECT_TYPE_MEDIA_KEYBAG 'mkey'
APFS 的描述:A keybag, wrapped up as a container-layer object.
nx_mkb_locker : Wrapped media key.
KB_TAG_WRAPPING_M_KEY:
The key data stores a key thatʼs used to wrap a media key.
初步分析,media key 应该是 2020年 Apple 版本升级的产物,负责封装数据宗卷上的元数据。
Apple 安全白皮书介绍:
When deleting a volume, its volume encryption key is securely deleted by the Secure Enclave.
This helps prevent future access with this key even by the Secure Enclave.
In addition, all volume encryption keys are wrapped with a media key.
The media key doesn’t provide additional confidentiality of data; instead, it’s designed to enable swift and secure deletion of data because without it decryption is impossible.
On a Mac with Apple silicon and those with the T2 chip, the media key is guaranteed to be erased by the Secure Enclave supported technology—for example by remote MDM commands.
Erasing the media key in this manner renders the volume cryptographically inaccessible.
media key Part of the encryption key hierarchy that helps provide for a secure and instant wipe.
In iOS, iPadOS, tvOS, and watchOS, the media key wraps the metadata on the data volume (and thus without it access to all per-file keys is impossible, rendering files protected with Data Protection inaccessible).
In macOS, the media key wraps the keying material, all metadata, and data on the FileVault protected volume. In either case, wipe of the media key renders encrypted data inaccessible.
附录一:一些重要的类型定义
1. Object Type 的定义
1 |
2. Object Flag 的定义
区分存储方式,即:虚拟对象、物理对象、或临时对象
1 |
3. Volume Flag 的定义
1 |
4. Volume Role 的定义
1 |
|
参考文献
- APFS 深度分析系列 - Dr. Joe T.Sylve
- APFS 技术白皮书 - ERNW.de
- ApFS Structure - NTFS.com
- APFS 数据结构参考图
- Fork (file system) - Wiki
- 谈谈 Mac OS 的文件系统