如何从USB加载LUKS密码,回到键盘?

And*_*rew 13 linux encryption disk luks

我想建立一个具有全磁盘加密功能的无头Linux(Debian Wheezy)PC,能够通过USB驱动器或通过键盘输入密码来解锁磁盘.我的出发点是在Debian安装程序中使用基本的整个磁盘加密选项进行全新安装,该选项管理除了/ boot之外的所有内容作为LUKS加密的逻辑卷组并给我键盘选项.我将在答案中描述我当前的解决方案,希望它会有用,其他人可以改进它.

以下是我遇到的一些问题:

  • 设置密码并将其放在USB驱动器上.

  • 及时加载USB模块.

  • 在尝试从中读取之前,等待USB驱动器被Linux识别.

  • 识别正确的USB驱动器(不是恰好插入的其他驱动器).

  • 写一个"keyscript"来从USB驱动器中取出密码.

  • 确保在所有USB故障情况下,键盘的后退都会出现问题.

我将接受一个有重大改进的答案,并提供有助于提供贡献的答案.

And*_*rew 21

我的很多解决方案都来自帖子,使用LUKS Passphrase的USB密钥.

  1. 创建一个随机密码:

    dd if=/dev/urandom bs=1 count=256 > passphrase
    
    Run Code Online (Sandbox Code Playgroud)
  2. 插入USB驱动器. dmesg输出将显示设备名称; 假设/dev/sdd.弄清楚它的大小:

    blockdev --getsize64 /dev/sdd
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我决定在原始设备的末尾安装密码短语,以确定它可能在任何意外使用USB驱动器后继续存在.

    dd if=passphrase of=/dev/sdd bs=1 seek=<size-256>
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将密码添加到LUKS卷:

    cryptsetup luksAddKey /dev/sda5 passphrase
    
    Run Code Online (Sandbox Code Playgroud)

    这不会影响安装程序现有的手动密码.密码短语文件可以删除:

    rm passphrase
    
    Run Code Online (Sandbox Code Playgroud)
  5. 找到USB记忆棒的唯一名称,以便我们在出现时识别它:

    ls -l /dev/disk/by-id | grep -w sdd
    
    Run Code Online (Sandbox Code Playgroud)

    你应该看到一个符号链接.我会打电话给它/dev/disk/by-id/<ID>.

  6. 编辑/etc/crypttab.您应该看到如下行:

    sdc5_crypt UUID=b9570e0f-3bd3-40b0-801f-ee20ac460207 none luks
    
    Run Code Online (Sandbox Code Playgroud)

    将其修改为:

    sdc5_crypt UUID=b9570e0f-3bd3-40b0-801f-ee20ac460207 /dev/disk/by-id/<ID> luks,keyscript=/bin/passphrase-from-usb
    
    Run Code Online (Sandbox Code Playgroud)
  7. keyscript上面提到的需要读取USB设备的密码.但是,它还需要做更多的事情.要了解它的使用方法,请检查/usr/share/initramfs-tools/scripts/local-top/cryptroot启动时运行的脚本以解锁根设备.注意,当keyscript设置a时,它只是运行并且输出通过管道输送到luksOpen没有其他检查.无法发出错误信号(USB驱动器不存在)或回退到键盘输入.如果密码短语失败,则会在循环中再次运行keyscript,最多会运行一次; 但是我们没有被告知我们正在进行哪次迭代.此外,我们无法控制keyscript何时运行,因此我们无法确定Linux是否已识别USB驱动器.

    我用一些黑客解决了这个问题:

    1. 轮询USB驱动器并等待3秒钟以显示它.这对我有用,但我很想知道更好的方法.

    2. /passphrase-from-usb-tried首次运行时创建一个虚拟文件,表明我们至少运行过一次.

    3. 如果我们至少运行过一次,或者找不到USB驱动器,请运行用于键盘输入的askpass程序cryptroot.

    最后的剧本:

    #!/bin/sh
    
    set -e
    
    if ! [ -e /passphrase-from-usb-tried ]; then
        touch /passphrase-from-usb-tried
        if ! [ -e "$CRYPTTAB_KEY" ]; then
            echo "Waiting for USB stick to be recognized..." >&2
            sleep 3
        fi
        if [ -e "$CRYPTTAB_KEY" ]; then
            echo "Unlocking the disk $CRYPTTAB_SOURCE ($CRYPTTAB_NAME) from USB key" >&2
            dd if="$CRYPTTAB_KEY" bs=1 skip=129498880 count=256 2>/dev/null
            exit
        else
            echo "Can't find $CRYPTTAB_KEY; USB stick not present?" >&2
        fi
    fi
    
    /lib/cryptsetup/askpass "Unlocking the disk $CRYPTTAB_SOURCE ($CRYPTTAB_NAME)\nEnter passphrase: "
    
    Run Code Online (Sandbox Code Playgroud)

    最后,我们需要确保initramfs中提供此脚本.创建/etc/initramfs-tools/hooks/passphrase-from-usb包含:

    #!/bin/sh
    
    PREREQ=""
    
    prereqs() {
            echo "$PREREQ"
    }
    
    case "$1" in
            prereqs)
                    prereqs
                    exit 0
            ;;
    esac
    
    . "${CONFDIR}/initramfs.conf"
    . /usr/share/initramfs-tools/hook-functions
    
    copy_exec /bin/passphrase-from-usb /bin
    
    Run Code Online (Sandbox Code Playgroud)
  8. 我的initramfs中没有USB驱动程序.(看来它们在Debian的更高版本中是默认的.)我必须通过添加到/etc/initramfs-tools/modules以下内容来添加它们:

    uhci_hcd
    ehci_hcd
    usb_storage
    
    Run Code Online (Sandbox Code Playgroud)
  9. 完成所有操作后,更新initramfs:

    update-initramfs -u
    
    Run Code Online (Sandbox Code Playgroud)

  • 这可能是使用`/ dev/random`而不是`/ dev/urandom`的少数时间之一. (3认同)
  • @Rondo,我认为这句话是关于每次启动时生成一个新的随机密钥.在这种情况下,密钥在引导时间之前生成一次,因此这不应该是一个问题.最坏的情况是,用户可以生成更多的熵,直到密钥完成. (2认同)

Ole*_*nge 5

如果我可以简单地拥有一个包含可以解锁磁盘的密码的小型 USB 记忆棒,那对我来说将是理想的。这不仅对服务器很方便(您可以将 USB 记忆棒留在服务器中 - 目标是能够返回损坏的硬盘而不必担心机密数据),它对我的​​笔记本电脑也很有用:插入启动时 U 盘,解锁密码盘后将其取出。

我现在编写了一个补丁,它将在所有设备的根目录中搜索文件“cryptkey.txt”,并尝试将每一行作为密钥进行解密。如果失败:恢复输入密码短语。

这确实意味着密钥不能包含 \n,但这也适用于任何键入的密钥。好处是您可以使用同一个 U 盘来存储多台机器的密钥:您不需要为每台机器单独使用一个 U 盘。因此,如果您的物理钥匙圈中有一个 USB 驱动器,那么您可以在物理关闭时为所有启动的机器使用相同的驱动器。

您添加密钥:

cryptsetup luksAddKey /dev/sda5
Run Code Online (Sandbox Code Playgroud)

然后将相同的密钥作为一行放在 USB/MMC 磁盘上名为“cryptkey.txt”的文件中。补丁在这里:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=864647

如果您的 initramfs 中不存在 USB 驱动程序、MMC 驱动程序或文件系统,您需要通过添加到 /etc/initramfs-tools/modules 来添加它们:

uhci_hcd
ehci_hcd
usb_storage
nls_utf8
nls_cp437
vfat
fat
sd_mod
mmc_block
tifm_sd
tifm_core
mmc_core
tifm_7xx1
sdhci
sdhci_pci
Run Code Online (Sandbox Code Playgroud)

全部完成后,更新 initramfs:

update-initramfs -u
Run Code Online (Sandbox Code Playgroud)

可以在以下位置找到补丁和文件:https : //gitlab.com/ole.tange/tangetools/tree/master/decrypt-root-with-usb