Upgrade to Pro — share decks privately, control downloads, hide ads and more …

End-to-End Encryption Saves Lives. You Can Sta...

Avatar for sylph01 sylph01
April 17, 2025
370

End-to-End Encryption Saves Lives. You Can Start Saving Lives With Ruby, Too (JP subtitles)

Avatar for sylph01

sylph01

April 17, 2025
Tweet

Transcript

  1. End-to-End Encryption Saves Lives. You Can Start Saving Lives With

    Ruby, Too Ryo Kajiwara/ 梶原 龍 (sylph01) 2025/4/17 @ RubyKaigi 2025 日本語字幕版スライド。脚注に日本語字幕があります 1
  2. I do stuff Play rhythm games (especially DanceDanceRevolution) Play the

    bassoon/contrabassoon Play DJ at clubs (also at RubyMusicMixin!) Ride a lot of trains (Rails!) (travelled on 99% of JR) Build keyboards if anything catches your interest let's talk! 今回はあっさり飛ばします 5
  3. And I do stuff that is more relevant to this

    talk: Freelance web developer focused on Digital Identity and Security Worked/ing on writing/editing and implementing standards HTTPS in Local Network CG / Web of Things WG @ W3C, OAuth / Messaging Layer Security WG @ IETF Worked as an Officer of Internet Society Japan Chapter (2020-23) 特に今回のトークで重要な点としてはW3C とかIETF とかで標準化に関わる活動をしてきました 6
  4. The Usual Disclaimer Cryptographic API can be very easy to

    misuse Operational Security is also very difficult I've done my research, but I don't consider myself a cryptography expert a.k.a. "I am not djb" If you're not sure, please have your system audited by a security expert before going to production 暗号API は間違った使い方を容易にしてしまいがちです。あと私はdjb じゃないのでどうしても気になる場合 はセキュリティ専門家にレビューを依頼してね 7
  5. Notes on Production Readiness The MLS implementation is still in

    progress Passes most test vectors "Passive Clients - Random" is not passing yet Lacks validation on error cases I am planning to release the complete version before the next IETF (2025/7) 実装はテストベクターを通す程度には作ったけどまだ完全ではないよ、特にエラーケースのバリデーション とかが落ちてるよ、次の7 月のIETF 目安で完全版リリースしたい(希望的観測) 8
  6. 9

  7. I happen to be known as the SMTP をやめろ-guy SMTP

    をやめろ = lit. "stop using SMTP"; more like "SMTP is dead" 10
  8. SMTP mail lacks two things: 1) Strong identity 2) End-to-end

    Encryption SMTP で私が気にしている点は2 点、アイデンティティの保証がないこと、そしてエンドツーエンド暗号化が ないことです。前者もMLS は助けてくれうるけど今回は後者 11
  9. End-to-End Encryption = The people who run the service cannot

    read your messages LINE, Facebook Messenger, Signal, WhatsApp, ... They each have their own version of E2EE エンドツーエンド暗号化とは、サービスを運営している人があなたのメッセージを読むことができない、と いうことです。みなさんの使ってるメッセージングアプリにもなんらかの形で実装されていることが多いで す 12
  10. E2EE is more important than ever Increasing tension in international

    affairs Powerful people wanting to control the Internet even in democratic countries! Provides a safe method to communicate under oppression / in war zones エンドツーエンド暗号化の重要性はかつてなく高まっています。それは国際情勢の緊張の高まりだったり、 民主主義国家においても力を持つ人がインターネットをコントロールしたいと考えるようになっているから です。抑圧や戦争の下でも安全な通信を保証してくれる暗号化の重要性がわかると思います 14
  11. Hey, but doesn't E2EE help criminals? E2EE is being targeted

    by authorities even in democratic countries! Even if you ban E2EE, criminals will use it anyways Banning E2EE disproportionately harms vulnerable people えっ?犯罪者を助けるからE2EE を禁止しなきゃって?そう、E2EE は民主主義国家においてすら法執行機関 から敵対視されています。犯罪者はE2EE 禁止しても犯罪するんだから、E2EE を禁止することは立場の弱い 人を一方的に不利にするだけです 15
  12. HTTPS(TLS) also helps criminals, but are you going to ban

    HTTPS(TLS)? TLS だって暗号化だし犯罪者の犯罪行為を助けるんですよ、だけどTLS のないインターネットなんて考えられ ないでしょ? 17
  13. Messaging Layer Security More interoperable version of doing E2EE MLS

    provides key exchange Protocol (RFC 9420), Architecture (to be an RFC soon) Today's topic is the implementation of the Protocol Now we (kinda) have RFC 9420 in Ruby! MLS はE2EE のための相互運用性のある鍵交換を提供します。MLS にはプロトコル定義の文書とアーキテクチ ャのドキュメントがあって、アーキテクチャはそろそろRFC になりそうです。今回はプロトコルの話をしま す。 19
  14. mls gem already exists (for a defunct website...) gem を作ろうとしたところ、

    mls っていうgem は2012 年、MLS が-00 Internet-Draft として出るはるか前から 存在してたんですね。でこのライブラリが使えるサイトもう生きてないんですが… 21
  15. 23

  16. Building blocks: HPKE "Encrypt with Public Key, Decrypt with Private

    Key", formalized A combination of the following: Key Encapsulation Mechanism (KEM) ( ≒ asymmetric crypto) Key Derivation Function (KDF) ( ≒ hash) Authenticated Encryption with Associated Data (AEAD) (= symmetric crypto) Available in Ruby: hpke gem HPKE はTLS で説明されるいわゆる「公開鍵で暗号化、秘密鍵で復号」をよりフォーマルに定義したもので、 鍵のカプセル化、鍵の導出関数、認証つき暗号の3 つからなります。gem があります。 25
  17. Security Characteristics Forward Secrecy: messages sent at a certain point

    in time are secure in the face of later compromise of a group member secure against "harvest now, decrypt later" attack 暗号化メッセージングに欲しいセキュリティ性質は2 つあり、そのうちの1 つはForward Secrecy 、長期鍵があ る時点で破られたとしても過去のメッセージの安全性には影響がない、という性質です。TLS 1.3 の説明でよ く聞くアレですね 26
  18. Security Characteristics Post-Compromise Security: messages are secure even if a

    group member was compromised at some point in the past Each member updates their key so that group secrets are not always encrypted with private keys that have been compromised もう1 つはPost-Compromise Security 、これは逆に、ある時点での長期鍵が破られても、鍵の更新が適切に行 えることで、将来のメッセージの安全性には影響がない、という性質です。 27
  19. 2 person is easy # both party starts with chain

    key 0 chain_key[0] = "some common secret" # when sending a message... message_key[n] = hmac_sha256(chain_key[n], 0x02) # encrypt the message #(n) using message_key[n] chain_key[n+1] = hmac_sha256(chain_key[n], 0x01) これらを2 人で実現することは簡単で、共通の鍵を申し合わせた上で、各メッセージの鍵をその世代の秘密 から導出し、次の世代の秘密を今の世代の秘密から別の関数で導出します。各メッセージの鍵は異なるので FS が実現できることがわかると思います。なお実はPCS は別の仕組みの組み合わせでやってる 29
  20. 3+ person is difficult Extend 2-person method? Number of edges

    in an n-node complete graph is O(n^2) じゃあ3 人以上は?ってなると急に難しいと思います。n-node の完全 グラフのエッジの数がO(n^2) なのはご存知の通り 30
  21. Introducing Your Favorite Data Structure That Turns O(n) Into O(log

    n): Trees そこでみんな大好きO(n) をO(log n) にしてくれるデータ構造、木構造の出番です。 31
  22. Secret Tree def self.populate_tree_impl(suite, tree, index, secret) tree.array[index] = {

    'handshake_ratchet_secret' => Melos::Crypto.expand_with_label(suite, secret, "handshake", "", suite.kdf.n_h), 'application_ratchet_secret' => Melos::Crypto.expand_with_label(suite, secret, "application", "", suite.kdf.n_h), 'next_handshake_ratchet_secret_generation' => 0, 'next_application_ratchet_secret_generation' => 0 } unless Melos::Tree.leaf?(index) left_secret = Melos::Crypto.expand_with_label(suite, secret, "tree", "left", suite.kdf.n_h) right_secret = Melos::Crypto.expand_with_label(suite, secret, "tree", "right", suite.kdf.n_h) populate_tree_impl(suite, tree, Melos::Tree.left(index), left_secret) populate_tree_impl(suite, tree, Melos::Tree.right(index), right_secret) end end Each user is assigned a leaf in the tree From the base encryption secret, we recursively populate (snip) ユーザーは木のleaf node を割り当てられ、Secret Tree を上からハッシュのチェーンで埋めていくことで秘密 を導出します 35
  23. Secret Tree The actual ratcheting part: def self.ratchet_application(suite, tree, leaf_index)

    node_index = leaf_index * 2 generation = tree.array[node_index]['next_application_ratchet_secret_generation'] application_ratchet_secret = tree.array[node_index]['application_ratchet_secret'] application_nonce = Melos::Crypto.derive_tree_secret(suite, application_ratchet_secret, "nonce", generation, suite.hpke.n_n) application_key = Melos::Crypto.derive_tree_secret(suite, application_ratchet_secret, "key", generation, suite.hpke.n_k) next_application_ratchet_secret = Melos::Crypto.derive_tree_secret(suite, application_ratchet_secret, "secret", generation, suite.kdf.n_h) tree.array[node_index]['next_application_ratchet_secret_generation'] = generation + 1 tree.array[node_index]['application_ratchet_secret'] = next_application_ratchet_secret tree.array[node_index]['application_nonce'] = application_nonce tree.array[node_index]['application_key'] = application_key end 実際のコードはこんな感じで文字数多いですが… 36
  24. Secret Tree It essentially boils down to this: # for

    generation n # derive_tree_secret is essentially a hash function key = Crypto.derive_tree_secret(ratchet_secret[n], "key", n) nonce = Crypto.derive_tree_secret(ratchet_secret[n], "nonce", n) ratchet_secret[n + 1] = Crypto.derive_tree_secret(ratchet_secret[n], "secret", n) This gives you the key and nonce to encrypt the actual messages. 実質的にはさっき説明したやつ(Signal のDouble Ratchet のうちHash Ratchet の部分)と同じ。 37
  25. TreeKEM Users are assigned a leaf node Users have their

    leaf key pair TreeKEM でもユーザーに葉が割り当てられるのは同じ。ユーザ ーはleaf key pair という公開鍵・秘密鍵の組を持ちます。 39
  26. TreeKEM When a user wants to update the group secret,

    user creates an UpdatePath ユーザーがPCS を実現するために自分自身の鍵を更新するため には、ユーザーはUpdatePath というものを作りそれをグループ に伝えることを行います。 40
  27. TreeKEM User generates a random path_secret at their leaf The

    parent's path_secret is calculated using the child's path_secret (snip) まずはランダムなpath_secret を生成し、親ノードのpath_secret をそれのハッシュで計算、root まで続けて、root からもう一度 ハッシュを取ったのがcommit_secret になります 41
  28. TreeKEM When 0 creates its UpdatePath (yellow) We find the

    copath nodes along the UpdatePath (green) (snip) 0 がUpdatePath を作るとき、UpdatePath (黄色)に沿って copath node (緑)の一覧を得て、もし木全体が埋まっているな らば、各UpdatePath ノードのpath_secret を対応する緑のノード の公開鍵を使って暗号化します。 42
  29. TreeKEM We can see that's possible in a 2-leaf tree

    0 creates an UpdatePath, node 1 has a path_secret the path secret is encrypted to 2 's public key node 2 knows the (snip) 2 ユーザーの場合で見てみましょう。0 がUpdatePath を作り、1 が path_secret を持ちます。2 の公開鍵で暗号化すると、2 は2 の秘密鍵を知っ ているのでpath_secret を復号でき、commit_secret を得られます。 43
  30. TreeKEM What happens if there are blanks in the tree?

    We calculate the resolution of the copath node to figure out which node's keys are available. Then, we encrypt the path secret of the UpdatePath node to each key でも木が常に全部埋まっているとは限りません、というか埋まっていないことのほうが多いです。その場合 はどうする?実際にやっているのはUpdatePathNode のcopath node に対してそのノードのresolution を計算 し、そのノードの下全ての葉が鍵を知っているノードの組み合わせを計算し、それぞれのノードの鍵に対し てpath_secret を暗号化します。 44
  31. TreeKEM The resolution of the node indicated right is [3,

    2] The indicated node has unmerged leaves so its resolution is itself + list of unmerged leaves 右の例ではresolution は[3, 2] (※順序付き)と計算されます。3 は unmerged leaves list を持っているので本体→unmerged list の順に計算 します。 45
  32. TreeKEM The resolution of the node indicated right is [3,

    2, 9, 14] The resolution is used (snip) 右の例では、まず左の木から[3, 2] 、続いて右の木から左優先で足し ていくので[3, 2, 9, 14] です。こうすることで、対象ノードから見て全 ノードに対して暗号化するために必要な鍵のノードの最小セットを 知ることができます。 46
  33. TreeKEM So actually what you do is: Calculate path_secret s

    for each node on UpdatePath then encrypt (snip) なので実際は、各UpdatePathNode に対して、copath node の resolution を取得し、resolution の各ノードの鍵に対して path_secret を暗号化する、ということをします。 47
  34. Evolution of a Group A group is updated through messages

    called proposals and commits Proposals Add and remove users Notifies an update of user's leaf key Injects Pre-Shared Keys Commits will fix those information and advances the group's epoch UpdatePath s are conveyed in the Commit 次はグループの変遷を見ていきましょう。Proposal とCommit という2 種類のメッセージを使ってグループの 状態を変更していきます。 48
  35. Evolution of a Group Users who want to join the

    group publishes their identity (including its public key) to a Directory using a KeyPackage グループに入りたいユーザーは、それぞれDirectory に自身の アイデンティティ情報を示すKeyPackage というものを登録し ます。 49
  36. Evolution of a Group User A creates an initial group

    To add User B , A sends an Add proposal adding B , then Commit s (snip) A は最初のグループを作り、B を追加するためには、B の KeyPackage を含むAdd メッセージとCommit を送信し、B には Welcome を送信します。 50
  37. Evolution of a Group When Add ing: Add the leaf_node

    from the KeyPackage in the proposal to the leftmost empty node Then add the leaf index to intermediate nodes' unmerged list Add のTreeKEM での動作はこう。KeyPackage からleaf_node を 取り出し一番左の空きに追加、でroot まで順にunmerged list に対象のノードindex を加えていきます。 51
  38. Evolution of a Group User B sends an Update proposal

    notifying the group of its leaf key update Then User A Commit s that update to include it in the epoch advancement ユーザーが鍵を更新するときはUpdate メッセージを送信しま す。 52
  39. Evolution of a Group When Update ing: Replace the leaf

    node of the sender with the leaf_node inside the Update proposal Then blank all nodes on its direct path up to the root Update のときは更新先のleaf_node が含まれてくるので、それ をsender のleaf_index に足し、root までのノードを空白化しま す 53
  40. Evolution of a Group When removing a user: Z sends

    a Remove proposal and a Commit B cannot decrypt () ユーザーのグループからの削除の際にはRemove proposal を使 います。Remove 後のcommit に含まれるUpdatePath をremove 対象のユーザーは復号できなくなっているので、remove され たことはわかるけど次の世代に進めません 54
  41. Evolution of a Group When Remove ing: Blank the specified

    node in the proposal Then blank all nodes on its direct path (snip) Update 同様、Remove では葉の削除後、root まで空白化しま す。その後に木の右半分が完全に空白なら木を縮めることを 行います 55
  42. Evolution of a Group When are intermediate parent nodes filled?

    During the processing of a Commit When processing a Commit , the UpdatePath inside the Commit is merged into the ratchet tree ParentNode s are created based on the UpdatePath content 空白化するといったけど中間ノードはどうやって埋まるの?ということについては、Commit の際に UpdatePath から得たUpdatePathNode を使って埋めていきます。UpdatePathNode を復号できたユーザーは path_secret を知っているので、そこからそのノードの鍵を導出します 56
  43. Stuff we are omitting here Injection of Pre-Shared Keys Transcript

    Hashes Hashes that summarize the proposals/commits taken place in the last epoch Signing/Verification of messages There are public messages and private messages というわけでMessaging Layer Security Any% 、タイマーストップです。完走した感想… ではなくて、Any% では 説明していない項目がかなりあります。RFC とか実装を読んでね 57
  44. 58

  45. It's not just a pack and unpack MLS has variable

    length vectors and optional values in their structs struct { opaque group_id<V>; uint64 epoch; ContentType content_type; opaque authenticated_data<V>; opaque encrypted_sender_data<V>; opaque ciphertext<V>; } PrivateMessage; 「バイナリの解析でしょ?pack/unpack じゃん、なんも難しいことないでしょ」っておもーじゃん? 60
  46. Variable length vectors struct { uint32 fixed<0..255>; opaque variable<V>; }

    StructWithVectors; Based on variable-length integer encoding in RFC 9000, Section 16 2-bit prefix (snip) MLS にはQUIC にある可変長整数エンコーディングを使った可変長文字列っていうのがあります。2^30 バイト までのベクターを表現できます。 61
  47. Optional values struct { uint8 present; select (present) { case

    0: struct{}; case 1: T value; }; } optional<T>; MLS にはoptional values といって存在するかどうかの変数と存在した場合に値が入っているstruct がありま す。ね?parse するのめんどそうでしょ? 62
  48. Define structs like this class Melos::Struct::PrivateMessage < Melos::Struct::Base attr_reader :group_id,

    :epoch, :content_type, :authenticated_data, :encrypted_sender_data, :ciphertext STRUCT = [ [:group_id, :vec], [:epoch, :uint64], [:content_type, :uint8], [:authenticated_data, :vec], [:encrypted_sender_data, :vec], [:ciphertext, :vec] ] でこんなんのencode/decode いちいち書いてられんので、メタプログラミングの出番です。こうやってstruct の定義をコードに落として 63
  49. Melos::Struct::Base #initialize , .new_and_rest : deserializer #raw : serializer These

    operate based on the STRUCT constant of the class 実態としては Melos::Struct::Base はこのSTRUCT 定数をベースにserialize/deserialize していきます 64
  50. Deserialize each element like this def deserialize_elem(buf, type, type_param) case

    type when :uint8 value = buf.byteslice(0, 1).unpack1('C') buf = buf.byteslice(1..) (snip) when :vec value, buf = Melos::Vec.parse_vec(buf) (snip) 各type のdeserialize はこうやってやっていきます。これ実際のところString を使ったバッファじゃなくて StringIO 一本でやるのがよさそうってのはわかってる 65
  51. Sometimes a class is nested class Melos::Struct::FramedContent < Melos::Struct::Base (snip)

    STRUCT = [ [:group_id, :vec], [:epoch, :uint64], [:sender, :class, Melos::Struct::Sender], [:authenticated_data, :vec], [:content_type, :uint8], (snip) ] でMLS のstruct ってstruct の中にstruct がネストされてることがありまして 66
  52. So we recursively call new when :class value, buf =

    type_param.send(:new_and_rest, buf) when :classes # prefix, length = buf.get_prefix_and_length # puts "#{prefix}, #{length}" vec, buf = Melos::Vec.parse_vec(buf) value = [] while (vec.bytesize > 0) current_instance, vec = type_param.send(:new_and_rest, vec) value << current_instance end そいつは :class タイプの追加の引数に対して send で new_and_rest を呼んで再帰的にバラします 67
  53. We sometimes have values that depend on other values class

    Melos::Struct::Sender < Melos::Struct::Base attr_reader :sender_type, :leaf_index, :sender_index STRUCT = [ [:sender_type, :uint8], [:leaf_index, :select, ->(ctx){ctx[:sender_type] == 0x01}, :uint32], [:sender_index, :select, ->(ctx){ctx[:sender_type] == 0x02}, :uint32], ] でこれみたいに sender_type によって値があるとかないとかみたいなやつがあって 68
  54. We call the Proc with the current context to handle

    that def deserialize_select_elem_with_context( buf, context, predicate, type, type_param) if predicate.(context) deserialize_elem(buf, type, type_param) else [nil, buf] end end それはProc を :select 形の引数にとって、これまで解析した値(context) を使ってProc を呼んであげた結果が true なら解析する、という方法でバラします 69
  55. Trees with arrays Complete balanced trees can be described with

    a flat array For example, the tree on the right will be written as: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, nil, 11, nil, nil, nil] あとRuby で木構造扱うのってポインタでやろうとすると 生のポインタないから厄介で、完全二分木だったらarray で表現できるのでそうします 70
  56. Trees with arrays Leaf nodes are always even indexed Parent

    nodes are always odd indexed (snip) そうするとleaf は偶数、parent は奇数、とか、あるノード index に対して右はどれ、左はどれ、みたいなのを木の性 質によって定義していきます 71
  57. Trees with arrays The algorithms are described in Appendix C

    of RFC 9420 Also this comes with a serialization/deserialization format! アルゴリズム自体はRFC の付録に書いてあります。あと serialization/deserialization format もついてきて便利 72
  58. 73

  59. HPKE using OpenSSL's API HPKE is nice, and OpenSSL itself

    has APIs that do this Talked about it at RubyConf Taiwan 2023 Haven't worked on it much since OpenSSL gem そのものにHPKE を入れる話をRubyConf Taiwan 2023 でしたんですが、そっからあんまり触って ないです 75
  60. HPKE using OpenSSL's API But is it a good idea?

    Protocols need the whole cipher suite Not only encap/decap and open/seal Also want access to constants such as hash/key length OpenSSL's HPKE context remembers which algorithm to use, but to use them separately you have to call them separately でも本当に嬉しいかと言われるとそうでもない気がしていて、プロトコルはハッシュの長さとかの定数や、 encap/decap 以外の機能へもアクセスしたくて、それはOpenSSL のHPKE は直接は提供してくれないからです ね 76
  61. Some APIs of OpenSSL gem are intentionally undocumented ...but I'm

    not gonna fix it. You have to know what you're doing to use them 前も言った気がするけどOpenSSL gem にはundocumented API がけっこうあります。がそれを直す気はない。 わかってる人にのみ使って欲しいAPI なんですよ 77
  62. Missing features in OpenSSL? def self.signature_key_pair_corresponds?(suite, private_key, public_key) private_pkey =

    suite.pkey.deserialize_private_signature_key(private_key) public_pkey = suite.pkey.deserialize_public_signature_key(public_key) if suite.pkey.equal?(Melos::Crypto::CipherSuite::X25519) || suite.pkey.equal?(Melos::Crypto::CipherSuite::X448) # is an Edwards curve; check equality of the raw public key private_pkey.raw_public_key == public_pkey.raw_public_key else # is an EC; check equality of the public key Point private_pkey.public_key == public_pkey.public_key end end もしかしたらないかもって機能として鍵ペアの対応を得る機能があった。こんな感じのしんどいコードにな る 78
  63. Missing features in OpenSSL? def self.derive_key_pair(suite, secret) pkey = suite.hpke.kem.derive_key_pair(secret)

    if suite.pkey.equal?(Melos::Crypto::CipherSuite::X25519) || suite.pkey.equal?(Melos::Crypto::CipherSuite::X448) # is an Edwards curve [pkey.raw_private_key, pkey.raw_public_key] else # is an EC [pkey.private_key.to_s(2), pkey.public_key.to_bn.to_s(2)] end end あとTLS やMLS が欲しい形のEC 鍵ペアのフォーマットを得る方法は自明じゃない 79
  64. Additional features in OpenSSL OpenSSL 3.5.0 ships with post-quantum cryptography

    ML-KEM, ML-DSA, SLH-DSA There is an Internet-Draft that adds ML-KEM in MLS OpenSSL 3.5.0 は耐量子暗号アルゴリズムのサポートがあります。ML-KEM のMLS への導入のドラフトがある ので、もしOpenSSL gem でサポートできたらRuby のMLS は真っ先にサポートできますね! 80
  65. Q: MLS is E2EE so client-side, right? Ruby is server-side

    lang lol もしかしたらこう聞く向きがあるかもしれません:MLS ってクライアントサイドの仕事でしょ?Ruby はサー バーサイド言語じゃん、笑 81
  66. A: NO Ruby is not just Rails We have ruby-wasm

    いいえ。Ruby はRails だけじゃないし、ruby-wasm って知ってる? 82
  67. Grand Unifying Cryptography API Different platforms depend on different cryptographic

    libraries Desktop: OpenSSL Compatible (to an extent) with LibreSSL, BoringSSL, and the like Browser: Web Crypto API Embedded: Mbed TLS, wolfSSL, ... ruby-wasm の話をしたので、ブラウザで暗号機能を動かす場合、Web Crypto API の助けを得る必要がありま す。各プラットフォームで異なる依存ライブラリに対して、 「大統一暗号ライブラリ」を提供することはで きないか?ということを最近考えています 83
  68. Grand Unifying Cryptography API Very quick example of calling Web

    Crypto API's random number generator require "js" array = JS::eval('return new Uint8Array(16)') JS.global[:window][:crypto].getRandomValues(array) p array ruby-wasm 経由でWeb Crypto API の乱数生成を呼ぶ簡単なサンプルがこれです。こんな感じで主要な暗号機 能に対してラッパーを用意していくことを考えています 84
  69. 85

  70. Why do you need End-to-End Encryption in Ruby? Because... (

    これはDanceDanceRevolution のネタです。ニコニコ大百科の「MAX.(period) 」 、 「Over the "Period" 」をご参照 ください) 87
  71. Ruby needs them to stay relevant or else people would

    just use Python, Go, Rust, whatever the cool kids use these days 第一に、Ruby がこれらを持たない場合、 「えーRuby にないの?じゃあいいや、イケてるモダンな言語である ところのPython/Go/Rust... で作っちゃえ」ってなるでしょう。ところでPython ってまだMLS 実装ないらしい ですね? 88
  72. Ruby needs Freedom on the Internet and the Free Internet

    needs Ruby そして、Ruby の発展のためには自由なインターネットは欠かすことができず、自由なインターネットも発展 のためにはRuby とそのコミュニティを必要とするでしょう。私はそのように信じています。 89
  73. Shoutouts The Messaging Layer Security Working Group @ IETF Protocol

    implementers in Ruby (the list is growing!) RubyKaigi 2025 organizer team, esp. the local organizers 謝辞。そういえばこの後プロトコル実装者のトークが本編セッションとLT に1 個ずつあるんですよ、当然聞 きに行きますよね? 90
  74. More Shoutouts Sponsors of RubyKaigi, esp: (ones I have personal

    connections with) codeTakt Inc. Bloomo Securities Inc. スポンサーさんはいいぞ。個人的につながりのあるところ。codeTakt さんは今の 現場の一つ。 「4 月仕事しねえぞ」って言って許してくれてありがとう。Bloomo さんはCEO が大学のゼミの同期でめっちゃびっくりした。 91
  75. Questions? / Comments? Twitter: @s01 or Fediverse: @[email protected] also find

    me in the venue / at drinkups! I am at: codeTakt Day2/Day4 Drinkup, RubyMusicMixin @ Day3 このへんにいるから気になることある人は話しかけてね。あと本番のスライドにはこの前に2 枚入ってるけ どそれは本編限定です 92