磁盘加密指南

David Braun

2004-11-17

修订历史
修订版 1.52004-11-17修订者:DB
添加了关于 dm-crypt 的警告
修订版 1.42004-08-17修订者:DB
错误修复,提示了关于看似可信的否认和 dm-crypt 的信息
修订版 1.32003-12-18修订者:DB
添加了 Diceware 的链接
修订版 1.22003-10-09修订者:DB
添加了空闲注销和 Gentoo 指令
修订版 1.12003-09-13修订者:DB
添加了清零钥匙串的步骤
修订版 1.02003-08-28修订者:tmm
初始版本,由 LDP 审核
修订版 0.922003-08-27修订者:DB
首次提交给 LDP

本文描述了一种加密硬盘的方法,可以完整或部分加密硬盘,并将加密密钥存储在外部介质上以提高安全性。


目录
1. 简介
1.1. 技术摘要
1.2. 版权和许可
1.3. 免责声明
1.4. 致谢
1.5. 反馈
1.6. 方法
1.7. 威胁模型
1.8. 注意事项
1.9. 要求
1.10. 展望未来
2. 步骤
2.1. 准备钥匙串
2.2. 准备资产
2.3. 脚本
2.4. 测试和备份
2.5. 救援磁盘
2.6. 安装 Linux
3. 更多信息
术语表
A. GNU 自由文档许可证
A.1. 序言
A.2. 适用性和定义
A.3. 逐字复制
A.4. 大量复制
A.5. 修改
A.6. 合并文档
A.7. 文档集合
A.8. 与独立作品的聚合
A.9. 翻译
A.10. 终止
A.11. 本许可证的未来修订
A.12. 附录:如何将本许可证用于您的文档

1. 简介

我有一台运行 Linux 的笔记本电脑,我不希望有人读取其中包含的个人信息,以防丢失或被盗。我的登录密码可能会阻止某人启动它,但它无法阻止攻击者移除硬盘并读取其数据。我需要更强的保护。

幸运的是,使用加密相对容易,这样硬盘数据如果落入坏人之手将无法读取。加密不仅对像笔记本电脑这样的便携式计算机有用,它还可以用来保护任何包含个人信息的计算机。我使用加密保护我计算机的文件的原因与我在家锁上文件柜的原因相同。为了进一步了解动机,您可能有兴趣阅读 Michael Crawford 的 为什么要使用加密

我可以只加密某些文件,例如我主目录中的文件。这将保护文件,但随后我必须担心信息从这些文件中泄露到磁盘上其他未加密的地方。相反,我加密整个磁盘,这样我就不必管理这个问题。

有很多加密算法可供选择。我选择了 AES,因为它已获得美国政府的 国家标准与技术研究院的批准,并且受到密码学界的广泛好评。我希望我对它的使用能够抵抗字典攻击,因此我使用一个长长的随机生成的密钥。我不可能记住这样一个密钥,所以我将它保存在一种我可以轻松携带的形式中:我的钥匙链上的 USB 闪存驱动器。我用一个密码短语加密密钥,这样我的数据就受到两种方式的保护:a) 我拥有的(USB 闪存驱动器)和 b) 我知道的(密码短语)。我甚至可以在不泄露我的密码短语的情况下让朋友访问我的电脑——她可以使用她自己的 USB 闪存驱动器和她自己的密码短语。

操作系统始终将数据加密存储在磁盘上,并在使用时才在 RAM 中解密。这样,如果计算机突然断电,数据将保持受保护状态。解密密钥在启动时加载到 RAM 中,并在计算机开启时保持在那里,因此启动计算机后我不需要一直插着 USB 闪存驱动器。

本指南中概述的过程是为 Linux 内核的 2.4 版本编写的。随着 Linux 2.6 的发布,它将变得不那么复杂,Linux 2.6 将内置对加密的支持,并且可以更好地管理环回设备中的分区。

本文档假设读者具有中等水平的 Linux 使用经验(您应该熟悉 修补和编译内核以及 分区、挂载和卸载磁盘)。


1.1. 技术摘要

加密是通过一种特殊的环回设备实现的。环回设备本身不存储任何数据;相反,它获取它接收到的所有数据存储和检索请求,并将它们传递给真正的存储设备,例如磁盘或文件。当数据通过时,可以对其进行过滤,在我们的例子中,使用的过滤器是加密。

部署系统时,可移动介质(USB 闪存驱动器)使用 GRUB、内核和 initrd 启动。密钥和内核都是从 GRUB 菜单中选择的,允许单个可移动介质与多台计算机一起使用。 initrd 包含足够的工具来请求密码短语、设置加密的环回设备并挂载它。挂载后,pivot_root用于从加密设备恢复启动过程。环回设备偏移量用于访问加密环回设备中的单独交换和根文件系统空间,而不是分区,因为 2.4 内核不提供对环回设备中分区的访问。偏移方法不能推广到多个分区(不幸的是),因为losetup理解的最大偏移量为 2GB。


1.2. 版权和许可

允许复制、分发和/或修改本文档,但必须遵守自由软件基金会发布的 GNU 自由文档许可证第 1.2 版或任何更高版本;不含不变部分、封面文本和封底文本。 许可证副本包含在附录 A中。

Linux 是 Linus Torvalds 的注册商标。®


1.3. 免责声明

对于本文档的内容,不承担任何责任。 使用这些概念、示例和信息风险自负。 可能存在可能损害您的系统并可能导致您丢失重要数据的错误和不准确之处。 请谨慎操作,尽管这种情况不太可能发生,但作者不承担任何责任。

除非另有特别说明,否则所有版权均归各自所有者所有。 本文档中使用的术语不应被视为影响任何商标或服务标志的有效性。 特定产品或品牌的命名不应被视为认可。

我知道您讨厌阅读说明并想立即跳到实质内容,但我建议您在触摸任何东西之前先阅读整个文档。 我知道所有的 HOWTO 都是这么说的,但我对这篇文档真的是认真的。 这是值得的; 相信我。 在处理生产系统之前,您可能还想先在测试系统上运行该过程。


1.4. 致谢

感谢 Linus Torvalds、Jari Ruusu 以及所有为他们的软件做出贡献的开发人员,没有他们的软件,本 HOWTO 将是不可能的。

感谢 国家标准与技术研究院 仔细选择了一种强大的、开放的加密算法。

感谢 linux-crypto 邮件列表和 Linux 文档项目邮件列表上的 Mark Garboden 和其他人,他们花时间批评我的写作并提出建议。

感谢警惕的读者 Ladislao Bastetti 和 Norris Pouhovitch 在不寻常的硬件配置中挣扎,发现 HOWTO 中的错误并提出好的想法。


1.5. 反馈

欢迎对本文档提出反馈。 请将添加、评论和批评发送给作者。


1.6. 方法

我们可以采取三种不同的方法来加密磁盘:加密整个磁盘、单个分区或单个文件。 我强烈建议采用第一种方法以获得最佳安全性。 前两种方法假定您将从可移动介质(例如 USB 闪存驱动器或名片大小的 CD-ROM)启动。 如果您不想这样做,您可以通过创建一个小的、未加密的启动分区来修改该方法以从磁盘启动。 如果您想使用 USB 闪存驱动器启动您的计算机,请务必首先确保您的主板可以做到这一点。 在撰写本文时,许多主板都无法做到这一点。

为了避免在所有地方列举所有三种方法,我将把您要保护的东西称为资产。 我将用于存储密钥的可移动介质称为钥匙串。 我称它为钥匙串而不是密钥,因为我们可以在同一介质上存储许多密钥,每个密钥用于不同的计算机。


1.6.1. 整个磁盘

使用加密来保守数据秘密的一个问题是数据喜欢移动。 想象一下,加密就像你数据周围的栅栏。 当数据在栅栏内时,它是安全的。 然而,为了最有用,数据喜欢在网络上传输,放在 CD-ROM 等可移动磁盘上,并与朋友分享。 每当你的数据离开围栏区域时,它都是不受保护的。 我们无法在我们数据可能播放的所有可能位置周围放置加密围栏,但我们确实希望使围栏尽可能大。 通过将加密围栏围绕你的整个硬盘放置,你将不必担心数据跳到磁盘的另一部分时会变得不受保护。

Warning

在这种方法中,我们创建一个交换空间和一个根文件系统。 有些人想要多个用于根文件系统的加密分区。 不幸的是,这里详细介绍的方法依赖于losetup的 offset 参数来在资产中创建“子分区”。 offset 参数的最大值为 2GB,从而将除了最后一个分区之外的所有分区的大小限制为 2GB。 这对于交换空间来说效果很好,因为交换空间在 i386 架构上已经被限制为 2GB,但我猜测它对于其他用途来说并不实用。 使用它来创建小于 2GB 的多个分区留给读者作为练习。

另一种处理多个分区的方法是分别加密每个分区(使用相同的密钥),以避免上述技术限制。这不如加密整个磁盘安全,因为分区表会暴露。当攻击者试图破解加密时,他做的第一件事就是试图弄清楚它加密的是什么。列出 Linux 分区的分区表是一个很大的提示。因此,我不鼓励分别加密多个分区,但可以认为这是绕过当前losetup限制的一个很好的折衷方案。另一种选择是直接等待 Linux 2.6 的发布,因为它有望使 offset 参数变得不必要。


1.6.2. 分区(用于多启动系统)

如果 Linux 是磁盘上唯一的操作系统,则加密整个磁盘是可行的,但这不适用于已将其计算机设置为启动多个操作系统(例如,LinuxNetBSDDarwin)的人。在这种情况下,我们可以只加密 Linux 分区,而让其他分区保持不变。由于我们是从可移动介质启动,因此我们甚至不需要将 Linux 分区与其他的分区一起包含在多启动菜单中。要了解为什么这不如加密整个磁盘安全,请阅读表 1


1.6.3. 文件(用于主目录)

您可能只想加密文件系统上的一个文件。加密后,您可以将任何您想要的东西放入其中,包括其他文件系统。例如,您可能想使用此方法仅加密您的主目录。这是三种方法中最不安全的,不建议使用。如果您选择这种方法,您会注意到以下跳过整个部分的说明。这是因为我假设您已经启动了操作系统并处理了您的交换问题,因此这些部分不适用于您。本 HOWTO 对于您的需求来说可能有点矫枉过正,您可能只需阅读精细的README附带 loop-AES 的文件。如果您这样做,请务必在完成此处之前阅读第 1.7 节


1.7. 威胁模型

为了很好地保护我们的资产,我们必须首先了解我们要保护它免受什么侵害。一般的想法是,您有一台容易被盗或丢失的笔记本电脑,并且您的钥匙链上有一个 USB 闪存驱动器,而该驱动器不会被盗或丢失,因此该系统旨在处理笔记本电脑被盗的情况。我猜您的钥匙链不容易被盗,因为它在您的口袋里,而且攻击者不会知道它很重要。如果您从口袋里拿出 USB 闪存驱动器,并且有人(不是技术人员)惊呼“那是什么?”,告诉他们这是一个Pez 分配器

Note

该系统在似是而非的否认性方面存在不足,这意味着无法隐藏您的个人数据已加密的事实。这就像将您的珠宝锁在一个保险箱中,并将保险箱放在客厅中央的显眼位置。只有您可以打开保险箱,但拿枪的人可以让您为他打开保险箱。因此,如果您担心您的电脑被传唤,并被告知交出您的笔记本电脑、钥匙链和密码,您最好看看其他解决方案,例如StegFS

Norris Pouhovitch 提出了以下针对否认性问题的解决方案。应该可以在磁盘的前面安装一个最小的 Windows 分区,并加密其余部分。当电脑在没有钥匙链的情况下打开时,它会正常启动 Windows。当钥匙链启动时,它会跳过 Windows 分区,解密磁盘的其余部分,并启动 Linux。

该方案的优点是,如果笔记本电脑被盗并打开,它看起来会像一个普通的攻击者期望看到的那样(一台 Windows 电脑)。另一方面,一个认真的攻击者可能会注意到异常小的分区并开始怀疑。我将在 HOWTO 的未来版本中进一步充实这个想法。

表 1. 攻击树

攻击反应注释
攻击者盗窃笔记本电脑当它开机时SOL当计算机运行时,资产不受保护,因为加密密钥在 RAM 中。您可以通过使用空闲注销(第 2.6.3 节)来降低风险,但如果您认为您的笔记本电脑即将被盗,请立即关闭电源并快速阅读合气道 HOWTO
当它关机时攻击者未盗窃钥匙链新密钥 
攻击者盗窃钥匙链攻击者知道您的密码SOL 
攻击者不知道您的密码新密钥 
攻击者盗窃钥匙链但没有笔记本电脑攻击者知道密码新密钥您的资产面临风险,因为攻击者可以解密它。
攻击者不知道密码您感到懒惰,或者您确信钥匙链丢失了,而不是被盗了新密码您可能不需要更改资产密钥,因为攻击者无法在没有密码的情况下解密资产。
您感到偏执新密钥 
攻击者说服您通过网络发送数据SOL 
攻击者说服您将数据复制到可移动介质SOL 
您仅加密一个分区,而一个进程将数据写入另一个分区SOL 
您仅加密一个文件,而一个进程将数据从 RAM 复制到未加密的交换分区,或者复制到文件中的/tmp,或者在未加密磁盘上的其他位置SOL 
攻击者威胁您,挥舞着橡皮软管,要求您交出笔记本电脑、钥匙链和密码SOL系统中没有内置似是而非的否认性。
新密码

恢复钥匙链备份并选择一个新密码。

新密钥

生成一个新的随机密钥以重新加密资产,选择一个新密码,并恢复资产备份。

SOL

对您的损失感到抱歉(Sorry Over your Loss)


1.8. 注意事项

  • 此方法不适用于(尚未)Linux 软件挂起

  • 加密磁盘无疑会减慢速度。我不知道减慢了多少。如果有人做了一些基准测试,请发送给我。

  • 此方法中没有任何内容支持似是而非的否认性(参见第 1.7 节)。

  • 它不能防止通过网络和可移动磁盘的信息泄露。

  • 加密备份超出了本 HOWTO 的范围。


1.9. 要求

  • 一台具有易于访问的可移动介质读取器(例如 USB 端口或 CD-ROM 驱动器)的计算机

  • 一个支持从可移动介质启动的主板(仔细检查 USB,并非所有主板都支持)

  • 可移动介质(例如USB 闪存驱动器)用作钥匙链

  • Linux 2.4

  • loop-AES


1.9.1. 关于 USB 闪存驱动器的题外话

市场上有许多选择。当我购买我的闪存驱动器时,我发现了一个满足以下要求的

  • 物理尺寸小(我把它放在我的物理钥匙链上)

  • 支持全速 USB 2.0

  • 有一个写保护开关,所以我不会意外地破坏我的加密密钥

您可能会想买一个带有指纹读取器的。我强烈建议您不要这样做。最初看起来可能是一个好主意,因为通过添加生物识别技术,您的安全保护扩展到

  • 您拥有的东西(USB 闪存驱动器)

  • 您知道的东西(密码)

  • 您的东西(您的指纹或其他东西)

但是,假设出现问题。如果您现在问自己,“会出现什么问题?”,那么您为什么要阅读本 HOWTO?如果出现问题,您会做出更改(参见纠正措施

  • 通过使用不同的 USB 闪存驱动器来更改您拥有的东西。

  • 通过学习一个新密码来更改您知道的东西。

  • 您无法更改您是什么。

停下来思考最后一行一会儿。


1.10. 展望未来

我在使用 2.4 内核时编写了本文档。Linux 2.6 引入了 Device-mapper,我们将能够使用它来避免使用 losetup 偏移量。Linux 2.6 还引入了 dm-crypt,它是 Device-mapper 的加密层,看起来非常优雅。不幸的是,它并不安全!希望有一天它会被修复,但在此期间,最好的方法是坚持使用 loop-AES。

本 HOWTO 的未来版本将解释如何将 Device-mapper 与 Linux 2.6 一起使用。


2. 程序

此方法旨在在加密之前擦除资产的内容。如果您已经有要加密的磁盘上的数据,则应将其临时复制到其他位置,然后在设置加密后将其移回。可以就地加密数据,但目前我认为这种魔术对于本 HOWTO 来说太高级了。如果您对此方法感兴趣,请参阅 loop-AESREADME 以获取更多详细信息。

要执行以下操作,您需要运行一个具有 loop-AES 功能的内核的系统。如果您还没有,我建议使用 KNOPPIX。它可以从 CD-ROM 启动,无需安装,因此非常省事。

为简单起见,这些说明假定您将在同一台计算机上准备钥匙链和资产,但这不必如此。根据对您方便的方式调整说明。


2.1. 准备钥匙链

如果您采用仅加密文件而不是磁盘或分区的方法,您可以跳过本节并直接进入第 2.2 节

在理想的设置中,您将使用可启动的钥匙链设备,例如USB 闪存驱动器或名片大小的 CD-ROM。这是因为我们希望尽可能少地暴露您的磁盘,但我们将不得不暴露一个最小的启动过程,否则计算机将永远无法启动。由于启动过程必然是未加密的,因此最好将其远离您的计算机(在您的钥匙链上)。如果您由于某种原因无法或不想使用可启动的钥匙链,请仍然按照这些说明进行操作,但将其应用于磁盘上的一个小启动分区,而不是钥匙链。

在下面的示例中,钥匙链显示为第一个 SCSI 驱动器/dev/sda. 替换/dev/sda为您的驱动器的设备(如果适用)。

第一步(将钥匙链归零)在技术上是不必要的,但是如果您像我在 第 2.4 节中建议的那样将钥匙链备份为图像,这将使钥匙链备份更小。

bash# dd if=/dev/zero of=/dev/sda

接下来,像对待任何可启动磁盘一样对钥匙链进行分区。如果您需要分区方面的帮助,请参阅 Linux 分区 HOWTO

bash# cfdisk /dev/sda

在第一个分区上放置一个文件系统。

bash# mkfs /dev/sda1

挂载钥匙链。

bash# mkdir /tmp/keychain
bash# mount /dev/sda1 /tmp/keychain
bash# cd /tmp/keychain

2.1.1. 构建内核

如果您将钥匙链与多台计算机一起使用,您可能想为每台计算机构建不同的内核。

您可能需要为您的密钥链构建一个自定义内核,以便确保两件事:

  • 它已经正确地用 loop-AES 打了补丁,并且加密支持已启用。

  • 启动计算机并使资源可访问所需的所有设备驱动程序都已被编译到内核中,而不是作为模块加载。

您可以将设备驱动程序作为模块加载,因为我们正在使用 initrd,但我选择将它们编译到内核中,以便使启动盘尽可能简单。您可以随意选择不同的方式。

要获得构建自定义内核的帮助,请阅读 Linux Kernel HOWTO。请务必设置CONFIG_BLK_DEV_RAM在内核配置中,以便它可以启动并使用 initrd。

按照 loop-AES 附带的说明来构建新的 loop 驱动程序。 还要按照说明重建 util-linux 工具,我们稍后会将其中一些工具复制到密钥链。 您的发行版可能已经为您构建了这些工具(例如,请参阅loop-aes-utilsloop-aes-sourceDebian 中的软件包)。

构建内核后,将其复制到密钥链。

bash# mkdir boot
bash# cp arch/i386/boot/bzImage boot/vmlinuz-laptop

安装 GRUB 或您最喜欢的引导加载程序。

bash# grub-install --root-directory=. /dev/sda

这是一个示例menu.lst适用于 GRUB。 它包含两个名为 laptopdesktop 的计算机的条目。

Important

需要将密钥的名称(我建议您以计算机命名)作为第一个参数传递给 linuxrc

示例 1。/tmp/keychain/boot/grub/menu.lst

title  laptop
root (hd0,0)
kernel /boot/vmlinuz-laptop root=/dev/ram0 init=/linuxrc laptop
initrd /boot/initrd
 
title  desktop
root (hd0,0)
kernel /boot/vmlinuz-desktop root=/dev/ram0 init=/linuxrc desktop
initrd /boot/initrd.old

2.1.2. 制作 initrd

我们使用 initrd 启动密钥链,以便在启动过程开始后可以将其删除(谁希望在咖啡馆里想让自己看起来很酷时,笔记本电脑上挂着一个 USB 闪存驱动器?)。 为了访问资源,我们创建了一个附加到 initrd 的环回设备/dev/loop0。 将设备文件放在 initrd 上意味着在挂载资源时,initrd 必须保持挂载状态(没什么大不了的)。

要了解有关制作初始 RAM 磁盘的所有信息,欢迎您阅读 Linux Bootdisk HOWTO 和 Linux 的 Documentation/initrd.txt, 或者不费心,直接跟着做。

我们首先选择 4MB 作为初始 RAM 磁盘的大小,我们不会需要所有这些,但这是传统的最大大小(并且不会造成任何伤害),因此这是一个需要做出的决定。

bash# head -c 4m /dev/zero > boot/initrd
bash# mke2fs -F -m0 -b 1024 boot/initrd

挂载 initrd,以便我们可以对其进行处理。

bash# mkdir /tmp/initrd
bash# mount -o loop=/dev/loop3 boot/initrd /tmp/initrd
bash# cd /tmp/initrd

创建我们将需要的最小目录结构。

bash# mkdir -p {bin,dev,lib,mnt/{keys,new-root},usr/sbin,sbin}

创建我们将需要的最小设备集。 请注意,tty是密码提示所必需的。 此命令假定您的资源是驱动器/dev/hda。 根据需要更改它。

bash# cp -a /dev/{console,hda,loop0,loop1,tty} dev

我们将复制我们需要的六个程序。

Tip

您可以使用which来查找程序的完整路径名,例如

bash# which mount
/bin/mount

复制程序

bash# cp /bin/{mount,sh,umount} bin
bash# cp /sbin/{losetup,pivot_root} sbin
bash# cp /usr/sbin/chroot usr/sbin

使用ldd来找出每个程序使用哪些共享库

bash# ldd /bin/{mount,sh,umount} /sbin/{losetup,pivot_root} /usr/sbin/chroot
/bin/mount:
        libc.so.6 => /lib/libc.so.6 (0x40023000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
/bin/sh:
        libncurses.so.5 => /lib/libncurses.so.5 (0x40020000)
        libdl.so.2 => /lib/libdl.so.2 (0x4005c000)
        libc.so.6 => /lib/libc.so.6 (0x4005f000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
/bin/umount:
        libc.so.6 => /lib/libc.so.6 (0x40023000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
/sbin/losetup:
        libc.so.6 => /lib/libc.so.6 (0x40023000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
/sbin/pivot_root:
        libc.so.6 => /lib/libc.so.6 (0x40023000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
/usr/sbin/chroot:
        libc.so.6 => /lib/libc.so.6 (0x40023000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

复制库。 在我的系统上,我复制了这些库(您的可能不同)

bash# cp /lib/{ld-linux.so.2,libc.so.6,libdl.so.2,libncurses.so.5} lib

2.2. 准备资源

您可以根据需要多次重复这些步骤,以使用相同的密钥链处理多台计算机。 每台计算机都将拥有自己的密钥,并且可能拥有自己的内核。 此处的说明假定计算机的名称为 laptop; 每次重复这些步骤时,请替换为您正在使用的计算机的名称。

首先,备份您的数据。 请参阅 Linux Complete Backup and Recovery HOWTO

不,停下,听我说。 备份您的数据。 真的。 如果您因为自己犯的一些错误而无法解密硬盘,那么拥有一个加密的硬盘就没有乐趣了。 这些工具是强大的魔法; 如果您搞砸了,您不能只是致电Computer Gurus Are Us 并期望他们为您找回您的数据。 这就是这项练习的全部意义。

如果您要加密整个磁盘(推荐),请替换/dev/hda为您的磁盘的设备。

bash# ln -s /dev/hda /tmp/asset

如果您要加密分区(多重引导情况),请替换/dev/hda3为您的分区的设备。

bash# ln -s /dev/hda3 /tmp/asset

如果您只加密一个文件,请替换~/encrypted为文件的名称,并创建一个名为/tmp/keychain的链接,该链接指向您决定存储密钥文件的位置(一个已经准备好的可移动介质,例如/mnt/cf).

bash# ln -s ~/encrypted /tmp/asset
bash# ln -s /mnt/cf /tmp/keychain

使用随机数据初始化资源。 这将使攻击者更难识别哪些部分是可用空间。

bash# shred -n 1 -v /tmp/asset

在这里,我们创建一个加密的文件系统来保存密钥。 您说,更多的加密? 是的,以防您的密钥链被盗(请参阅 表 1),您不希望您的密钥暴露。 我选择 1MB 作为文件系统的大小,因为它是一个整数。 我们肯定不需要那么多空间来存储密钥,因此如果您愿意,可以随意选择更小的大小(每个密钥文件将是 61 个字节长)。

再次,使用随机数据初始化。

bash# cd /tmp/initrd
bash# head -c 1m /dev/urandom > keys

为了使密码短语能够抵抗字典攻击,我们将生成一个种子。 只要您看到符号<seed>请务必将其替换为您生成的种子。 以下命令将在屏幕上显示一个随机种子。

bash# head -c 15 /dev/random | uuencode -m - | head -2 | tail -1

使用种子设置环回设备。 在这里您可以选择您的密码短语,其长度必须至少为 20 个字符。 谨慎选择一个您知道您不会忘记的密码短语。 您可能想使用 Diceware method 来选择一个安全的密码短语。

bash# losetup -e AES128 -C 100 -S <seed> -T /dev/loop1 keys

格式化并挂载密钥文件系统(decrypt.sh 脚本假定您在此处使用ext2文件系统)。

bash# mke2fs /dev/loop1
bash# mkdir /tmp/keys
bash# mount /dev/loop1 /tmp/keys

现在是实际的资源密钥,45 个字节尽可能随机地由您的计算机生成。 尝试对该密钥进行字典攻击,攻击者! 哈! 我们以将要使用它的计算机 (laptop) 的名称命名密钥。 替换为您计算机的名称。

bash# head -c 45 /dev/random | uuencode -m - | head -2 | tail -1 > /tmp/keys/laptop

使用密钥设置环回设备,以便对资源进行加密访问。

bash# losetup -e AES128 -p 0 /dev/loop0 /tmp/asset < /tmp/keys/laptop

卸载密钥文件系统。

bash# umount /tmp/keys
bash# losetup -d /dev/loop1

2.2.1. 交换分区

如果您仅加密一个文件,请跳过本节。

至关重要的是要给mkswap在此处提供一个 size 参数,因为我们没有向其提供专用的分区。 选择您想要的任何大小; 我选择了 2GB。

bash# mkswap /dev/loop0 $((2*1024*1024))
mkswap: warning: truncating swap area to 2097144kB
Setting up swapspace version 1, size = 2147471360 bytes

2.2.2. 根文件系统

如果您仅加密一个文件,请使用像这样的文件系统对其进行格式化,然后跳到 第 2.3 节

bash# mkfs /dev/loop0

我们将在交换空间之后创建根“分区”。 我将“分区”一词放在引号中,因为它不是一个真正的分区。 我们使用偏移量参数来伪造它losetup.

注意mkswap告诉了我们交换空间的实际大小,这不一定是请求的大小。 指定开始根文件系统的偏移量时,请使用实际大小(在上面的示例中为 2147471360)。

bash# losetup -o <root offset> /dev/loop1 /dev/loop0

如果资源是整个磁盘或磁盘上的最后一个分区,那么我们无需担心指定文件系统的大小。 如果这适用于您,请执行以下操作,然后跳到 第 2.2.2.1 节

bash# mkfs /dev/loop1

由于资源不是磁盘上的最后一个分区,因此我们必须给mkfs大小限制,否则它将覆盖此分区和磁盘末尾之间的所有分区。 我再说一遍,如果您没有在此处为 mkfs 提供正确的大小参数,您可能会丢失数据mkfs实际上只是一个前端,因此为了尽可能小心,我们将选择一个实际的文件系统制造商,在这种情况下mke2fs.

可以通过以块为单位指定文件系统的大小来限制文件系统的大小,但是mke2fs根据文件系统的大小选择块大小。 一个经典的 Catch-22! 我们可以要求它对磁盘的其余部分(超出我们想要的)进行试运行,以查看它将选择什么块大小。

bash# mke2fs -n -j /dev/loop1
mke2fs 1.34-WIP (21-May-2003)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
9781248 inodes, 19544448 blocks
977222 blocks (5.00%) reserved for the super user
First data block=0
597 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424

在这种情况下,它选择了 4096。无论它选择什么,对于我们的文件系统来说可能都足够接近。 计算块中正确的大小。

文件系统大小 = (分区大小 − 交换空间大小) / 块大小

假设分区的大小为 10GB,交换空间的大小为 2GB。 的正确大小为mke2fs是 (10 − 2) * 230 / 4096 = 2097152。不要弄错! 制作备份! 三思而后行!

bash# mke2fs -j /dev/loop1 2097152

2.2.2.1. initrd 挂载点

挂载新的根文件系统并创建initrd挂载点。 这对于 linuxrc 脚本调用pivot_root.

bash# mount /dev/loop1 mnt/new-root
bash# mkdir mnt/new-root/initrd
bash# umount mnt/new-root

2.3. 脚本

我们有足够的信息来创建解密脚本。 更改开头的变量以反映您的设置(包括您之前生成的种子)。

如果您要加密整个磁盘或分区,请设置ROOT_OFFSET为您从mkswap获得的大小。 将脚本放在/tmp/initrd并将其命名为decrypt.sh.

如果您仅加密一个文件,则此脚本可以位于任何位置。 在这种情况下,请务必将ROOT_OFFSET设置为零并设置MOUNT到方便的挂载点(可能不是/mnt/new-root).

图 1。/tmp/initrd/decrypt.sh

#!/bin/sh

SEED=<seed>
ASSET=/dev/hda
ROOT_OFFSET=<root offset>
ROOT_TYPE=ext3
MOUNT=/mnt/new-root
KEY="$1"

# Ask for a passphrase to open the keys (this prevents exposure of the keys in
# case the owner loses the keychain).  Give the user three tries to get the
# passphrase right.
for ((FAILED=1, TRY=1; ($FAILED != 0) && (TRY <= 3); TRY++))
do
        mount -n -t ext2 -o loop=/dev/loop1,encryption=AES128,itercountk=100,pseed=$SEED keys /mnt/keys
        FAILED=$?
done
                                                                                
if [ $FAILED -ne 0 ]; then
        echo "Sorry, you get only three attempts to guess the password."
        exit 1
fi

# Use the key to decrypt the asset.
losetup -e AES128 -p 0 /dev/loop0 $ASSET < "/mnt/keys/$KEY"
 
# Close the keys.
umount -n /mnt/keys
losetup -d /dev/loop1
 
# Set up the root "partition" device.
losetup -o $ROOT_OFFSET /dev/loop1 /dev/loop0
 
# Mount the root file system (read-only, so it can be checked with fsck).
mount -n -r -t $ROOT_TYPE /dev/loop1 $MOUNT

使脚本可执行。

bash# chmod +x decrypt.sh

如果您仅加密一个文件,请跳到 第 2.4 节。 否则,将以下启动脚本另存为linuxrc并将其放在/tmp/initrd.

图 2。/tmp/initrd/linuxrc

#!/bin/sh

# Decrypt the asset
source decrypt.sh "$1"

# Pivot to the asset's root file system.
cd $MOUNT
/sbin/pivot_root . initrd

# Pass control to init.
shift 1
exec chroot . /sbin/init $* <dev/console >dev/console 2>&1

使脚本可执行。

bash# chmod +x linuxrc

好的,密钥链和资源现在已准备就绪。 卸载所有内容。

bash# umount /tmp/{initrd,keychain}

您现在拥有一个空的加密文件系统。 万岁!


2.4. 测试和备份

通过启动密钥链或根据需要执行 decrypt.sh 脚本来测试您的系统(将其作为参数提供给您要使用的密钥的名称)。 启动后,可能会抱怨不存在/sbin/init但现在没关系。

检查以确保您的根文件系统已成功挂载。 当您确信一切正常时,备份您的密钥链。 事实上,制作大量备份。 您可能会问,“但是将我的密钥链的副本放在某个地方不是不安全吗?” 答案是肯定的,但不如丢失您唯一的密钥链那么不安全,如果您将安全性定义为也意味着“确保对我的数据的访问”。

因为我的钥匙链很小,所以我决定备份整个镜像,这样可以很容易地恢复。

bash# bzip2 -c /dev/sda > keychain.img.bz2

如果你仅仅加密了一个文件,那么你可以为此感到自豪了,因为你已经完成了。


2.5. 救援盘

当系统行为异常和/或拒绝启动时,救援盘非常有用。请检查以确保您的救援盘在其内核中具有 loop-AES 支持,并且具有正确修补的 util-linux 工具,例如losetupmount,否则它对你新加密的资产毫无价值。将来,所有救援盘都将包含此支持,因为它将成为2.6内核的标准配置。同时,KNOPPIX(例如)已经拥有所有必要的支持,可以用作救援盘。

在启动适当的救援盘后,挂载你的钥匙链并执行 decrypt.sh 脚本。

bash# mkdir /tmp/{keychain,initrd}
bash# mount /dev/sda1 /tmp/keychain
bash# mount -o loop=/dev/loop3 /tmp/keychain/boot/initrd /tmp/initrd
bash# pushd /tmp/initrd
bash# ./decrypt.sh laptop
bash# popd
bash# umount /tmp/{initrd,keychain}

现在,你可以通过在 decrypt.sh 中指定的挂载点访问你的资产。


2.6. 安装 Linux

你的最终任务是将 Linux 安装到新的加密文件系统中。在执行此操作时,请确保你的/etc/fstab中根目录和交换分区的条目看起来如下所示

# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>               <dump>  <pass>
/dev/loop0      none            swap    sw                      0       0
/dev/loop1      /               ext3    errors=remount-ro       0       1

如果已经安装了其他发行版,请阅读 硬盘升级 Mini How-To,了解如何复制它。

针对每个发行版,全新安装 Linux 的过程各不相同。 请将未在下面列出的发行版的安装说明发送给我,我将在此处包含它们。


2.6.1. Debian

  1. 按照第 2.5 节中的说明从救援盘启动。

  2. 使用 3.7 从 Unix/Linux 系统安装 Debian GNU/Linux 方法进行安装。


2.6.2. Gentoo

  1. 按照第 2.5 节中的说明从救援盘(Gentoo 的 Live CD 1.4 将不起作用)启动。

  2. 如果创建了交换分区,请激活它。

    bash# swapon /dev/loop0
  3. /mnt/gentoo指向根文件系统。

    bash# ln -s new-root /mnt/gentoo
  4. 跳到 第八章:Stage tarballs 和 chroot,在 Gentoo Linux 1.4 安装指南中。


2.6.3. 空闲注销

系统启动并运行后,考虑将其配置为在一段时间不活动后自动注销。 如果笔记本电脑在开机状态下被盗,这将减少(但不会消除)暴露资产的风险(请参阅表1)。


3. 更多信息

词汇表

AES

高级加密标准,一种强大且备受推崇的 加密 算法,由美国 国家标准与技术研究院 选择

资产

加密 保护的数据,可以是磁盘、分区或文件

加密

一种对数据进行加扰的数学方法,使其变得难以理解,除非使用特定的 密钥 解密

密钥

使加密数据可理解所需的小块数据

钥匙链

用于保存加密 密钥(以及可能的启动过程的开始部分)的物理介质(例如 USB 闪存驱动器

环回设备

一个 Linux 块设备,它看起来存储数据(通过使用另一个设备)

loop-AES

由 Jari Ruusu 编写的软件,使用 环回设备 实现 AES 算法

可信的否认

一种避免被强迫为攻击者解密自己的数据的方法

USB 闪存驱动器

一种包含存储芯片和 USB 接口的小型电子设备


A. GNU 自由文档许可证

版本 1.2,2002 年 11 月

版权 (C) 2000,2001,2002 自由软件基金会,Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 允许任何人复制和分发此许可证文档的逐字副本,但不允许更改它。


A.1. 前言

本许可证的目的是使手册、教科书或其他功能性和有用的文档在自由的意义上“自由”:以确保每个人都拥有复制和重新分发它的有效自由,无论是否修改它,无论是商业的还是非商业的。 其次,本许可证保留了作者和出版商获得对其工作的认可的方式,同时不被认为对他人所做的修改负责。

本许可证是一种“著作权”,这意味着文档的衍生作品本身必须以相同的意义自由。 它补充了 GNU 通用公共许可证,后者是为自由软件设计的著作权许可证。

我们设计本许可证是为了将其用于自由软件的手册,因为自由软件需要自由的文档:自由程序应该附带提供与软件相同的自由的手册。 但本许可证不限于软件手册; 它可以用于任何文本作品,无论主题如何,或者是否以印刷书籍形式出版。 我们主要推荐本许可证用于以指导或参考为目的的作品。


A.2. 适用性和定义

本许可证适用于任何手册或其他作品,以任何介质,其中包含版权持有者放置的声明,声明它可以根据本许可证的条款进行分发。 此类声明授予全球范围内的免版税许可,无限期地使用该作品,但须遵守此处规定的条件。 下面的“文档”是指任何此类手册或作品。 任何公众成员都是被许可人,并被称为“你”。 如果你以需要版权法许可的方式复制、修改或分发作品,则你接受该许可。

文档的“修改版本”是指包含文档或其一部分的任何作品,无论是逐字复制,还是经过修改和/或翻译成另一种语言。

“次要章节”是文档的命名附录或前言章节,专门处理文档的出版商或作者与文档的总体主题(或相关事项)的关系,并且不包含可能直接属于该总体主题的内容。(因此,如果文档部分是数学教科书,则次要章节可能不会解释任何数学。)这种关系可能是与该主题或相关事项的历史联系,或者关于它们的法律、商业、哲学、伦理或政治立场。

“不变章节”是某些次要章节,其标题在声明文档已根据本许可证发布的声明中被指定为不变章节的标题。 如果某个章节不符合上述次要章节的定义,则不允许将其指定为不变章节。 文档可能包含零个不变章节。 如果文档未标识任何不变章节,则不存在不变章节。

“封面文字”是在声明文档已根据本许可证发布的声明中被列为封面文字或封底文字的某些简短的文本段落。 封面文字最多可以有 5 个单词,封底文字最多可以有 25 个单词。

文档的“透明”副本是指以一种可供公众使用的规范表示的机器可读副本,该副本适合使用通用文本编辑器(对于由像素组成的图像)或通用绘图程序(对于绘图)直接修改文档,并且适合输入到文本格式化程序或自动翻译成各种适合输入到文本格式化程序的格式。 以其他方式透明的文件格式制作的副本,其标记或缺少标记已安排为阻止或劝阻读者进行后续修改,则不是透明的。 如果用于任何大量的文本,则图像格式不是透明的。 不“透明”的副本称为“不透明”。

透明副本的合适格式示例包括没有标记的纯 ASCII、Texinfo 输入格式、LaTeX 输入格式、使用公开可用的 DTD 的 SGML 或 XML,以及符合标准的简单 HTML、PostScript 或 PDF,专为人工修改而设计。 透明图像格式的示例包括 PNG、XCF 和 JPG。 不透明格式包括只能由专有文字处理器读取和编辑的专有格式、DTD 和/或处理工具通常不可用的 SGML 或 XML,以及某些文字处理器仅出于输出目的而生成的机器生成的 HTML、PostScript 或 PDF。

“标题页”对于印刷书籍而言,是指标题页本身,以及包含本许可证要求出现在标题页上的材料所需的所有后续页面。 对于没有标题页格式的作品,“标题页”是指作品标题最突出显示附近的文本,该文本位于正文的开头之前。

“标题为 XYZ”的章节是指文档的命名子单元,其标题要么正是 XYZ,要么包含 XYZ,括号中带有以另一种语言翻译 XYZ 的文本。(此处 XYZ 代表下面提到的特定章节名称,例如“致谢”、“奉献”、“背书”或“历史”。)当你修改文档时“保留”此类章节的“标题”是指根据此定义,它仍然是一个“标题为 XYZ”的章节。

文档可能在声明本许可证适用于该文档的声明旁边包含免责声明。 这些免责声明被认为是通过引用包含在本许可证中的,但仅在免责声明方面:这些免责声明可能具有的任何其他含义均无效,并且对本许可证的含义没有影响。


A.3. 逐字复制

你可以以任何介质复制和分发文档,无论是商业的还是非商业的,前提是在所有副本中都复制了本许可证、版权声明以及声明本许可证适用于该文档的许可证声明,并且你没有在本许可证的声明中添加任何其他条件。 你不得使用技术措施来阻止或控制你制作或分发的副本的阅读或进一步复制。 但是,你可以接受报酬以换取副本。 如果你分发足够多的副本,你还必须遵守第 3 节中的条件。

你也可以在上述相同条件下借出副本,并且你可以公开展示副本。


A.4. 批量复制

如果您出版该文档的印刷版(或常用印刷封面的媒体版本),数量超过100份,且该文档的许可声明要求提供封面文字,您必须在封面上清晰、易读地包含所有这些封面文字:在封面上放置正面封面文字,在封底放置背面封面文字。 两个封面还必须清晰、易读地标明您是这些副本的出版商。封面必须以同等突出和可见的方式呈现完整的标题和标题中的所有文字。您也可以在封面上添加其他材料。对封面的更改仅限于保留文档标题并满足这些条件的复制,在其他方面可以被视为逐字复制。

如果任何一个封面所需的文字量太大,无法清晰地放置,您应该将首先列出的文字(尽可能多地合理放置)放在实际封面上,并将剩余的文字继续放在相邻的页面上。

如果您出版或分发超过100份的文档不透明副本,您必须随每个不透明副本包含一份机器可读的透明副本,或者在每个不透明副本中或随附声明一个计算机网络位置,公众可以通过该位置使用公共标准网络协议下载完整的文档透明副本,且不包含任何附加材料。 如果您使用后一种选项,则必须采取合理谨慎的措施,在您开始大量分发不透明副本时,确保该透明副本在声明的位置保持可访问状态,至少直到您向公众分发该版本的最后一个不透明副本(直接或通过您的代理商或零售商)后一年。

建议(但不是必需)您在重新分发大量副本之前与文档的作者联系,让他们有机会为您提供文档的更新版本。


A.5. 修改

您可以根据上述第2节和第3节的条件复制和分发文档的修改版本,前提是您以与本许可完全相同的许可发布修改版本,使修改版本扮演文档的角色,从而将修改版本的发布和修改许可给拥有该版本副本的任何人。 此外,您必须在修改版本中执行以下操作:

  1. 在标题页上(如果适用,在封面上)使用与文档标题不同的标题,也与先前版本的标题不同(如果存在任何先前版本,则应在文档的历史记录部分中列出)。 如果该版本的原始出版商给予许可,您可以使用与先前版本相同的标题。

  2. 在标题页上,将修改版本中修改的作者列为作者,以及文档的至少五个主要作者(如果文档的主要作者少于五个,则列出其所有主要作者),除非他们免除您的此项要求。

  3. 在标题页上,将修改版本的出版商列为出版商。

  4. 保留文档的所有版权声明。

  5. 在其他版权声明旁边添加适合您修改的版权声明。

  6. 在版权声明之后立即包含一个许可声明,允许公众根据本许可的条款使用修改版本,格式如下面的附录所示。

  7. 在该许可声明中保留文档许可声明中给出的不变部分和所需封面文字的完整列表。

  8. 包含本许可的未修改副本。

  9. 保留标题为“历史记录”的部分,保留其标题,并在其中添加一个项目,至少说明标题页上给出的修改版本的标题、年份、新作者和出版商。 如果文档中没有标题为“历史记录”的部分,则创建一个部分,说明标题页上给出的文档的标题、年份、作者和出版商,然后添加一个项目,描述修改版本,如前一句中所述。

  10. 保留文档中给出的用于公众访问文档透明副本的网络位置(如果有),以及文档中给出的用于访问其所基于的先前版本的网络位置。 这些可以放在“历史记录”部分中。 您可以省略在文档本身发布前至少四年发布的作品的网络位置,或者如果其所指版本的原始出版商给予许可。

  11. 对于任何标题为“致谢”或“献词”的部分,保留该部分的标题,并保留该部分中每个贡献者致谢和/或献词的所有实质内容和语气。

  12. 保留文档的所有不变部分,其文本和标题均不得更改。 节号或等效内容不被视为节标题的一部分。

  13. 删除任何标题为“认可”的部分。 此类部分不得包含在修改版本中。

  14. 不要将任何现有部分重命名为标题为“认可”,也不要使其标题与任何不变部分冲突。

  15. 保留所有免责声明。

如果修改版本包含符合辅助部分条件且未包含从文档复制的材料的新前言部分或附录,您可以选择将其中一些或全部部分指定为不变部分。 为此,请将它们的标题添加到修改版本的许可声明中的不变部分列表中。 这些标题必须与其他任何节标题不同。

您可以添加一个标题为“认可”的部分,前提是它只包含各方对您的修改版本的认可——例如,同行评审声明或文本已获得某个组织批准为标准的权威定义。

您可以在修改版本中的封面文字列表末尾添加最多五个单词的一段文字作为正面封面文字,以及最多25个单词的一段文字作为背面封面文字。 任何一个实体只能添加一段正面封面文字和一段背面封面文字(或通过其安排)。 如果文档已经包含同一封面的封面文字,该文字先前由您添加,或者由您代表的同一实体安排添加,则您不得再添加另一个;但是您可以替换旧的文字,但必须获得添加旧文字的先前出版商的明确许可。

文档的作者和出版商不通过本许可授予使用其名称进行宣传或断言或暗示对任何修改版本的认可的许可。


A.6. 合并文档

您可以根据上述第4节中定义的修改版本条款,将文档与根据本许可发布的其他文档合并,前提是您在合并中包含所有原始文档的所有不变部分,且不得修改,并在其许可声明中将它们全部列为合并作品的不变部分,并且您保留它们所有的免责声明。

合并后的作品只需要包含本许可的一个副本,并且多个相同的不变部分可以用一个副本代替。 如果有多个具有相同名称但内容不同的不变部分,则通过在其末尾添加括号中的该部分的原始作者或出版商的姓名(如果已知),或者添加一个唯一的数字,使每个此类部分的标题都是唯一的。 在合并作品的许可声明中的不变部分列表中对节标题进行相同的调整。

在合并中,您必须合并各个原始文档中标题为“历史记录”的任何部分,形成一个标题为“历史记录”的部分;同样,合并任何标题为“致谢”的部分以及任何标题为“献词”的部分。 您必须删除所有标题为“认可”的部分。


A.7. 文档集合

您可以创建一个由文档和根据本许可发布的其他文档组成的集合,并将各个文档中的本许可的单独副本替换为包含在该集合中的单个副本,前提是您在所有其他方面都遵循本许可关于每个文档的逐字复制的规则。

您可以从此类集合中提取单个文档,并根据本许可单独分发它,前提是您将本许可的副本插入到提取的文档中,并在关于该文档的逐字复制的所有其他方面都遵循本许可。


A.8. 与独立作品的聚合

将文档或其衍生物与其他单独且独立的文档或作品汇编到存储或分发介质的卷中,如果汇编产生的版权不用于限制汇编用户超出各个作品允许范围的合法权利,则称为“聚合”。 当文档包含在聚合中时,本许可不适用于聚合中不是文档衍生作品的其他作品。

如果第3节的封面文字要求适用于这些文档副本,则如果文档小于整个聚合的一半,则文档的封面文字可以放置在将文档括在聚合内的封面上,或者如果文档是电子形式,则放置在封面的电子等效物上。 否则,它们必须出现在将整个聚合括起来的印刷封面上。


A.9. 翻译

翻译被认为是一种修改,因此您可以按照第 4 节的条款分发文档的翻译版本。使用翻译替换不变部分需要获得其版权持有者的特别许可,但除了这些不变部分的原始版本之外,您还可以包含部分或全部不变部分的翻译。您可以包含本许可证的翻译,以及文档中的所有许可证声明和任何免责声明,前提是您同时包含本许可证的原始英文版本以及这些声明和免责声明的原始版本。如果本许可证或声明或免责声明的翻译版本与原始版本之间存在分歧,则以原始版本为准。

如果文档中的某个章节标题为“致谢”、“献词”或“历史”,则保留其标题(第 1 节)的要求(第 4 节)通常需要更改实际标题。


A.10. 终止

除非本许可证明确规定,否则您不得复制、修改、再许可或分发本文档。任何其他复制、修改、再许可或分发本文档的企图均无效,并将自动终止您在本许可证下的权利。但是,根据本许可证从您那里获得副本或权利的各方,只要这些各方始终完全遵守本许可证,其许可证就不会被终止。


A.11. 本许可证的未来修订

自由软件基金会可能会不时发布 GNU 自由文档许可证的新修订版本。这些新版本在精神上与当前版本相似,但在细节上可能会有所不同,以解决新的问题或疑虑。请参阅 https://gnu.ac.cn/copyleft/。

每个许可证版本都有一个唯一的版本号。如果文档指定本许可证的特定编号版本“或任何后续版本”适用于它,您可以选择遵循该指定版本或自由软件基金会发布的任何后续版本(非草案)的条款和条件。如果文档未指定本许可证的版本号,您可以选择自由软件基金会发布的任何版本(非草案)。


A.12. 附录:如何在您的文档中使用本许可证

要在您编写的文档中使用本许可证,请在文档中包含本许可证的副本,并在标题页之后添加以下版权和许可证声明:

版权所有 (c) 年份 您的姓名。 允许根据 GNU 自由文档许可证 1.2 版或自由软件基金会发布的任何后续版本的条款复制、分发和/或修改本文档;不包含不变部分,不包含封面文本,也不包含封底文本。许可证的副本包含在标题为“GNU 自由文档许可证”的章节中。

如果您有不变部分、封面文本和封底文本,请用以下内容替换“不包含...文本”行:

不变部分为:列出它们的标题,封面文本为:列出,封底文本为:列出。

如果您有不包含封面文本的不变部分,或者三种组合中的其他组合,请合并这两个选项以适应具体情况。

如果您的文档包含重要的程序代码示例,我们建议您选择一种自由软件许可证(例如 GNU 通用公共许可证)并行发布这些示例,以允许在自由软件中使用它们。