タイトルの通りです。本シリーズ最後のエントリになる予定のSide D、感情処理パートはRubyKaigi 2025 事後勉強会のあとに公開する予定です*1。
自分のセッションについて
- 英語: https://speakerdeck.com/sylph01/end-to-end-encryption-saves-lives-you-can-start-saving-lives-with-ruby-too
- 日本語: https://speakerdeck.com/sylph01/end-to-end-encryption-saves-lives-you-can-start-saving-lives-with-ruby-too-jp-subtitles
Messaging Layer Security Protocol (RFC 9420)のRuby実装について話しました。Speaker Deckの過去ログを見ると2019年くらいからMessaging Layer Securityの動向については何度か話してきたことがわかりますが、実装にやっと手が着いて大方できたといっていいところまでやった、という話になります。ひよった言い方をしているのは、test vectorの全passによってプロトコルの要求する暗号処理が正しく行えることの確認はできているが、アプリケーションがその値を使って暗号処理を行うところまではまだ隔たりがあったり、グループの状態管理をかなり無理やりやっているのでアプリケーションが使うにはかなり不親切だったり、まだプロトコルに存在するすべてのmessage typeに対応しているわけではない、というのが話した時点でのstatusだからです。アプリケーションとしてもっと使えるようにするところは7月のIETFまでにやって、他の実装者と接続試験を行えるところまで持っていきたいと思っています。
タイトルに「人命を救う技術である」というふうに書いているのは、暗号化のあるメッセージングのおかげで権威主義国家や戦場の中からジャーナリズムを得ることができていることから書いています。この重要性は国際情勢の緊迫化に伴い日に日に高まっています。タイトルが公開されて以来暗号化の重要性がより強調されるような事態ばかりニュースで聞かれるようになって、こういう方向には進んでほしくはないんだけどなあ…と複雑な気持ちでした。
Messaging Layer Securityを知ってから実際の実装に至るまで7年近くかかっているのは私の能力不足という側面も大いにありますが、ビルディングブロックが足りていなかったところを埋めていた、というのもあります。HPKEの実装を行ったのも長期的にはMLSで必要だからで、誰も使わなかったとしても自分で使うつもりで作りました。hpke gemがECHの検証のために使われたというユースケースを知ったときはとても嬉しかったです。
今回の発表で一番難儀だったのがTreeKEMの説明で、これはどうやっても10分〜15分で説明できるものではなく、どちらかというと手を動かしながら途中状態を見て説明できるようにしたほうがいいな、と感じました。今までの他の言語の実装ではREPLがない、あるいはREPLのようなもので使えるようにするまでのハードルが高いためこれが難しかったわけですが、Rubyで実装されたということはirbでステップごとに実行するということが可能になったわけです。MLSを理解して拡張するのにこれ以上便利な道具はなかなかないのではと思います。
今回の発表でプロトコルの動作説明を急ぎ足でやってしまったのをあまり気に入っておらず、ある程度似たような分野に気持ちのある人ですら「これはこの時間では無理」っていうコメントをもらったので、発表としてはうまくいっていない、と言わざるを得ないでしょう。もちろんMessaging Layer Security*2はRubyに限った話ではないので、今後然るべき場所で改善されたRubyのMLS実装を使ってMLSひいてはMIMI*3をやっていく話をしていければと思います*4。
Twitterコメント補足
同じ方からのコメントの紹介で恐縮なのですが質問してくれたからには答えないとなということで…
木構造にしたぶん、メッセージパッシングに必要なノードの数が増えてしまっているのはトレードオフという解釈で良いのかな #rubykaigi #rubykaigiB
— expa / Shu Oogawara (@expajp) 2025年4月17日
実は木構造を取ることによって発生するparent node(末端の葉でないノード)によって通信するべきノードの数が増えるっていうことはなく、これは「ユーザーを示すのは葉のノードのみ」「parent nodeは途中状態を計算するためのただの状態保持機構」で、ユーザー同士はproposalやcommitのメッセージでやりとりをする、なので鍵の合意のためにはユーザー数分=葉ノードの数分の通信のみを行えばよく(結果としてO(n))、全員がお互いに鍵の合意のために通信をするO(n2)にはならないで済みます。ツリーの高さぶんだけ計算は発生するので結果として通信はO(n)、そこからの状態の計算はO(log n)かかる、ということになります。「ユーザーを示すのは葉のノードのみ」「parent nodeは途中状態を計算するためのただの状態保持機構」、っていう部分をうまく説明できてなかったのがよくなかったですね…。
前半のスライドずっと見ながら考えてる
— expa / Shu Oogawara (@expajp) 2025年4月17日
木構造に依存するのが鍵の漏洩対策にもなってるんだなこれ
逆に自分の預かり知らないところで鍵がロストしたら詰む? #rubykaigi #rubykaigiB
また、鍵が漏れてしまったら台無し、鍵をロストしたら詰み、はそれはそうで、liveなleaf key pairとグループの状態がセットで漏れたら該当のleafのユーザーになりすまして以降もそのユーザーになり続けることができますし、復旧メカニズムとかを用意しようにもそれがバックドアになってしまう可能性があるので鍵のロストは特に考慮されていません。post-compromise securityはそこまでは保護しきれません。ユーザーはleaf key pairを更新することで、その鍵が使われていた期間のみに鍵(ひいてはグループの共有秘密)の流出の影響を閉じ込めることができる、というのがpost-compromise securityの意図するところです。結局ある程度の鍵管理は避けられず、でも鍵管理は人類には早すぎるとよく言われるほど難しいので、そこはアプリケーション側の腕の見せ所になります。
聞いたやつ
Bringing Linux pidfd to Ruby
process-ID reuseとかマルチプロセスってこんな浅いところに地雷埋まってるんだ…と思っていたら現代のプロセスID空間はかなり巨大なので相当なことがない限り発生しないらしいと聞いた。用心するに越したことはないというのはそう。でもこういうのがあるからプロセスに依存しない形で、例えばRactorとかでやりたいんだろうなあ…。プロセスIDまで含めてなんでもファイルのように扱えるっていうのは確かにLinuxらしい。
Keeping Secrets: Lessons Learned From Securing GitHub
自分の実装で send
をカジュアルに使ってたので肝が冷えたし、 instance_variable_set
とかも使ってたのでいっそう肝が冷えた。 public_send
で send
呼べば結局 send
だけ塞いでも無意味っていうの厳しいなあ…。あとなかなかセキュリティインシデント対応の裏側について聞けることがないのでその手続き的な話もだいぶ貴重だった。
MicroRuby: True Microcontroller Ruby
去年のトークのあとTCPServer実装しないんですか?っていろんなところから言われており、TCPServerを実装するにあたってCの世界からRubyのメソッドを呼び出すコールバックがmruby/cには用意されておらず迂遠なワークアラウンドが必要なので避けていたのだけど、/cでないmrubyであればTCPServerを作るのにあたってほしい機能があるので非常に期待していた。現時点だと無印Pico Wではメモリが厳しそうとのこと、まあ仕方ない、Pico 2 Wも安いので今後はみなさんそっち使いましょう。
あとメモリ管理周りで気になった内容があったので書いたらコメントが返ってきた(ありがとうございます!)。lwipとメモリ管理が別々になってるのでメモリを食うっていうのはあるのでなんとかなってほしい一方で、スレッドセーフ性の問題言われたら確かにそうなのでそう簡単には行かないよなあというのも納得です。
もしかしてlwipにこのアロケータのAPIを晒せばそっちにアロケートしてくれる…?そんな都合のいいことはないか #rubykaigiA
— sylph01 / G4きゅーぶ (@s01) 2025年4月17日
スレッドセーフの関係でそれができないようになってるんですけど、最近打たれたLwIPのタグで、それができるようになってる?と匂わしていて気になっています。まだよくわかってないですがhttps://t.co/iMaGnqoZOT
— hasumikin (@hasumikin) 2025年4月17日
Making TCPSocket.new "Happy"!
私も30分で90枚をspeedrunしたと思ったらそれを上回る200+枚で、しかも去年の発表を5分くらいで振り返るspeedrunしてきたのでひっくり返った。実は単純な状態遷移でやっちゃうと本来実行してはいけないケースで特定の状態になってしまうことがある…ってどうやってこれ気づくんだ…どうやってconformance testするんだ…そしてこのままだとどういう悪用ができるんだ…???テストどうするんだ問題はCI火吹いたパートでも同様に思ったところ。
Porting PicoRuby to Another Microcontroller: ESP32
やってることはめちゃくちゃヤバいんだけどその一方でスライドがめちゃくちゃ丁寧だった。コンパイラとリンカの機能なんてこの手の内容話すと「皆さんもうご存知ですね」ですっ飛ばしそうなところ、確かにクロスコンパイルが必要な環境だからというのもあるけれど、この手のトークではかつてなく丁寧に解説していたのが好感が持てた。いやこれスライドだけ見るとやれそうに見えるけどめちゃくちゃすごいことやってるんですよ…。ESP32のSDK自体はかなりよくできてそうなので今後ESP32側のPicoRubyでも機能が増えていくのが楽しみ。
The Challenges of Building sigstore-ruby
今回最も刺さったトークがこれ。X.509周りが面倒だよねーというのはCfPにも書かれていたけれど、暗号ライブラリに機能が足りてなかったり自明じゃない機能がある、っていうのは私のトークでも扱った内容だったし、Ed25519周りの機能がまだ未整備だよねというのは確かにHPKEをRuby実装したときに思って今回も自分で2年前に開けたAPIを使ったりしていたので、「そうそうそれそれ!!」とニヤニヤしながら聞いていた。でCRuby側のOpenSSLだけならまだしも、JRubyのOpenSSLになるともっと機能が足りていないのでJavaのsecurityライブラリを使って足りない機能を作った…まで行くと本当に気にしたことがなかったので衝撃だった。ディテールは1%のRubyist向けの内容だったけどその成果は決して1%のRubyist向けではなくてgemsを使う人ほぼ全員に影響がある話というのもいい話。そして「標準を実装する例が世の中に1つ増えると次の実装者がやりやすくなる」というのはMLSをRuby実装することで私も目指していたことではあるのでとても共感できた。
スライドで話した「大統一暗号API」の今後について
実際これのようなものがほしいというのは"The Challenges of Building sigstore-ruby"でも言われていた(と私は読み取ったよ!)のでまあほしいのはわかるのですが、これについては私の調査不足があって、まず似たようなことをやろうとした前例があります:
また、ruby-wasmにはwasmにポーティングされたopensslを使ったopenssl gemがすでに存在して、OpenSSLの機能をブラウザから使うことはできます。聞いたときは「ほんとに…!?」ってなりました。kateinoigakukunさんはすごい人。一方でwasmポートされたopensslを使うよりはWeb Crypto APIを使ったほうがパフォーマンスは出るだろうという話も聞いたので、Web Crypto APIを使う道筋を開くのは全く意味がない、ということはなさそうです。またJRubyサイドでもbackend-agnosticな共通化された暗号APIがあることは嬉しそうな気がするので、既存の試みや、他のエコシステムにおける暗号APIの調査を行うところから始めようと思います。
(なおこの関係で、CfPオープン初日に投稿した関西Ruby会議08のCfPはこの内容をしゃべるつもりであったためRubyKaigi後に取り下げています。あまり中途半端な状態でしゃべるのもよくないだろうと思うので、調査と実装が進んだ上で然るべきところで話そうと考えています)