LUKS2を拡張する方法

LUKS2を拡張する方法

数年前、LUKS1がデータを失うことなく右側と隣接する空き領域に拡張できる方法についてのガイドを読んでいましたが、抜け出すことはできませんでした。これで、多くの新機能を提供するLUKS2がリリースされているので、データを失うことなく左の拡張を異なるものにすることは可能ですか?

答え1

長すぎます。その可能性はほとんどありません。まだではありません。メタデータ形式ではこれが可能であることを示唆していますが、これまでは実際には実装されていません。したがって、古い「すべてのデータの再配置」または「新しいパーティションを作成してLVMで処理できるようにする」に固執する必要があります。 LUKS1とほとんどのファイルシステムで同じことを行います。


これLUKS2ヘッダ概念があるデータセグメント:

Segmentsオブジェクトには、ユーザーデータ(LUKS1ではユーザーデータペイロードと呼ばれる)を含むディスクの暗号化領域の定義が含まれています。一般的なLUKSデバイスの場合、データセグメントは1つだけ存在します。

データを再暗号化すると、内部的にはデータ領域は既存のキーと新しいキーに基づいて区別されますが、ユーザーには抽象領域のみが表示されます。

そしてデータセグメント、LUKSヘッダーを左に移動し、元のデータ(最初のセグメント)をポイントし続け、空き領域(ヘッダーとデータセグメントの間)を新しいデータセグメントとして論理的に最後に追加できる必要があります。暗号化されたデバイスのデータセグメント。 LVM が任意の物理範囲グループを論理ボリュームに接続する方法と同じです。

しかし、これは単なる理論です。

まだこの機能を実装する実際の使用/ツールがなく、そうする計画があるかどうかわかりません。


私はそれを風変わりな方法(概念証明など)で動作させようとしています。

# truncate -s 100M foobar.img
# cryptsetup luksFormat --type=luks2 foobar.img
# cryptsetup luksOpen foobar.img foobar
# yes > /dev/mapper/foobar
# sync
# hexdump -C /dev/mapper/foobar
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

LUKS2 はパターンを暗号化します。データセグメントはどのようなものですか?

# cryptsetup luksDump foobar.img
Data segments:
  0: crypt
    offset: 16777216 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# strings -n 100 foobar.img
"segments":{"0":{"type":"crypt","offset":"16777216","iv_tweak":"0","size":"dynamic","encryption":"aes-xts-plain64","sector_size":512}}

後者は実際に生のLUKS2メタデータの外観です。これはJSON形式です。後で修正します...

それを育てよう - 左(100M):

# truncate -s 100M barfoo.img
# cat foobar.img >> barfoo.img
# ls -lh *.img
-rw-r--r-- 1 root root 200M Jun  9 20:57 barfoo.img
-rw-r--r-- 1 root root 100M Jun  9 20:53 foobar.img

したがって、barfoo.imgは100Mの新しい空きスペースであり、その後には100Mの元のLUKSコンテナがあります。

LUKS ヘッダーをデバイスの新しい先頭に再配置します。

# dd bs=1M count=16 if=foobar.img of=barfoo.img conv=notrunc
# cryptsetup luksOpen barfoo.img barfoo
# hexdump -C -n 16 /dev/mapper/barfoo
00000000  4e a6 39 e7 e0 e8 63 ae  81 72 29 81 5f 1b 08 c2  |N.9...c..r)._...|
00000010

今は開くことができますが、データセグメントそれでも古いオフセット(16MiB)を指していますが、もちろんそこにはありません。 100Mを追加したので、このオフセットはデータセグメントこれで116MiBになるはずです。

編集してください(オフセット16777216からオフセット121634816へ):

# strings -n 100 barfoo.img | head -n 1 > barfoo.json
# nano -w barfoo.json
# dd if=barfoo.json of=barfoo.img bs=1 seek=4096 conv=notrunc
# dd if=barfoo.json of=barfoo.img bs=1 seek=20480 conv=notrunc

結果:

# cryptsetup luksDump barfoo.img
Device barfoo.img is not a valid LUKS device.

ああ、もちろんです。 LUKS2にはメタデータチェックサムもあります。コンテンツを編集するためにnanoを使用し、ヘッダーを削除するためにddを使用したくありません。先生、あなたは神秘的な魔法を持っていません。まあ、チェックサムをパッチするまでは…

# cryptsetup luksDump barfoo.img --debug
# LUKS2 header version 2 of size 16384 bytes, checksum sha256.
# Checksum:8552bf514ab70b53e63180e9fdd3bb59db1385e3dca87f792f8197b33b851aa1 (on-disk)
# Checksum:e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e (in-memory)
# LUKS2 header checksum error (offset 0).

...デフォルトでは、オンディスクチェックサムをメモリ内チェックサムに置き換えます。

# echo e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e |
  xxd -r -ps - |
  dd of=barfoo.img bs=1 seek=448 conv=notrunc

結果(現在は):

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# hexdump -C /dev/mapper/barfoo
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

この時点で、我々はLUKSヘッドを左に100M移動させることに成功しました。しかし、デバイスのサイズはまだ同じです。今、別のデータセグメントを追加できますか?オフセット16Mから116Mまでの100Mの空きセグメントがあります。これをJSONに追加しましょう。

# nano -w barfoo.json
man this is unreadable
# jq < barfoo.json > barfoo.pretty
# nano -w barfoo.pretty
...
  "segments": {
    "0": {
      "type": "crypt",
      "offset": "121634816",
      "iv_tweak": "0",
      "size": "88080384",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    },
    "1": {
      "type": "crypt",
      "offset": "16777216",
      "iv_tweak": "172032",
      "size": "104857600",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    }
  },
  "digests": {
    "0": {
      "type": "pbkdf2",
      "keyslots": [
        "0"
      ],
      "segments": [
        "0",
        "1"
      ],
...and so on and so forth...

結果:

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: 88080384 [bytes]
    cipher: aes-xts-plain64
    sector: 512 [bytes]

  1: crypt
    offset: 16777216 [bytes]
    length: 104857600 [bytes]
    cipher: aes-xts-plain65
    sector: 512 [bytes]

残念ながら、この時点ではデバイスがうまく開き、サイズは正しく増加します(はい!)、データは間違っています(いいえ!)。論理バイト0は、予想される116MiBの代わりに物理バイト16MiBにマッピングされる。

おい、それは0ではなく1だ、この愚かなビリー!何が間違っていますか?

わかりません。まだ誰もテストしていない隠された機能のロックを解除するために単純なメタデータを変更しないでください。

私が理解力の欠如のせいか、断片を逆に配置しても、まだ間違った順序で開きます。物理オフセットに基づいてソートすることはありますか?しかし、なぜ?

残念ながら、この特別な魔法は失敗しました。私が何か間違っているか、使用する準備ができていません。それにもかかわらず、この機能は存在するので、将来への希望はまだ残っています。

動作しても推奨されません。

関連情報