dmgに入れたファイルを、パスワードで保護したい場合がある。hdiutil createに-encryptionを指定すると、dmgを暗号化できる。パスワードは、-stdinpassで標準入力から渡す。

$ printf '%s' "$DMG_PASSWORD" | hdiutil create -volname "[ボリューム名]" -srcfolder [フォルダ] -format UDZO -encryption AES-256 -stdinpass -ov [dmgのファイル名].dmg

ここでは、暗号化したdmgの作成、マウント、暗号化の確認方法を紹介する。実行例はmacOS 27.0.1のもの。

参考: 【hdiutil】フォルダからdmgを作る

暗号化したdmgを作る

-encryptionに暗号方式を、-stdinpassにパスワードの入力方法を指定する。hdiutil create -helpには、暗号方式としてAES-128とAES-256があり、AES-256が推奨と書かれている。

$ printf '%s' "$DMG_PASSWORD" | hdiutil create -size 10m -fs APFS -volname Secret -encryption AES-256 -stdinpass -ov enc

パスワードは、環境変数などに入れておき、printfで標準入力に渡す。パスワードを直接コマンドに書くと、シェルの履歴に残る。

フォルダから、圧縮した形式(UDZO)の暗号化dmgも作れる。

$ printf '%s' "$DMG_PASSWORD" | hdiutil create -volname Enc -srcfolder src -format UDZO -encryption AES-256 -stdinpass -ov enc3

diskutilで暗号化する

diskutil image createでは、--encrypt(-e)を指定する。暗号方式はAES-256である。パスワードは、--stdinpassphraseで標準入力から渡す。

$ printf '%s' "$DMG_PASSWORD" | diskutil image create from --encrypt --stdinpassphrase --format UDZO src enc4.dmg
enc4.dmg created
$ printf '%s' "$DMG_PASSWORD" | diskutil image create blank --encrypt --stdinpassphrase --size 10m --volumeName EncBlank enc5.dmg
enc5.dmg created

fromは既存のフォルダやdmgから、blankは空のdmgから作る。

参考: 【diskutil】image createでdmgを作る

dmgが暗号化されているか確認する

hdiutil isencryptedで、dmgが暗号化されているかを確認できる。パスワードを入力せずに実行できる。

$ hdiutil isencrypted enc.dmg
blocksize: 512
uuid: [UUID]
private-key-count: 0
passphrase-count: 1
max-key-count: 1
version: 2
encrypted: YES
$ hdiutil isencrypted plain.dmg
encrypted: NO

暗号化したdmgは、encrypted: YESと表示される。暗号化していないdmgは、encrypted: NOだけが表示される。

hdiutil imageinfoでも、書き込み可能な形式の暗号化dmgでは、Encrypted: trueとEncryption: AES-256を確認できた。ただし、hdiutil imageinfoは、暗号化したdmgでパスワードの入力を求められる場合がある。パスワードなしで確認したい場合は、hdiutil isencryptedを使う。

ファイルの中身が読めないことを確認する

暗号化したdmgと、暗号化していないdmgに、同じ文字列を書き込んで、dmgのファイルを検索した。

$ grep -a -c MARKER_PLAINTEXT_STRING_12345 enc.dmg
0
$ grep -a -c MARKER_PLAINTEXT_STRING_12345 plain.dmg
1

暗号化していないdmgのファイルには、書き込んだ文字列がそのまま見つかった。暗号化したdmgのファイルでは、見つからなかった。

暗号化したdmgをマウントする

パスワードは、標準入力から渡す。diskutil image attachでは--stdinpassphrase、hdiutil attachでは-stdinpassを指定する。

$ printf '%s' "$DMG_PASSWORD" | diskutil image attach --stdinpassphrase --mountOptions nobrowse --mountPoint [マウントポイント] enc.dmg
/dev/disk22  	GUID_partition_scheme
/dev/disk22s1	Apple_APFS
/dev/disk23  	Apple_APFS_Container
/dev/disk23s1	Apple_APFS_Volume    	[マウントポイント]
$ printf '%s' "$DMG_PASSWORD" | hdiutil attach enc.dmg -stdinpass -nobrowse -mountpoint [マウントポイント]

マウントしたあとは、通常のdmgと同じように、ファイルを読み書きできる。

パスワードが誤っている場合

誤ったパスワードを標準入力から渡すと、diskutil image attachは、エラーで終了コード1になる。

$ printf '%s' "$WRONG_PASSWORD" | diskutil image attach --stdinpassphrase --mountOptions nobrowse --mountPoint [マウントポイント] enc.dmg
Error: Incorrect passphrase
$ echo $?
1

hdiutil attach -stdinpassで、標準入力が空の場合は、attach failed - 認証エラーで、終了コード1になる。

$ hdiutil attach enc.dmg -nobrowse -mountpoint [マウントポイント] -stdinpass < /dev/null
hdiutil: attach failed - 認証エラー

パスワードを渡さない場合

標準入力でパスワードを渡さずにマウントすると、パスワードの入力画面が表示される。入力画面をキャンセルすると、エラーで終了コード1になる。

$ diskutil image attach --mountOptions nobrowse --mountPoint [マウントポイント] enc.dmg
Error: 操作はユーザによってキャンセルされました
$ hdiutil attach enc.dmg -nobrowse -mountpoint [マウントポイント]
hdiutil: attach canceled

暗号化したdmgを作った直後の1回目のマウントでは、パスワードを渡さなくても、マウントできた。2回目以降は、パスワードを求められた。理由は確認していない。スクリプトでは、毎回、標準入力でパスワードを渡す。

パスワードを変更する

diskutil image chpassは、暗号化したdmgのパスワードを変更するサブコマンドである。--helpには、成功すると新しいパスワードに置き換わると書かれている。