USB HDDをLUKS&Btrfsで初期化

USBのケースに2.5インチHDDを入れて初期化しました．
LUKSで暗号化のためにCryptsetupを，透過圧縮，重複排除も使いたいということでBtrFSを利用しました．

余分なストレージの取り外し

まず，作業PCから余分なHDDやSD cardなどのストレージを取り外しておきます．これは誤って対象外のストレージを消去してしまわないようにするためです．

作業ストレージの取り付けと確認

作業ハードディスクを取り付ける前にdmesgコマンドを -W, --follow-new オプション付きで実行しておきます．これにより新しいメッセージが表示されます．終了時は ctrl+c で終了できます．

dmesgコマンドを実行後USB接続してメッセージを確認します．

[Nov10 19:51] usb 2-4: new SuperSpeed USB device number 6 using xhci_hcd
[ +0.031413] usb 2-4: New USB device found, idVendor=0bda, idProduct=9201, bcdDevice=f2.00
[ +0.000017] usb 2-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ +0.000007] usb 2-4: Product: RTL9201
[ +0.000005] usb 2-4: Manufacturer:-W, --follow-new Realtek
[ +0.000004] usb 2-4: SerialNumber: 012345679446
[ +0.000623] usb 2-4: Device is not authorized for usage

今回は Device is not authorized for usage となっています．USBGuardでブロックされているので許可します．

$ usbguard list-devices | grep block (1)
19: block id 0bda:9201 serial "012345679446" name "RTL9201" hash "qLSxXWok3I6aK/Wj7GKQnbe3aTW0PNGtemQcsnWzKfs=" parent-hash "prM+Jby/bFHCn2lNjQdAMbgc6tse3xVx+hZwjOPHSdQ=" via-port "2-4" with-interface { 08:06:50 08:06:62 } with-connect-type "hotplug"
$ usbguard allow-device 19 (2)

USBGuardでブロックされているデバイスを表示

dmesgの内容と見比べて許可する

USBGuardで許可するとdmesgに続きが表示されました． sda として認識しているようです．

[ +27.584359] usb 2-4: Enable of device-initiated U1 failed.
[ +0.000893] usb 2-4: Enable of device-initiated U2 failed.
[ +0.028833] usb 2-4: Enable of device-initiated U1 failed.
[ +0.000492] usb 2-4: Enable of device-initiated U2 failed.
[ +0.002026] scsi host0: uas
[ +0.000251] usb 2-4: authorized to connect
[ +0.142409] scsi 0:0:0:0: Direct-Access HGST HTS 541050A9E680 1.02 PQ: 0 ANSI: 6
[ +0.033919] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ +0.280706] sd 0:0:0:0: [sda] 976773168 512-byte logical blocks: (500 GB/466 GiB)
[ +0.000015] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ +0.001535] sd 0:0:0:0: [sda] Write Protect is off
[ +0.000016] sd 0:0:0:0: [sda] Mode Sense: 37 00 00 08
[ +0.002897] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ +0.063143] sd 0:0:0:0: [sda] Preferred minimum I/O size 512 bytes not a multiple of physical block size (4096 bytes)
[ +0.040509] sd 0:0:0:0: [sda] Attached SCSI disk

dmesgに表示されたvidでlsusbの内容を確認します．

$ lsusb -d 0bda:
Bus 002 Device 006: ID 0bda:9201 Realtek Semiconductor Corp. RTL9201
$ lsusb -t
/: Bus 001.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/12p, 480M
|__ Port 005: Dev 002, If 0, Class=Video, Driver=uvcvideo, 480M
|__ Port 005: Dev 002, If 1, Class=Video, Driver=uvcvideo, 480M
|__ Port 007: Dev 008, 12M
|__ Port 010: Dev 004, If 0, Class=Wireless, Driver=btusb, 12M
|__ Port 010: Dev 004, If 1, Class=Wireless, Driver=btusb, 12M
/: Bus 002.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/6p, 10000M
|__ Port 004: Dev 006, If 0, Class=Mass Storage, Driver=uas, 5000M

lsblkでも確認

$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 465.8G 0 disk
nvme0n1 259:0 0 476.9G 0 disk
|-nvme0n1p1 259:1 0 512M 0 part /boot/efi
|-nvme0n1p2 259:2 0 488M 0 part /boot
`-nvme0n1p3 259:3 0 476G 0 part
`-nvme0n1p3_crypt 254:0 0 475.9G 0 crypt
|-tp--l13--vg-swap 254:1 0 16.8G 0 lvm [SWAP]
`-tp--l13--vg-root 254:2 0 459.2G 0 lvm /

fdiskで容量やモデル名を確認して該当のデバイスであることを確認します．

$ sudo fdisk -l /dev/sda
Disk /dev/sda: 465.76 GiB, 500107862016 bytes, 976773168 sectors
Disk model: 541050A9E680
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

中古で購入したディスクでフォーマットされているようですが，photorecで中を覗いてみるとWindowsのシステムファイルなどが見えました．復元はせずに終了して次に進みます．

$ sudo photorec /dev/sda

ディスクの消去

これは時間もかかるしやらなくてもいいかなと思うのですが念の為ディスクの内容を消去しておきます．1回ランダムで上書きした後0で埋めています．

$ sudo shred -n1 -z -v /dev/sda
shred: /dev/sda: pass 1/2 (random)...
shred: /dev/sda: pass 1/2 (random)...402MiB/466GiB 0%
shred: /dev/sda: pass 1/2 (random)...869MiB/466GiB 0%
:
shred: /dev/sda: pass 1/2 (random)...463GiB/466GiB 99%
shred: /dev/sda: pass 1/2 (random)...464GiB/466GiB 99%
shred: /dev/sda: pass 1/2 (random)...465GiB/466GiB 99%
shred: /dev/sda: pass 1/2 (random)...466GiB/466GiB 100%
shred: /dev/sda: pass 2/2 (000000)...
shred: /dev/sda: pass 2/2 (000000)...387MiB/466GiB 0%
shred: /dev/sda: pass 2/2 (000000)...854MiB/466GiB 0%
shred: /dev/sda: pass 2/2 (000000)...1.2GiB/466GiB 0%
:
shred: /dev/sda: pass 2/2 (000000)...466GiB/466GiB 100%

randomが2時間近く，0が1.5時間と少しくらいかかりました．

Cryptsetupのベンチマーク

ディスクの消去中暇なのでベンチマークをとってみました．

ThinkPad L13(Intel® Core™ i7-10510U)

$ /sbin/cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 1034098 iterations per second for 256-bit key
PBKDF2-sha256 1593580 iterations per second for 256-bit key
PBKDF2-sha512 1046483 iterations per second for 256-bit key
PBKDF2-ripemd160 731224 iterations per second for 256-bit key
PBKDF2-whirlpool 559538 iterations per second for 256-bit key
argon2i 7 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id 7 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 1063.9 MiB/s 2951.4 MiB/s
serpent-cbc 128b 84.8 MiB/s 570.7 MiB/s
twofish-cbc 128b 217.5 MiB/s 322.2 MiB/s
aes-cbc 256b 697.5 MiB/s 2572.2 MiB/s
serpent-cbc 256b 87.0 MiB/s 605.4 MiB/s
twofish-cbc 256b 225.6 MiB/s 288.2 MiB/s
aes-xts 256b 2564.0 MiB/s 2645.4 MiB/s
serpent-xts 256b 478.9 MiB/s 527.6 MiB/s
twofish-xts 256b 286.5 MiB/s 290.9 MiB/s
aes-xts 512b 2470.2 MiB/s 2223.5 MiB/s
serpent-xts 512b 502.4 MiB/s 562.8 MiB/s
twofish-xts 512b 312.6 MiB/s 293.5 MiB/s

RasperryPi model 3B

$ /sbin/cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 99750 iterations per second for 256-bit key
PBKDF2-sha256 161617 iterations per second for 256-bit key
PBKDF2-sha512 126762 iterations per second for 256-bit key
PBKDF2-ripemd160 81310 iterations per second for 256-bit key
PBKDF2-whirlpool 23710 iterations per second for 256-bit key
argon2i 4 iterations, 124356 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id 4 iterations, 115630 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 23.9 MiB/s 48.9 MiB/s
serpent-cbc 128b N/A N/A
twofish-cbc 128b 17.1 MiB/s 21.4 MiB/s
aes-cbc 256b 20.6 MiB/s 36.6 MiB/s
serpent-cbc 256b N/A N/A
twofish-cbc 256b 19.2 MiB/s 20.4 MiB/s
aes-xts 256b 52.6 MiB/s 46.0 MiB/s
serpent-xts 256b N/A N/A
twofish-xts 256b 18.8 MiB/s 20.9 MiB/s
aes-xts 512b 42.4 MiB/s 34.0 MiB/s
serpent-xts 512b N/A N/A
twofish-xts 512b 21.5 MiB/s 20.5 MiB/s

RasperryPi 3Bにぶら下げたいなと思っているのですがはやはり遅いですね．AES支援のあるSBCだとましになるんでしょうが手持ちがないので諦めます．

Cryptsetupで初期化

luksFormatで初期化します．ここでパスフレーズを設定しますが，これが弱いと意味がないので強いものにしましょう．

$ sudo cryptsetup luksFormat /dev/sda

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

Are you sure? (Type 'yes' in capital letters): YES (1)
Enter passphrase for /dev/sda: (2)
Verify passphrase:

大文字で YES で進む

パスフレーズを2回設定，Keyslot 0に設定される

暗号化情報確認

念の為暗号化LUKSパーティションの確認をします．

$ sudo cryptsetup luksDump /dev/sda
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 28dee849-e142-49bc-96c2-be62adfc9309
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 4096 [bytes]

Keyslots:
0: luks2
Key: 512 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 512 bits
PBKDF: argon2id
Time cost: 6
Memory: 1048576
Threads: 4
Salt: 60 50 4a 09 0d ed 44 1d 53 52 04 f5 71 15 58 40
42 8b 7d 36 8f 7c f7 b5 2f 7f af 79 1f 68 e8 29
AF stripes: 4000
AF hash: sha256
Area offset:32768 [bytes]
Area length:258048 [bytes]
Digest ID: 0
Tokens:
Digests:
0: pbkdf2
Hash: sha256
Iterations: 63381
Salt: 88 19 5e 89 5a 22 dd f5 7e 20 a3 b6 e3 d3 87 1b
f8 ec e0 d9 cc ff 86 01 3b a1 ee 44 8b db 31 e6
Digest: e7 c3 5d 78 d2 9c 51 d8 5b 67 d7 15 27 9d 72 73
91 a1 64 b3 36 cf 16 4b c0 2b 9b 5f b6 0d 05 8d

Cryptsetupでディスクをアンロック

hddというデバイスにマッピングしています．既定値で作成したので特にオプションはなし．

$ sudo cryptsetup open /dev/sda hdd
Enter passphrase for /dev/sda:
$ ls /dev/mapper/hdd
/dev/mapper/hdd

ファイルシステムの作成

ここからは通常のファイルシステムと同じです．

$ sudo fdisk /dev/mapper/hdd

Welcome to fdisk (util-linux 2.40.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS (MBR) disklabel with disk identifier 0x6407f54a.

Command (m for help): p
Disk /dev/mapper/hdd: 465.75 GiB, 500091084800 bytes, 122092550 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x6407f54a

Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (256-122092549, default 256):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (256-122092549, default 122092549):

Created a new partition 1 of type 'Linux' and of size 465.7 GiB.

Command (m for help): p
Disk /dev/mapper/hdd: 465.75 GiB, 500091084800 bytes, 122092550 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x6407f54a

Device Boot Start End Sectors Size Id Type
/dev/mapper/hdd-part1 256 122092549 122092294 465.7G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Invalid argument

The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or partx(8).

$ sudo partprobe /dev/mapper/hdd
$ sudo fdisk -l /dev/mapper/hdd
Disk /dev/mapper/hdd: 465.75 GiB, 500091084800 bytes, 122092550 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x6407f54a

Device Boot Start End Sectors Size Id Type
/dev/mapper/hdd1 256 122092549 122092294 465.7G 83 Linux

BtrFSで初期化

$ sudo fdisk -l /dev/mapper/hdd
Disk /dev/mapper/hdd: 465.75 GiB, 500091084800 bytes, 122092550 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x6407f54a

Device Boot Start End Sectors Size Id Type
/dev/mapper/hdd1 256 122092549 122092294 465.7G 83 Linux

mount

$ sudo mount /dev/mapper/hdd1 /mnt
$ mount | grep /dev/mapper/hdd1
/dev/mapper/hdd1 on /mnt type btrfs (rw,relatime,space_cache=v2,subvolid=5,subvol=/)
$ df /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/hdd1 488369176 5920 486254592 1% /mnt

zstdで透過圧縮するようremount

$ sudo mount -o remount,compress=zstd /dev/mapper/hdd1
$ mount | grep /dev/mapper/hdd1
/dev/mapper/hdd1 on /mnt type btrfs (rw,relatime,compress=zstd:3,space_cache=v2,subvolid=5,subvol=/)

透過圧縮が効いているのを確認

$ sudo chown `id -u`:`id -g` /mnt (1)
$ dd if=/dev/zero of=/mnt/zero bs=1M count=2048 (2)
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 0.979651 s, 2.2 GB/s
$ ls -s /mnt/zero (3)
2097152 /mnt/zero
$ df -H /mnt (4)
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/hdd1 501G 79M 498G 1% /mnt

自分の権限にする

2GBほどの中身が0のファイルを作成

2GBのファイルが出来ているのを確認

2GBのファイルがあるけどファイルシステムは79MBしか使っていないのを確認

アンマウント，暗号化FSのクローズ

$ sudo umount /mnt (1)
$ sudo cryptsetup close hdd (2)
$ udisksctl power-off -b /dev/sda (3)
$ ls /dev/sda
ls: cannot access '/dev/sda': No such file or directory

ファイルシステムのアンマウント

暗号化FSのクローズ

ドライブの電源オフ

環境

$ dpkg-query -W cryptsetup fdisk btrfs-progs udisks2
btrfs-progs 6.6.3-1.2+b2
cryptsetup 2:2.7.5-1
fdisk 2.40.2-10
udisks2 2.10.1-11
$ lsb_release -dr
Description: Debian GNU/Linux trixie/sid
Release: n/a
$ arch
x86_64