それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Raspberry pi を dm-crypt(LUKS) にして暗号化する。(その1考察ポエム)

raspberry pi をLUKSにする。

バイスを暗号化すると、盗難対策だとかコピープロテクションとかを考慮しつつ、センシティブ情報を格納出来る。

暗号化は現代には不可欠な技術だが、RaspberryPiにはTPMチップが無いので、X86のPCのような手軽に扱える用にならない。

が、パスワードやログなど見られたくない情報を保護するのであれば、やはりLUKSが一番だろうと思う。

Raspi を暗号化する前に考えること。

2つの事を考える。一つはCPUの負荷、もう一つは格納方法だ。

パフォーマンスとCPU負荷

暗号化によりCPU不可が大きくなりすぎると、ほかの処理に影響がでる。

格納手段による違い。

機密情報を保持するのに、システム全体か、特定ファイルだけを暗号化すればいいのか。ディレクトリだけでいいのか、ネットワーク上だけでいいのか。などを考えておかないといけない。

パフォーマンス

intel にはAES-NIという強烈なAESサポートがある。armの一部製品にも含まれるらしいが、RaspiのCPUには含まれない。

CPUベンチマーク

LUKSを使ったとき、どれくらいの速度差があるか、ちょっと見てみる。

cryptsetup benchmark -c xchacha20,aes-adiantum-plain64
cryptsetup benchmark -c aes-xts-plain64 -s 256

自宅に転がっているPCで軽く測定してみた。

cpu アルゴリズム Encrypt Decrypt
RPi4(Cortex-A72) xchacha20,aes-adiantum 256b 133.2 MiB/s 132.6 MiB/s
RPi4(Cortex-A72) aes-xts 256b 76.8 MiB/s 85.5 MiB/s
Intel i6700 xchacha20,aes-adiantum 256b 498.8 MiB/s 473.6 MiB/s
Intel i6700 aes-xts 256b 2762 MiB/s 2853 MiB/s
Intel n4200 xchacha20,aes-adiantum 256b 303.3 MiB/s 304.4 MiB/s
Intel n4200 aes-xts 256b 742.5 MiB/s 743.6 MiB/s
intel n3350 xchacha20,aes-adiantum 256b 258.6 MiB/s 293.6 MiB/s
intel n3350 aes-xts 256b 697.3 MiB/s 716.8 MiB/s
AMD 4750GE xchacha20,aes-adiantum 256b 469.7 MiB/s 498.3 MiB/s
AMD 4750GE aes-xts 256b 1119.7 MiB/s 1095.9 MiB/s

正確に測定するのであれば、openssl でやるべきだろうが、今回は cryptsetup のベンチマークを利用した。

intel 6700 という古いCPUでも格段のスコアを叩き出している。AMD Ryzenは期待ほど伸びない。インテル強い。

この測定から、Raspberry Pi でLUKSのような暗号化デバイスを扱うと、暗号化がボトルネックになると予想される。

ちなみに、Rpi4 結果を抜粋するとつぎのようになる。

cpu アルゴリズム Encrypt Decrypt
RPi4(Cortex-A72) xchacha20,aes-adiantum 256b 133.2 MiB/s 132.6 MiB/s
RPi4(Cortex-A72) xchacha12,aes-adiantum 256b 161.0 MiB/s 162.2 MiB/s
RPi4(Cortex-A72) aes-xts 256b 76.8 MiB/s 85.5 MiB/s
RPi4(Cortex-A72) aes-cbc 128b 79.6 MiB/s 82.7 MiB/s

他にもみたいときは cryptsetup benchmarkをオプション無しで起動すると良い。chachaがずば抜けている。xchacha12はなんちゃって暗号化のためには行けそうだけど、ちゃんと安全を確保するには厳しそう

cpu 負荷について。

仮にAES-XTSで妥協したとする。そこそこの速度がでるから良いかも。と判断して採用したとする。そうしても、CPUがハイ・ロードでとどまり続けてしまうと。使いものにならないかもしれない。

https://github.com/keks24/raspberry-pi-luks/issues/2のスレッドをみてみると、以下の画像がでてきた。

LUKSで起動に成功したとしても、暗号化処理にCPUを取られる可能性がある。 CPUのワークロードが高くなりすぎて電源浪費するし、CPUリソースを食い尽くすと他の処理が遅延するため、暗号化に意味がないということがわかる。10年前には「秘文」のようなソフトウェア暗号化による体感速度の低下があった。先輩方にわせると、みんな秘文が嫌いだったらしい。あの当時の苦痛に、いまさら頭を悩ますことになる可能性がある。

adiantumという暗号化

ここで、注目されるのが、xchacha20,aes-adiantum である。これはCPU負荷はそんなに高くはなく速度もAES-NIには及ばない。しかしCPUでAES-XTSを処理するよりは早く、ワークロードも低めに抑えられる。

試しに、適当なUSBメモリをxchacha20,aes-adiantumで暗号化して使ってみたところ、CPU負荷は気にならないレベルまで落ちてくれた。

このあたりの詳しい検証は参考資料に書いてあった。

暗号化する対象と、ツール

dm-cryptのようにルートファイルシステム全体を暗号化せずに、機密情報をRaspberry Pi に格納するにはどうすればいいだろうか。

RaspiのストレージはSDカードです。簡単に奪取されます。パスワードや秘密鍵を設置しておくと面倒が起きそうです。

Raspiに安全にパスワード(秘密鍵)を設置する

安全に機密情報保持するなら、考えられる手段は、次のとおりです。

  • LUKSでSDカード全体を暗号化する
  • ecryptfs/encfs で$HOMEを暗号化する
  • 秘密鍵パスフレーズ保護する。単なる暗号化ファイル作成
  • bitwarden / 1passwordなどを使う。
  • NFS などネットワークマウント
手法 対象 デメリット
LUKS システム全体 起動時にパスワード入力が必要
initramfsが必要
ecryptfs ディレクト 再起動の初回ログインで必ずパスワードが必要
単なる暗号化 ファイル ファイルが増えてくると厄介。ディレクトリは面倒
bitwarden bitwarden 専用サーバーが必要。cli も必要。1passwordなら課金も必要
NFS/Cifs ネットワーク NASサーバーが必要。常時接続が必要。

LUKS の場合

LUKSを解除するために、initramfs が再構成が必要です。initramfs がCryptSetupを使うように構成を変更しなくてはいけません。再起動のたびにパスフレーズの入力が必要です。システム全体を暗号化してしまうので、ロック解除後は通常のLinux操作と同じです。何も意識せずに暗号化のメリットを享受できます。考えることが少なくてすみます。TPMチップがあればロック解除も安心できるのですが。残念ながらRaspiにはプリインストールされていません。モジュールで購入も可能ですが、UKで£32 (≒送料込5000円弱)くらいです。

encrypt-fs の場合

めちゃくちゃ簡単です。驚くくらい簡単に$HOMEを暗号化出来ます。時短には最適。何個かコマンドをコピペするだけで最低限十分な暗号化が手に入ります。

encfs / ecrypt-fsを用いる場合、指定ディレクトリを暗号化出来ます。ecryptfs は/home/usernameを暗号化できます。ただしロック解除時にパスフレーズが必要です。パスフレーズは、通常はログインパスワードと共通にします。ecrypt-fs で $HOMEを暗号化すると、/home/usernameがロックされるので、~/.ssh/authorized_keys が使えません。

 察しの良い読者さんは、保存場所を変えればいいじゃんと思うかもしれません。ところが、そう簡単でもないのです。authorizied_keysの保存場所を変えてログインできたとしても、$HOMEロックされたままですsshログインできても、結局は、homeロック解除にパスフレーズを提供します。じゃあ秘密鍵でロック解除すればいいじゃん!と思うかもしれません。libpam-ssh-agent-authでできはくはないが、そのためには、ssh-agentで秘密鍵転送が必要になります。秘密鍵を提供できたとしても、.bashrcすらロック状態です。ロック状態でそれらのpam設定を行うのは地獄のような気がします。

ecryptfsなら $HOME ロックををLUKSで代替できる。

同じ目的であれば、LUKS+PAMで同等の機能が実現できるらしい。これらのことを考えると、ノートPCにインストールしたUbuntuであればecryptfsにメリットはあるが、パーティションをイジくれるなら、LUKS+ログイン時にロック解除で良いと考えられます。

ecryptfsにはいくつかの制限事項がある。ファイル名が143文字に限定される。スパースファイルが作れないスパースファイルが作れないのは、諦めるとしてもファイル名が長くなるとエラーになるのはちょっと怖い。

なにより、Ubuntuであれば簡単ですが、その他のディストリで苦労が伴います。

公開鍵認証によるSSHログインを諦めなら、encryptfs はいい選択肢だと思います。ただそれでもLUKS+PAMで同じことだと思います。わざわざ暗号化のオーバーヘットを掛ける理由がありません。LUKSをxchachaで行い、encryptfsの代わりにPAMを構成すればい同じことです。手軽さに頼るかどうか。ここが判断基準になると思います。

単なるファイル暗号化 openssl enc -d -pbkdf2 -aes256 -base64

Raspiに設置したファイルを、暗号化しておけば良いかもしれません。openssl enc -d -pbkdf2 -aes256 -base64 のようなOpenSSLのコマンドや、ssh内蔵のssh-keygen -p -f ~/my.ssh.id_rsa コマンドが使えそうです。ファイルが少ないときは良いのですが。ディレクトリまるごと暗号化のような需要に答えるのは苦労が伴います。もし実現するとすれば、たとえばtar ファイルに圧縮しておいて、tar マウント(archivemount my.tgz ~/mnt)方法も考えられますが、更新が頻繁になると、これも面倒です。ファイルが増えてくるとSparseファイルを作ってloopback ブロックデバイスを結局は使うことになるでしょう。なので、これはファイル数の多寡が判断基準になりそうです。多いときはdm-crypt LUKSに行き着きます。

bitwarden / 1password など使う。

cli から利用できるパスワード管理ソフトを使ってその中に機密情報を保存する方法が考えられます。bitwarden には bwというクライアントコマンドがあります。これを使って安全にファイルを暗号化すれば良いのですが。ディレクトリまるごと暗号化では手間が苦痛です。また bitwardenのbwコマンドの公式レポジトリはディスコンされて行き場を失っています。この点からも外部依存するのも考えものです。1passwordなら完成度は高いのですが、値段も高いです。

NFS/cifs マウントを使う

ネットワークをマウントしまえばいいかもしれません。SSHFSやrclone マウントなどの便利な方法もあります。しかいNFSのようなネットワーク接続先への接続情報と認証情報をどうやって管理すれば良いのでしょうか。「振り出しに戻る」です。データを保護するのであればNFS/Cifsで十分でしょう。ただ、/homeを暗号化するような目的を考えるとNFSNISでガチな移動プロファイル環境が必要で手に余ると思います。いまのRaspiberry piはNFSでブート出来るので、ディスクレスにしてしまってNFSで運用も悪くないとは思います。・・・SDカードはすぐ壊れるし。USBメモリもそこまで寿命はないですし。AD/Cifs の移動プロファイルを使うのは悪くないと思いますが、通信経路の保護や認証情報の保持を考えて、サーバを用意するとなるとハードルが高くなりすぎて。

 Google DriveやOneDriveをマウントするのもいいと思います。ログイン時に自動的にリモートのファイルサーバをマウントするのも同じです。systemd-user をつかってログイン時に、ログインパスワードで機密情報を解除してマウントしてしまうのです。この場合は、パスワードをどうやって提供するかが問題になり、ecryptfsと同じく公開鍵認証を用いた場合に設定が煩雑になりそうです。ただスクリプトを組めば手軽になりそう。

pam_mount を使う。

pam_moutを使って、ログイン時に何かをマウントすることも出来ますし、それでも良いと思いますが、ログアウト時にロック解除が動かないそうです

Pam_mount はセッションの終了時にパーティションをアンマウントすることもできますが、pam で使われている pam_systemd.so が原因で今のところ機能しません。

安定性は非常に高いですが,DM 起動前にパスワードが求められるのでタブレットBluetooth キーボードでは解錠ができませんし,ログイン操作との統合もできず,あえてこうする実益があるケースは思いつきません。

PAMをクラウド認証やLDAPと組み合わせる。

GoogleChromebookは2010 の段階でこのような設計になっていたそうです。

昔の大学や高校の情報処理教室ではpamとLDAPとCIFSを組み合わせて、移動プロファイルの代わりに、CIFSマウントを起動時に行っていたらしいです。ここまでの設定を振り切ってやりきってた学校があったのか。非常に驚きです。

個人的な結論

adiantum で暗号化、dm-crypt で LUSKを起動時に dropbear でSSH経由でロック解除で十分じゃん。

自動マウントとか夢だけど、夢にしておこう。

参考資料