linux 磁盘加密和tpm搭配使用1

一.基本名称,容易混淆

1.dm-crypt是linux的2.6内核开始集成的一种磁盘加密功能。十几年来,连sche调度算法都被改了N次,但dm-crypt一直稳定在内核中,稳定性还是很好的。

2.cryptsetup是linux一般自带的一个用户态工具,用来操作dm-crypt。

[root@localhost mnt]# whereis cryptsetup
cryptsetup: /usr/sbin/cryptsetup /usr/share/man/man8/cryptsetup.8.gz

3.luks是dm-crypt 最常用的一种模式,因为是linux中最常用的,所以有人经常混淆这三个东西。

二.dm-crypt支持的类型

open <device> <name> --type <device_type>

              Opens (creates a mapping with) <name> backed by device <device>.

              Device type can be plain, luks (default), loopaes or tcrypt.

              For backward compatibility there are open command aliases:

              create (argument-order <name> <device>): open --type plain
              plainOpen: open --type plain
              luksOpen: open --type luks
              loopaesOpen: open --type loopaes
              tcryptOpen: open --type tcrypt-------这个在cryptsetup 的1.6版本之后才开始支持。

四种模型,建议使用luks。

PLAIN DM-CRYPT OR LUKS?
       Unless you understand the cryptographic background well, use LUKS.  With plain dm-crypt there are a number of possible user errors
       that massively decrease security. While LUKS cannot fix them all, it can lessen the impact for many of them.

由于cryptsetup 也在不停发展,在1.6的版本之后才开始支持tcrypt,所以如果要测试tcrypt 模式,建议使用高版本的内核,这样自带的cryptsetup 一般都支持。

# cryptsetup --version
cryptsetup 1.6.7

三.测试记录:

由于不同的模式有不同的参数,本文记录的是luks模式。

You can only call luksFormat on a LUKS device that is not mapped.

              <options> can be [--hash, --cipher, --verify-passphrase, --key-size, --key-slot, --key-file (takes precedence over optional
              second  argument),  --keyfile-offset, --keyfile-size, --use-random | --use-urandom, --uuid, --master-key-file, --iter-time,
              --header, --force-password].

              WARNING: Doing a luksFormat on an existing LUKS container will make all data the old container  permanently  irretrievable,
              unless you have a header backup.

怎么设置参数呢?如果没指定的话,cryptsetup 会使用默认参数。

先fdisk分配一个分区,本文例子中,分区是sdb2。

对比两次不同的算法搭配不同的模式的性能比较:

[root@localhost mnt]# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       583839 iterations per second
PBKDF2-sha256     361577 iterations per second
PBKDF2-sha512     231985 iterations per second
PBKDF2-ripemd160  464794 iterations per second
PBKDF2-whirlpool  234475 iterations per second
#  Algorithm | Key |  Encryption |  Decryption
     aes-cbc   128b   646.6 MiB/s  2649.2 MiB/s
 serpent-cbc   128b    79.2 MiB/s   535.7 MiB/s
 twofish-cbc   128b   170.5 MiB/s   352.5 MiB/s
     aes-cbc   256b   478.4 MiB/s  2049.6 MiB/s
 serpent-cbc   256b    90.6 MiB/s   553.2 MiB/s
 twofish-cbc   256b   183.2 MiB/s   353.4 MiB/s
     aes-xts   256b  2238.0 MiB/s  2244.4 MiB/s
 serpent-xts   256b   551.2 MiB/s   533.5 MiB/s
 twofish-xts   256b   342.4 MiB/s   349.7 MiB/s
     aes-xts   512b  1771.8 MiB/s  1767.3 MiB/s
 serpent-xts   512b   552.3 MiB/s   535.4 MiB/s
 twofish-xts   512b   343.8 MiB/s   349.3 MiB/s
[root@localhost mnt]# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       585142 iterations per second
PBKDF2-sha256     353293 iterations per second
PBKDF2-sha512     233224 iterations per second
PBKDF2-ripemd160  463151 iterations per second
PBKDF2-whirlpool  235741 iterations per second
#  Algorithm | Key |  Encryption |  Decryption
     aes-cbc   128b   646.2 MiB/s  2622.6 MiB/s
 serpent-cbc   128b    90.5 MiB/s   551.6 MiB/s
 twofish-cbc   128b   183.8 MiB/s   353.0 MiB/s
     aes-cbc   256b   479.0 MiB/s  2048.1 MiB/s
 serpent-cbc   256b    90.4 MiB/s   554.1 MiB/s
 twofish-cbc   256b   183.6 MiB/s   353.5 MiB/s
     aes-xts   256b  2237.1 MiB/s  2238.7 MiB/s
 serpent-xts   256b   554.0 MiB/s   534.2 MiB/s
 twofish-xts   256b   339.8 MiB/s   348.9 MiB/s
     aes-xts   512b  1773.2 MiB/s  1708.6 MiB/s
 serpent-xts   512b   553.3 MiB/s   535.7 MiB/s
 twofish-xts   512b   343.6 MiB/s   348.2 MiB/s

可以看到,aes搭配xts性能较高,所以我们创建加密分区的时候,使用这种模式。

cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512  luksFormat /dev/sdb2

这个表示加密方式是aes-xts-plain64,密钥长度为512,散列算法为sha512 。

[root@localhost mnt]# cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512  luksFormat /dev/sdb2

WARNING!
========
This will overwrite data on /dev/sdb2 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 

密码必须大于8位,且不能是简单密码,否则会无法通过。

用 LUKS 方式创建(格式化)加密盘之后,开始可以打开该盘用于操作了。

cryptsetup open  /dev/sdb2 caq_Encrypted_Fs
Enter passphrase for /dev/sdb2: 

输入之前的密码,open成功,由于默认的open格式是luks,所以不需要输入对应的格式。否则,需要按照下面的格式来。

 Opens (creates a mapping with) <name> backed by device <device>.

              Device type can be plain, luks (default), loopaes or tcrypt.

              For backward compatibility there are open command aliases:

              create (argument-order <name> <device>): open --type plain
              plainOpen: open --type plain
              luksOpen: open --type luks
              loopaesOpen: open --type loopaes
              tcryptOpen: open --type tcrypt

可以看到,在/dev/mapper下,有一个创建的虚拟设备了。

[root@localhost mnt]# ls /dev/mapper/caq_Encrypted_Fs
/dev/mapper/caq_Encrypted_Fs
[root@localhost mnt]# cryptsetup status /dev/mapper/caq_Encrypted_Fs
/dev/mapper/caq_Encrypted_Fs is active.
  type:    LUKS1
  cipher:  aes-xts-plain64
  keysize: 512 bits
  device:  /dev/sdb2
  offset:  4096 sectors
  size:    815104 sectors
  mode:    read/write

之后,我们所有的操作都是基于caq_Encrypted_Fs。比如挂载,读写等。

创建一个目录,用来挂载。

mkdir -p /mnt/caqEncryptedFilesystem/

然后对我们的盘进行建立文件系统的操作:

root@localhost mnt]# mkfs.xfs -b size=4096 -d sunit=0,swidth=0 /dev/mapper/caq_Encrypted_Fs 
meta-data=/dev/mapper/caq_Encrypted_Fs isize=512    agcount=4, agsize=25472 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=101888, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=1605, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@localhost mnt]# mount /dev/mapper/caq_Encrypted_Fs /mnt/caqEncryptedFilesystem/

挂载之后,可以对/mnt/caqEncryptedFilesystem/ 进行正常的文件读写了。

[root@localhost mnt]# cd /mnt/caqEncryptedFilesystem/
[root@localhost caqEncryptedFilesystem]# ls
[root@localhost caqEncryptedFilesystem]# 
[root@localhost caqEncryptedFilesystem]# 
[root@localhost caqEncryptedFilesystem]# dd if=/dev/zero of=caq.txt bs=4K count=10
10+0 records in
10+0 records out
40960 bytes (41 kB) copied, 0.000195657 s, 209 MB/s
[root@localhost caqEncryptedFilesystem]# ls *
caq.txt
[root@localhost caqEncryptedFilesystem]# echo "do it yourself" >>caq.txt2
[root@localhost caqEncryptedFilesystem]# ls
caq.txt  caq.txt2

加密,顾名思义,保存在硬盘上的数据,应该就不是明文了,但是我们cat 看到的文件和写的文件是一样的,是因为经过了解密。如果硬盘丢失了,就不会有各种艳照门出现了。

描述到此,也没看出分区加密和tpm什么关系啊,下面,开始描述两者结合产生的效果。

我们知道,tpm能够加密文件,如果我们的加密分区的密码是以文件的形式存在,两者就很好地配合了。来看下面的操作:

先产生一个随机文件:

dd if=/dev/urandom of=/tmp/passwd_caq bs=1k count=64

我们看dump默认的输出,是密码数组,所谓密码数组,是指可以用一组独立的密码来解密这个加密的分区。

# cryptsetup luksDump /dev/sdb2
LUKS header information for /dev/sdb2

Version:           1
Cipher name:       aes
Cipher mode:       xts-plain64
Hash spec:         sha512
Payload offset:    4096
MK bits:           512
MK digest:         e6 12 5c 12 e8 ab 1d 8a 81 ac cc f6 e5 7d bb d0 e2 6c 5f ed 
MK salt:           a8 03 1d b6 05 c8 64 cb de f4 2a 64 0d 77 5b cb 
                   b9 11 aa e7 d2 58 eb aa aa 68 24 8f bf 16 26 f2 
MK iterations:     28000
UUID:              da24c447-4e62-463b-b533-89bd7fdf3238

Key Slot 0: ENABLED
    Iterations:             112280
    Salt:                   10 8f 31 ab 38 9a e1 28 94 df 61 0b 43 62 5e 94 
                              57 0c c7 18 fc e8 d6 39 e7 5d d1 93 76 0e f1 13 
    Key material offset:    8
    AF stripes:                4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

目前使用了第一个密码,后面的是空的,我们用来存密码文件。

# cryptsetup luksAddKey /dev/sdb2 /tmp/passwd_caq
Enter any passphrase: 

现在,/tmp/passwd_caq 就成为了这个加密分区的密码文件了。重新dump一下,发现用掉了一个组,还剩下6个。

# cryptsetup luksDump /dev/sdb2
LUKS header information for /dev/sdb2

Version:           1
Cipher name:       aes
Cipher mode:       xts-plain64
Hash spec:         sha512
Payload offset:    4096
MK bits:           512
MK digest:         e6 12 5c 12 e8 ab 1d 8a 81 ac cc f6 e5 7d bb d0 e2 6c 5f ed 
MK salt:           a8 03 1d b6 05 c8 64 cb de f4 2a 64 0d 77 5b cb 
                   b9 11 aa e7 d2 58 eb aa aa 68 24 8f bf 16 26 f2 
MK iterations:     28000
UUID:              da24c447-4e62-463b-b533-89bd7fdf3238

Key Slot 0: ENABLED
    Iterations:             112280
    Salt:                   10 8f 31 ab 38 9a e1 28 94 df 61 0b 43 62 5e 94 
                              57 0c c7 18 fc e8 d6 39 e7 5d d1 93 76 0e f1 13 
    Key material offset:    8
    AF stripes:                4000
Key Slot 1: ENABLED
    Iterations:             110917
    Salt:                   91 18 c0 0c 4d 19 c2 96 85 d1 b6 4a a6 6d 8e 90 
                              d3 96 5f d0 d4 78 28 a3 27 4d 4d ad 94 74 98 28 
    Key material offset:    512
    AF stripes:                4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

然后我们umount这个挂载的路径,看新增加的密码文件能否解密我们的分区。

[root@localhost mnt]# umount /mnt/caqEncryptedFilesystem/
[root@localhost mnt]# cryptsetup close /dev/mapper/caq_Encrypted_Fs 
[root@localhost mnt]# cryptsetup --key-file /tmp/passwd_caq luksOpen /dev/sdb2 caq_Encrypted_Fs

从第三行可以看出,再也不用输入密码了,直接从文件中读密码。

下面的步骤,就简单了,使用之前的一篇博客,《linux tpm 测试完整记录,亲测有效》来再次加密这个/tmp/passwd_caq,就可以统一在tpm中管理我们的分区加密密码了。

水平有限,如果有错误,请帮忙提醒我。如果您觉得本文对您有帮助,可以点击下面的 推荐 支持一下我。版权所有,需要转发请带上本文源地址,博客一直在更新,欢迎 关注 。
原文地址:https://www.cnblogs.com/10087622blog/p/7852786.html