在我的系统上,我有两个加密磁盘:
- 包含 raspbianstretch 根分区的 crypt
- usb-crypt 是一个外部 USB 磁盘。该磁盘上使用 LVM。
两个磁盘都使用相同的密码进行保护,但根据“cryptsetup luksDump”,主密钥不同。两个磁盘均未使用密钥文件进行配置(每个 LUKS 容器仅使用一个密钥槽)。
系统启动时,会要求输入“crypt”密码,但 usb-crypt 会自动挂载,无需输入密码。注意:我从未加密的根分区开始,通过该设置,在启动过程中系统会要求我输入 usb-crypt 的密码。
这是详细设置:
$ sudo dmsetup ls --target crypt
crypt (254, 0)
usb-crypt (254, 1)
$ sudo cat /etc/fstab
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mapper/crypt / ext4 defaults,noatime 0 1
# ...
UUID=b9fb061f-0877-4d2c-bd3c-9c155b8f88a5 /mountpoint ext4 rw,auto 0 0
$ sudo cat /etc/crypttab
# <target name> <source device> <key file> <options>
crypt /dev/mmcblk0p2 none luks
usb-crypt UUID=31fb8df7-6148-4408-90a2-93b8ec752fa0 none luks
虽然只需输入一次密码很方便,但我很惊讶地看到这种行为。我原以为会被要求提供这两个密码。
这是否与在两个磁盘上使用相同的密码有关?还是U盘的主密钥自动保存在“crypt”加密根分区的某处?如果有人可以解释这里发生的事情,并可能对相关日志文件等提供一些提示,我将不胜感激。
提前致谢!
答案1
取决于询问您密码的初始化脚本正在用它做什么。
如果是的话systemd
,它可能只是一个功能。systemd-ask-password
带有可能负责的缓存功能。
https://www.freedesktop.org/software/systemd/man/systemd-ask-password.html
--accept-cached If passed, accept cached passwords, i.e. passwords previously entered. --multiple When used in conjunction with --accept-cached accept multiple passwords. This will output one password per line.
以这种方式,它会首先尝试您已经输入的密码,并且仅在不起作用时才要求输入其他密码。
这种想法的缺点是使用 LUKS 检查密码需要花费 1 秒的 CPU 时间,因此如果您有很多 LUKS 容器,这些尝试可能会减慢您的速度。但大多数人只有一两个密码,而且他们使用相同的密码实际上并不罕见。
我实际上无法找到专门负责此问题的源代码,因此上述只是猜测,我不知道您是否可以选择以某种方式禁用此功能。
找到了似乎是负责的代码,在 Github 上查看。
有一个 for 循环,每次迭代以 1开始tries = 0
并递增1。tries
该循环调用ifget_password()
并将bool accept_cached
其设置为 true tries == 0 && !arg_verify
。因此,如果在循环的第一次迭代中已经缓存了密码,它将仅返回缓存的密码。如果这些不起作用,下一次迭代将tries == 1
设置accept_cached
为 false,只有这样它才会要求您提供另一个密码来尝试。
密码列表被传递到attach_luks_or_plain()
。这将是第一次迭代中以前缓存的密码,以及所有后续迭代中的单个新密码,因此它不会重新尝试以前尝试过的密码(除非您继续输入相同的密码)。
至于将密码明文保存在内存中,密码列表被声明为 a ,_cleanup_strv_free_erase_ char **passwords = NULL;
这样至少听起来像是在某个时候会正确处理清理工作。
密钥总是在内存中的某个地方,那是没有办法的,crypt 需要 masterkey 才能工作,只要容器打开,你就可以随时看到它dmsetup table --showkeys
。
您通常会arg_tries = 3
尝试三次输入有效的密码,但如果您有多个容器并且缓存的密码不起作用,则只会尝试两次输入密码,因为缓存的密码尝试已经算作第一次尝试。我没有加密的 systemd 机器来测试这是否属实,或者我只是误读了某处的代码。