如何擴展 LUKS2

如何擴展 LUKS2

幾年前我讀過一本指南,內容是關於 LUKS1 如何在不丟失資料的情況下擴展到右側和相鄰的自由空間,但無法離開。如今LUKS2已經到來,帶來了許多新功能,它是否可以在不丟失資料的情況下使左側擴展不同?

答案1

太長了;博士這還不太可能——目前還不可能。元資料格式表明它應該是可行的,但到目前為止,它還沒有實際實現。因此,您應該堅持古老的“重新定位所有資料”,或“建立新分割區並讓 LVM 處理它”。您對 LUKS1 和大多數檔案系統執行的操作相同。


LUKS2 標頭有一個概念數據段:

Segments 物件包含磁碟上包含使用者資料(在 LUKS1 中稱為使用者資料有效負載)的加密區域的定義。對於普通 LUKS 設備,僅存在一個資料段。

資料重加密時,內部會根據新舊密鑰劃分資料區域,但只向使用者呈現一個抽象區域。

數據段,應該可以將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 映射到物理位元組 16MiB,而不是預期的 116MiB。

嘿,那是段 1,不是段 0,你這個傻比利!什麼地方出錯?

我不知道。這幾乎就像您不應該進行簡單的元資料修改來解鎖尚未有人測試過的隱藏功能一樣。

也許這是由於我缺乏理解,但即使以相反的方式放置片段,它仍然會以錯誤的順序打開它們。有什麼東西會按物理偏移量對這些進行排序嗎?但為什麼?

不幸的是,這個特殊的魔法以失敗告終。要嘛是因為我做錯了什麼,要嘛是它還沒有準備好要使用。儘管如此,該功能還是存在的——所以未來仍然充滿希望。

請注意,即使它確實有效,也不建議您使用它。

相關內容