静态数据加密

来自 Arch Linux 中文维基

本文讨论静态数据加密软件,该软件即时加密/解密写入/读取块设备磁盘分区或目录的数据。块设备的示例是硬盘驱动器、闪存驱动器和 DVD。

静态数据加密仅应被视为操作系统现有安全机制的附属品——专注于保护物理访问,同时依赖系统的其他部分提供网络安全和基于用户的访问控制等功能。

对于全盘加密 (Full-disk encryption,FDE),参阅Dm-crypt/加密整个系统

为什么要使用加密?[编辑 | 编辑源代码]

静态数据加密确保文件始终以加密的形式存储在磁盘上。这些文件只有在系统运行并由受信任的用户解锁时才以可读形式提供给操作系统和应用程序(使用中的数据传输中的数据)。未经授权的人直接查看磁盘内容,只会发现混乱的随机数据,而不是实际的文件。

例如,这可以防止未经授权的数据查看,当电脑或硬盘:

  • 处于当你离开时不受信任的人可能获得使用机会的场所
  • 丢失或被盗,如笔记本电脑、上网本或外部存储设备
  • 在维修店里
  • 淘汰后被丢弃

此外,静态数据加密还可用于增加一些安全性,以防止未经授权的篡改操作系统的尝试——例如,可以获得物理访问权限的攻击者趁你不在的时候安装键盘记录程序(keyloggers)或特洛伊木马(Trojan)。

警告: 静态数据加密并不能保护你的数据免受所有威胁。

你仍然容易受到以下威胁:

  • 攻击者可以在系统运行时以及你已经解锁并挂载磁盘的加密部分后闯入你的系统(例如通过Internet)。
  • 如果可获得对计算机的物理访问权限的攻击者有资源,那么他们能够在电脑运行时(即使你使用了屏幕锁),或在电脑运行不久,执行冷启动攻击
  • 一个政府实体,它不仅拥有轻松实施上述攻击的资源,而且还可能使用各种胁迫技术简单地迫使你放弃密钥/密码。如果执法机构怀疑你可能隐藏了一些他们感兴趣的东西,那么执法机构这样做可能是合法的。
  • 橡胶软管密码分析。另请参阅XKCD #538

需要一个非常强大的磁盘加密设置(例如,具有真实性检查和无明文引导分区的完整系统加密)才能有机会抵御能够在你使用系统之前篡改你的系统的专业攻击者。即便如此,它也无法阻止所有类型的篡改(例如硬件键盘记录器)。最好的补救措施可能是基于硬件的全盘加密可信计算

警告: 静态数据加密也不会保护你免受某人简单地擦除你的磁盘的侵害。 建议定期备份以确保数据安全。

系统数据加密[编辑 | 编辑源代码]

虽然仅加密用户数据本身(通常位于家目录中,或在数据 DVD 等可移动媒体上)是最简单且侵入性最小的方法,但是它有一些明显的缺点。 在现代计算机系统中,有许多后台进程可能会在硬盘驱动器的非加密区域中缓存和存储有关用户数据或部分数据本身的信息,例如:

  • 交换分区(swap)
  • /tmp(用户应用程序创建的临时文件)
    • (可能的补救措施:避免此类应用程序;在ramdisk内挂载/tmp
  • /var (日志文件和数据库等;例如,mlocate将所有文件名的索引存储在/var/lib/mlocate/mlocate.db中)

解决办法就是对系统和用户数据都进行加密,阻止未经授权的对可能被系统缓存的隐私数据的物理访问。不过,这样也带来了一个缺点——必须在启动时对磁盘的加密部分进行解锁。系统数据加密的另一个好处是,它给具有物理访问权限的人安装诸如键盘记录器或 rootkits 之类的恶意软件带来了麻烦。

可用方法[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: Ext4ZFS,可能还有其他的文件系统,提供(原生(native))加密。 (在 Talk:静态数据加密 中讨论)

所有静态数据加密方法都是这样操作的:虽然磁盘实际存放的是加密数据,但只要加密容器(即磁盘中存放加密数据的逻辑部分)被“解锁”并被挂载,那么操作系统和应用程序就会把它 "看成 "相应的普通的可读数据。

为此,用户需要提供一些“机密信息”(通常采用密钥文件和/或密码短语的形式),从这些信息中可以派生出实际的加密密钥(并在会话期间存储在内核密钥环中)。

如果你对这种操作完全不熟悉,还请阅读下文#加密是怎么运作的的部分。

可用的静态数据加密方法可以按其操作层分为两种类型:

栈式文件系统加密[编辑 | 编辑源代码]

作为堆叠在已有文件系统之上的层而实现的堆栈式文件系统加密方案,使所有写入启用加密的文件夹的文件在底层文件系统将其写入磁盘之前就被即时加密,并在文件系统从磁盘读取它们时被解密。这样,文件以加密的形式存储在宿主文件系统中(意味着它们的内容,通常还有它们的文件/文件夹名称,都被长度大致相同的随机数据所取代),但除此之外,它们仍然以正常的文件/符号链接/硬链接等形式存在于该文件系统中,如同没有加密一样。

它的实现方式是,为了解锁宿主文件系统中存储原始加密文件的文件夹(“下层目录”),它被挂载(使用一个特殊的堆叠的伪文件系统)到它本身或可选的不同位置(“上层目录”),然后相同的文件以可读的形式出现——直到它再次被卸载,或系统被关闭。

此类别中可用的加密方案是eCryptfsEncFS

云存储优化[编辑 | 编辑源代码]

如果你正在部署堆栈式文件系统加密,以实现与第三方控制的位置(如云存储服务)的零知识同步(zero-knowledge synchronization),你可能需要考虑替代 eCryptfs 和 EncFS 的方案,因为他们并不是为了通过 Internet 传输文件这一目的而优化的。有一些解决方案是为了这个目的而设计的:

请注意,一些云存储服务直接通过他们自己的客户端应用程序提供零知识加密(zero-knowledge encryption)。

块设备加密[编辑 | 编辑源代码]

另者,块设备加密(block device encryption)方法操作于文件系统层之下,确保写入某个块设备(即整个磁盘、分区或充当回环设备的文件)的所有内容都是加密的。这意味着当块设备处于脱机(offline)状态时,它的整个内容看起来就像一大团随机数据(a large blob of random data),无法确定它包含什么样的文件系统和数据。通过一种特殊方式将受保护的容器(在本例中为块设备)挂载到任意位置,再次访问数据。

Arch Linux 中提供了以下几种“块设备加密”方案:

loop-AES
loop-AES 是 cryptoloop 的继任者,是一种安全、快速的系统加密解决方案。然而,loop-AES 被认为不如其他选择易用(less user-friendly),因为它需要非标准内核支持(non-standard kernel support)。
dm-crypt
dm-crypt 是由 Linux 内核提供的标准设备映射器加密(standard device-mapper encryption)功能。喜欢全面掌握分区及密钥管理的各个方面的人直接用它就行了。对 dm-crypt 的管理是通过 cryptsetup 用户空间实用程序完成的。它可用于以下类型的块设备加密:LUKS(默认)plain,并且具备有限的用于 loopAESTruecrypt 设备的功能。
  • 默认情况下使用的 LUKS 是一个额外的便利层,它将 dm-crypt 所需的所有设置信息存储在磁盘本身上,并抽象分区和密钥管理,以提高易用性和加密安全性。
  • plain 模式下的 dm-crypt,作为原始的内核功能,并没有采用便利层。用它来应用(与 LUKS 类型)同样的加密强度是比较困难的。这样做时,会产生更长的密码或密钥文件(二者被统称为 keys)。但是,它具有其他优点,描述于下文#块设备加密与堆栈式文件系统加密的对比[损坏的链接:无效的章节]之中。
TrueCrypt/VeraCrypt
一种可移植(portable)格式,支持整个磁盘/分区或文件容器的加密,兼容所有主流操作系统。对 TrueCrypt 的开发于2014年5月被其开发者停止。其分支 VeraCrypt 于2016年被审计。

关于选定的操作层的实际含义,参阅下文#块设备加密与堆栈式文件系统加密的对比[损坏的链接:无效的章节],以及对 eCryptfs的总体描述。参阅Category:Encryption,了解下表比较的方法的可用内容,以及未包括在表中的其他工具。

块设备加密与堆栈式文件系统加密的对比[编辑 | 编辑源代码]

块设备加密 堆栈式文件系统加密
加密 整个块设备 文件
加密数据的容器可能是…… 作为回环设备的磁盘或磁盘分区/文件 现有文件系统中的目录
与文件系统的关系 在文件系统层下运行:不关心加密块设备的内容是文件系统、分区表、LVM 设置还是其他任何内容 向现有文件系统添加一个附加层,以在文件被写入/读取时自动加密/解密文件
加密文件元数据(文件数、目录结构、文件大小、权限、最后修改时间等)
(使用 'discard' 可能会暴露文件的大小)
部分
(只有名称被加密,所有其他元数据都是可见的)
可被用于自定义加密整个硬盘驱动器(包括分区表)
可被用于加密交换(swap)空间
可被用作加密数据容器而无需预分配固定大小的空间
(使用 'discard' 可能允许少有分配的容器,代价是暴露文件的大小)
可被用于保护没有块设备访问的现有文件系统,例如NFS 或 Samba 共享、云存储等 1
允许对加密文件进行基于文件的脱机备份
  1. 额……这些文件系统中的单个文件可以用作容器(虚拟环回设备!)但实际上,人们就不会再使用文件系统(及其提供的功能)了

比较表[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: 填写空白处。为复选标记/交叉点添加来源。(salt)、密钥槽替代(key-slot diffusion)以及 密钥擦除(key scrubbing)分别是什么? (在 Talk:静态数据加密 中讨论)

“dm-crypt +/- LUKS” 一栏表示 dm-crypt 在 LUKS("+")和 plain("-")加密模式下的功能。如果一个特定的功能需要使用LUKS,这将以“(用 LUKS)”表示。同样,“(不用 LUKS)”表示使用 LUKS 对实现该功能起反作用,应该使用 plain 模式。

概要(Summary) Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS eCryptfs EncFS gocryptfs fscrypt
加密类型 块设备 块设备 块设备 原生文件系统或块设备 堆栈式文件系统 堆栈式文件系统 堆栈式文件系统 原生文件系统
说明(Note) 存在时间最长的;可能是最快的;适用于遗留系统(legacy systems) Linux 上块设备加密的事实标准;非常灵活 TrueCrypt 的受维护分支,支持 TrueCrypt 和 VeraCrypt 卷(volume) 加密功能相对较新(2019 年);由 ZVOL 提供被加密的块设备 比EncFS稍快;可在系统之间转移的单个加密文件 最易用的一种;支持非 root 管理 有抱负的 EncFS 的继任者 默认用于 Chrome OS 和 Android 加密
在 Arch Linux 中的可用性 需要手动编译、定制内核 内核模块:已随默认内核一起提供;工具:device-mappercryptsetup veracrypt ZFS#安装 内核模块:已随默认内核一起提供;工具:ecryptfs-utils encfs gocryptfs 内核模块:已随默认内核一起提供;工具:fscrypt
许可协议(License) GPL GPL Apache License 2.0,一些部分受 TrueCrypt License v3.0 约束 CDDL GPL GPL MIT GPL (内核)、Apache 2.0 (用户空间工具)
加密实现于…… 内核空间 内核空间 内核空间 内核空间 内核空间 用户空间(FUSE 用户空间(FUSE 内核空间
加密元数据存于…… 用 LUKS:LUKS 标头 (已解密的)设备之首/尾 (格式规范) DSL(数据集和快照层;报告(talk)/幻灯片(slides)) 每个加密文件的标头 每个 EncFs 容器顶层的控制文件 每个文件系统根目录下的 .fscrypt 目录
封装的加密密钥存于…… 用 LUKS:LUKS 标头 (已解密的)设备之首/尾 (格式规范) DSL(数据集和快照层;报告(talk)/幻灯片(slides)) 密钥文件可被存储在任何地方 密钥文件可被存储在任何地方

[1][2]

每个文件系统根目录下的 .fscrypt 目录
可用功能 Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS eCryptfs EncFS gocryptfs fscrypt
Non-root users can create/destroy containers for encrypted data 受限
提供图形用户界面(GUI)

可选的

支持登录时自动挂载

利用 systemd 和 /etc/crypttab

支持在不活动的情况下自动卸载 ?
[3]
安全特性 Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS eCryptfs EncFS gocryptfs fscrypt
支持的密码(cipher) AES AES、Anubis、CAST5/6、Twofish、Serpent、Camellia、Blowfish …… (内核 Crypto API 提供的每一种密码(cipher)) AES、Twofish、Serpent、Camellia、Kuznyechik AES AES、Blowfish、Twofish... AES、Blowfish、Twofish,以及其余所有在此系统上可用的密码(cipher) AES AES、ChaCha12
完整性(校验)(Integrity) 可选于 LUKS2 CCM、GCM 无(默认模式)
HMAC (paranoia 模式)
GCM
支持加盐
(用 LUKS)
支持级联多个密码(Support for cascading multiple ciphers) 不在一个设备中,但块设备可以级联

AES-Twofish、AES-Twofish-Serpent、Serpent-AES、Serpent-Twofish-AES、Twofish-Serpent

支持密钥槽替代(key-slot diffusion)
(用 LUKS)
保护密钥不被擦除
(不用 LUKS)
支持为相同的加密数据设置多个(独立可撤销的)密钥
(用 LUKS)
性能特点 Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS eCryptfs EncFS gocryptfs fscrypt
多线程支持
[4]
硬件加速加密(Hardware-accelerated encryption)支持
[5]
块设备加密特有的 Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS
支持(手动)就地调整加密块设备的大小
堆栈式文件系统加密特有的 ZFS eCryptfs EncFS gocryptfs fscrypt
支持的文件系统 ZFS ext3、ext4、xfs (附有警告,with caveats)、jfs、nfs …… ext3、ext4、xfs (附有警告,with caveats)、jfs、nfs、cifs ……

[6]

任何 ext4、F2FS、UBIFS
能加密文件名
zfs(8)
加密文件名
[7]
稀疏文件的优化处理(Optimized handling of sparse files)
兼容性 & 流行度 Loop-AES dm-crypt +/- LUKS VeraCrypt ZFS eCryptfs EncFS gocryptfs fscrypt
支持的 Linux 内核版本 2.0 或更新 CBC-mode 自 2.6.4 以来,ESSIV 2.6.10,LRW 2.6.20,XTS 2.6.24 2.6.32 或更新(截至 0.8.3) 2.4 或更新 4.1 或更新
也可以从Windows 访问加密数据
OpenZFS on Windows (仓库)
否 (需要管理员权限) 是 (cppcryptfs 端口,cppcryptfs port)
也可以从 Mac OS X 访问加密数据
OpenZFS on OS X (仓库)

[8]
是 (测试版质量,beta quality)
也可以从 FreeBSD 访问加密数据
ZFS on FreeBSD (内置,native; 仓库)

[9]
被用于 Debian/Ubuntu安装程序(系统加密)
Fedora 安装程序
Android、Chrome OS

准备[编辑 | 编辑源代码]

选择设置[编辑 | 编辑源代码]

根据你的目的(请阅读上文#为什么要使用加密?)及系统参数选取合适的加密设置。

此外,你需要回答下列问题:

你想抵御什么样的“攻击者”?
  • 在你的系统被关闭、被盗等情形下窥探你的磁盘的普通用户
  • 可在你使用你的系统前后反复获得读写权限的专业密码分析员
  • 任何介于这两者之间的人
你想加密什么?
  • 仅用户数据
  • 用户数据和系统数据
  • 仅机密数据,也就是你的数据的子集
交换分区(swap)、/tmp 等,应如何处理?
  • 禁用或挂载为 ramdisk
  • 被加密的交换分区
    • 将交换文件作为全盘加密的一部分
    • 单独加密交换分区
应如何解锁磁盘的加密部分?
  • 使用密码
    • 同账户登录密码
    • 不同于账户登录密码
  • 使用密钥文件(例如将其置于随身携带的或保存在安全地方的U盘上)
  • 二者兼有
何时解锁磁盘的加密部分?
  • 引导前
  • 引导过程中
  • 登录账户时
  • 按需手动解锁(账户登录后)
应如何满足多用户需求?
  • 不需要
  • 使用每个用户都知道的共享密码(或密钥文件)
  • 用于磁盘的同一加密部分的,被独立分发的、可撤销的密码(或密钥文件)
  • 为不同的用户分配磁盘的加密部分

接下来你可以做出所需的技术选择(参阅上文#可用方法,以及下文#加密是怎么运作的),关于:

  • 块设备加密与堆栈式文件系统加密的对比
  • 密钥管理
  • 密码及操作模式
  • 元数据存储
  • “下层目录”的位置(在堆栈式文件系统加密的情况下)

示例[编辑 | 编辑源代码]

在实践中,结果可能是这样的:

示例 1
仅利用用户的家目录(home directory)里的一个被用 EncFS 加密的路径名为 ~/Private 的虚拟文件夹的简单的(内部硬盘驱动器)用户数据加密
  • 被 on-disk 存储的文件的加密版本位于 ~/.Private(encrypted versions of the files stored on-disk in ~/.Private
  • 使用专用密码按需解锁
示例 2
部分系统加密,每个用户的主目录用 ECryptfs 加密
  • 使用账户登录密码,在各个用户登录时被解锁
  • 具有用LUKS的dm-crypt加密的 swap/tmp 分区,使用每个会话自动生成的一次性密钥
  • 禁止 slocate(及类似的应用程序)索引或缓存 /home 的内容
示例 3
系统加密——具有用LUKS的dm-crypt加密的整个硬盘驱动器,/boot 分区除外(不过,用 GRUB 引导时,/boot 可被加密)
  • 使用密码或带有密钥文件的 U 盘,在引导期间解锁
  • 每个用户可能有不同的密码/密钥——可独立撤销的
  • 可用 LUKS on LVM 实现跨驱动器加密或灵活性分区布局
示例 4
隐藏式/plain 系统加密——具有 plain dm-crypt 加密的整个硬盘驱动器
  • USB-boot,使用专用密码 + 带有密钥文件的U盘
  • 在挂载前检查数据完整性
  • /boot 分区位于上述U盘上
示例 5
文件容器加密——将预分配的文件用作用户数据的加密容器

当然还有许多其他的组合。你应该仔细计划什么样的设置适合你的系统。

选用强密码[编辑 | 编辑源代码]

参阅 Security#Passwords.

准备磁盘[编辑 | 编辑源代码]

在一(部分)磁盘上设置加密之前,先考虑安全地擦除它。这包括用零字节或随机字节的流覆盖整个驱动器或分区,并且出于以下一个或两个原因而做:

防止恢复以前存储的数据

当文件系统创建或修改这些特定扇区所保存的数据时,磁盘加密不会改变单个扇区仅按需覆盖的事实(请参阅下面的#加密是怎么运作的。文件系统认为“当前未使用”的扇区不会被触及,并且可能仍包含来自先前文件系统的数据残余。确保无法恢复之前存储在驱动器上的所有数据的唯一方法是手动擦除它。 为此,使用零字节或随机字节都没有关系(尽管使用零字节擦除会快得多)。

防止泄露加密驱动器上的使用模式

理想情况下,磁盘的整个加密部分应该与均匀随机数据无法区分。这样,未经授权的人就无法知道哪些扇区以及多少个扇区实际上包含加密数据——这本身可能是一个理想的目标(作为真正机密性的一部分),也可以作为抵御试图破解加密的攻击者的额外屏障。 为了实现这个目标,使用高质量随机字节擦除磁盘至关重要。

第二个目标仅与块设备加密结合使用才有意义,因为在堆栈式文件系统加密的情况下,无论如何都可以轻松定位加密数据(以独特的加密文件的形式出现于宿主文件系统中)。另请注意,即使你只打算加密特定文件夹,如果你想删除以前以未加密形式存储在该文件夹中的文件,则必须擦除整个分区(由于磁盘碎片)。如果同一分区上还有其他文件夹,则必须备份它们,然后再将它们移回。

确定要执行哪种磁盘擦除后,请参阅文章安全擦除磁盘以获取技术说明。

提示:在决定使用哪种方法对硬盘驱动器进行安全擦除时,请记住,只要驱动器被用作加密驱动器,就不需要多次执行此操作。

加密是怎么运作的[编辑 | 编辑源代码]

本节旨在作为对常规磁盘加密的核心设置的概念和过程的高级介绍。

它不涉及技术或数学细节(请查阅相应的文献),但应该让系统管理员大致了解不同的设置选择(尤其是关于密钥管理)如何影响可用性和安全性。

基本原则[编辑 | 编辑源代码]

出于磁盘加密的目的,每个块设备(或堆栈式文件系统加密情况下的单个文件)被划分为等长的扇区,例如 512 字节(4,096 位)。然后在每个扇区的基础上进行加密/解密,因此磁盘上块设备/文件的第 n 个扇区将存储原始数据的第 n个扇区的加密版本。

每当操作系统或应用程序从块设备/文件请求某个数据片段时,包含数据的整个扇区(或扇区们)将被从磁盘读取,被即时解密,并被临时存储在内存中:

           ╔═══════╗
  扇区 1   ║“???……”║
           ╠═══════╣         ╭┈┈┈╮
  扇区 2   ║“???……”║         ┊ 密钥 ┊
           ╠═══════╣         ╰┈┬┈╯
          :              :              │
           ╠═══════╣             ▼             ┣┉┉┉┉┉┉┉┫
  扇区 n   ║“???……”║━━━━━(解密)━━━━▶┋“甲乙丙……”┋   扇区 n
           ╠═══════╣                            ┣┉┉┉┉┉┉┉┫
          :              :
           ╚═══════╝

              磁盘上加密的                                RAM 中解密的数据
              块设备或文件                      
        

同样,在每次写入操作中,所有受影响的扇区都一定会被彻底地重加密(而其余扇区不受影响)。

为了能够对数据进行解密/加密,磁盘加密系统需要知道与之相关的唯一的秘密 "钥匙"。每当要挂载相关的加密块设备或文件夹时,必须提供与其相对应的密钥(以下称为“主密钥”)。

密钥的熵对于加密的安全性至关重要。一个随机生成的一定长度的字节串,例如32字节(256比特),虽具有所需的安全性,却没法记忆,也无法在挂载期间手动应用。

出于这个原因,有两种技术被用作辅助手段。第一种是应用密码学来增加主密钥的熵值,通常涉及一个单独的人类友好的口令。对于不同类型的加密,#比较表列出了各自的特点。第二种方法是创建一个具有高熵的密钥文件,并将其存储在与要加密的数据驱动器分开的介质上。

另请参阅维基百科:认证加密(英文页面)

密钥、密钥文件和密码短语[编辑 | 编辑源代码]

以下是如何使用密钥文件来存储、加密保护主密钥的示例:

存储在明文密钥文件中

简直(以可读形式)将主密钥存储在文件中是最简单的选择。该文件——被称为“密钥文件”——可以放置于你保存在安全位置的 U 盘上,并且仅在你想要挂载磁盘的加密部分时(例如在启动或登录期间)将它连接到计算机。

以受密码保护的形式存储在密钥文件或磁盘本身中

主密钥(以及加密数据)可以使用一段必须记下来且每次你想要挂载加密的块设备或文件夹时都必须输入的保密密码短语(secret passphrase)进行保护。有关详细信息,请参阅下面的#加密的元数据

给每个会话随机生成一个临时的

在某些情况下,例如在加密交换空间(swap)或 /tmp 分区时,根本不需要保留永久的主密钥。可以给每个会话随机生成一个新的一次性密钥,而无需任何用户交互。这意味着一旦被卸载,写入相关分区的所有文件都不能被任何人再次解密——在那些特定的用例中,这非常好。

加密的元数据[编辑 | 编辑源代码]

加密技术经常使用密码函数来增强主密钥本身的安全性。在挂载加密设备时,密码或密钥文件通过这些(密码函数)传递,只有结果才能解锁主密钥以解密数据。

一个常见的设置是(通过一种“密钥导出函数(key derivation function)”)对密码短语(passphrase)应用所谓的“密钥拉伸(key stretching)”,并使用生成的增强密码短语作为挂载密钥来解密(之前以加密的形式存储的)实际的主密钥:

 ╭┈┈┈┈┈┈┈╮                           ╭┈┈┈┈┈╮
 ┊ 挂载密码短语 ┊━━━━⎛密钥导出⎞━━━▶┊ 挂载密钥 ┊
 ╰┈┈┈┈┈┈┈╯   ,──⎝  函数  ⎠        ╰┈┈┬┈┈╯
 ╭──╮          ╱                               │
 │ 盐 │────´                                  │
 ╰──╯                                           │
 ╭───────╮                                 ▼           ╭┈┈┈┈╮
 │ 加密的主密钥 │━━━━━━━━━━━━━━━(解密)━━━▶┊ 主密钥 ┊
 ╰───────╯                                              ╰┈┈┈┈╯

密钥导出函数(如 PBKDF2 或 scrypt)刻意地放慢速度(它应用一个哈希函数的多次迭代,例如 HMAC-SHA-512 的 1000 次迭代),因此通过暴力破解来找到密码短语变得不可行。对于认证用户的正常用例,每个会话只需要计算一次,因此小的减速不是问题。 它(密钥导出函数)还需要一个额外的数据块,即所谓的“”,作为一个参数——在设置磁盘加密期间随机生成一次,并被作为加密元数据的一部分不受保护地存储。因为每次设置的值都不同,攻击者无法使用密钥导出函数的预计算表来加速暴力破解。

加密的主密钥可以与加密的数据一起存储在磁盘上。这样,加密数据的机密性完全取决于保密密码短语。

可以通过将加密的主密钥存储在密钥文件中来获得额外的安全性,例如U 盘。这提供了双重身份验证(two-factor authentication):现在访问加密数据需要只有你知道的内容(密码短语),以及只有你拥有的内容(密钥文件)。

实现双重身份验证的另一种方法是增强上述密钥检索方案,以数学方式将密码短语与从(位于U 盘或类似设备上的)一个或多个外部文件读取的字节数据“结合”起来,然后将其传递给密钥导出函数。任何文件都在考虑范围之中,例如有助于#合理推诿[损坏的链接:无效的章节]的普通的JPEG图像。不过,在这种情况下,它们仍然被称为“密钥文件”。

在其导出后,只要挂载了加密的块设备或文件夹,主密钥就会被安全地存储在内存中(例如,在内核密钥环中)。

不过,它通常不直接用于对磁盘数据进行加/解密。 例如,在堆栈式文件系统加密的情形中,每个文件都可以自动分配它自己的加密密钥。每当文件要被读取/修改时,这个文件密钥首先需要用主密钥进行解密,然后它本身才能用于对文件内容进行加/解密。

                           ╭┈┈┈┈┈╮
                           ┊  主密钥  ┊
   磁盘上的文件:          ╰┈┈┬┈┈╯
  ┌──────────┐       │
  ╎╭────────╮╎       ▼         ╭┈┈┈┈┈╮
  ╎│ 加密的文件密钥 │━━━(解密)━━▶┊ 文件密钥 ┊
  ╎╰────────╯╎                  ╰┈┈┬┈┈╯
  ╎┌────────┐╎                        ▼          ┌┈┈┈┈┈┈┈┈┈┐
  ╎│ 加密的文件内容 │◀━━━━━━━━━━(加/解密)━━▶┊ 可读取的文件内容 ┊
  ╎└────────┘╎                                    └┈┈┈┈┈┈┈┈┈┘
  └──────────┘

以类似的方式,在堆栈式文件系统加密的情形下,可以使用单独的密钥(例如,每个文件夹一个)来加密文件名。

在块设备加密的情况下,每个设备使用一个主密钥,因此使用所有数据。一些方法提供了为同一设备分配多个密码短语/密钥文件的特性,而另一些方法则没有。有些使用上述函数来保护主密钥,有些则把密钥安全的控制权完全交给用户。通过 dm-crypt 在 plain 或 LUKS 模式下使用的加密参数解释两个例子。

当比较两种模式使用的参数时,我们注意到 dm-crypt plain 模式有关于如何定位密钥文件的参数(如--keyfile-size--keyfile-offset)。dm-crypt LUKS 模式不需要这些,因为每个块设备在开头都包含一个带有加密元数据的标头。标头包括使用的密码、加密的主密钥本身以及派生解密所需的参数。后面的参数又来自于主密钥初始加密时使用的选项(如--iter-time--use-random)。

对于不同技术的优/缺点,请参考#比较表或浏览特定页面。

另请参阅:

密码和操作模式[编辑 | 编辑源代码]

用于在相对于给定加密密钥彼此对应的未加密和加密数据(所谓的“明文(plaintext)”和“密文(ciphertext)”)之间进行转换的实际算法称为“密码(cipher)”。

磁盘加密采用“块密码(block cipher)”,它对固定长度的数据块进行操作,例如16 字节(128 位)。在撰写本文时,主要使用的是:

块大小 密钥大小 注释
AES 128 bits 128、192 或 256 bits 经 NSA 批准用于保护“机密”和“绝密”机密的美国政府信息(当使用 192 或256位的密钥大小时)
Blowfish 64 bits 32–448 bits 最早公开的无专利安全密码之一,因此在 Linux上非常成熟
Twofish 128 bits 128、192 或 256 bits 作为 Blowfish的继任者而开发,但尚未得到广泛使用
Serpent 128 bits 128、192 或 256 bits 被认为是入围AES决赛的五个算法中最安全的[10][11][12].

加/解密扇区(见上文[损坏的链接:无效的章节])是通过将其划分为与密码的块大小相匹配的小块来实现的,并遵循特定的规则集(所谓的“操作模式(mode of operation)”)将密码连续地应用于各个块。

仅将其不加以修改地单独应用于每个区块(被称为 "电子编码本(electronic codebook,ECB)"模式)是不安全的。因为如果相同的 16 字节明文总会产生相同的16 字节密文,攻击者可轻易识别出存储在磁盘上的密文中的加密模式。

实践中使用的最基本(且常见的)操作模式是“密码分组链接(cipher-block chaining,CBC)”。使用此模式加密扇区时,每个明文数据块以数学方式与前一个块的密文组合,然后使用密码对其进行加密。对于第一个块,由于它之前没有密文,因此使用了一个特殊的预生成的数据块(data block),该数据块与扇区的加密的元数据(cryptographic metadata)一起存储,称为“初始化向量 (initialization vector,IV)”:

                                          ╭─────╮
                                          │初始化向量│
                                          ╰──┬──╯
           ╭  ╠═════╣       ╭─密钥    │      ┣┉┉┉┉┉┫
           │  ║          ║       ▼          ▼      ┋          ┋       . 开始
           ┴  ║"????????"║◀━(密码)━━━(+)━━┋"Hello, W"┋ 块  ╱╰──┐
        文件或 ║          ║                           ┋          ┋ 1   ╲╭──┘
      块设备的 ║          ║-─────────╮      ┋          ┋       '
      n 号扇区 ╟─────╢       ╭─密钥    │      ┠┉┉┉┉┉┨
           ┬  ║          ║       ▼          ▼      ┋          ┋
           │  ║"????????"║◀━(密码)━━━(+)━━┋"orld!!!!"┋ 块
           │  ║          ║                           ┋          ┋ 2 
           │  ║          ║-─────────╮      ┋          ┋
           │  ╟─────╢                   │      ┠┉┉┉┉┉┨
           │  ║          ║                   ▼      ┋          ┋
          :   :   ...   :        ...         ...     :   ...   :  ...

                磁盘上的密文                             RAM 中的明文

类似地,在解密时,程序是反过来的。

对应于每个扇区的唯一的初始化向量的生成是值得注意的。最简单的选择是把现成的数值(如扇区号码)以某种可预见的方式计算。但这将给可以重复访问系统的攻击者执行所谓的水印攻击以可乘之机。为了预防这种情况,可以使用一种称为 “加密的盐扇区初始化向量 (Encrypted salt-sector initialization vector,ESSIV)”的方法来生成初始化向量,使它们在潜在攻击者看来完全随机。

还有许多其他更复杂的操作模式可用于磁盘加密,它们已经提供了针对此类攻击的内置安全性(因此不需要 ESSIV)。 有些还可以额外保证加密数据的真实性(即确认它没有被无权访问密钥的人修改/损坏)。

另请参见:

合理推诿[编辑 | 编辑源代码]

参见 Wikipedia:Plausible deniability.

用于磁盘加密场景的数据备份[编辑 | 编辑源代码]

为防止数据丢失,制作用户数据的备份。一般来说,你的被加密数据的备份也应该加密。

块设备加密[编辑 | 编辑源代码]

有多种选择:你可以将加密容器(encryption container)所在的磁盘块设备(disk block device)备份为映像(image),例如 /dev/sdx;也可以备份加密容器内的文件系统,例如 /dev/mapper/dm_name;亦可备份里面的文件,例如使用 rsync。 以下部分列出了每个选项的优点和缺点。

磁盘块设备备份[编辑 | 编辑源代码]

磁盘块设备备份会:

  • 按原样加密,具有与工作副本(working copy)相同的安全级别
  • 包含你的 LUKS 标头
  • 总是和磁盘块设备一样大
  • 难以使用高级备份策略,例如增量备份、压缩或重复数据删除
  • 易于恢复到新磁盘因其亦恢复加密容器

文件系统或文件备份[编辑 | 编辑源代码]

文件系统或文件备份,它:

  • 按原样加密
  • 应在通过网络传输之前或保存到磁盘时进行加密。需做额外的工作
  • 未必具有与工作副本相同的安全级别
  • 不包含你的LUKS标头
  • 仅与文件系统上的已用空间一样大,比如看看partclone
  • 可使用高级备份策略,例如增量备份、压缩或重复数据删除
  • 需要手动将加密容器恢复到新磁盘,例如通过恢复 LUKS 标头的备份

LUKS 标头备份[编辑 | 编辑源代码]

如果使用 LUKS,则可以对 LUKS 标头进行备份:定期检查与同步这些备份是有意义的,尤其是在密码已被撤销的情况下。

但是,如果你有数据备份,并且想要恢复它,你可以使用 cryptsetup 从头开始重新创建 LUKS 加密分区,然后恢复数据,因此备份 LUKS 标头不如备份数据重要。