1"use strict";(globalThis.webpackChunkmy_site=globalThis.webpackChunkmy_site||[]).push([[4141],{53031(e,n,s){s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>a});const i=JSON.parse('{"id":"research/Tutorials/signal-protocol-tutorial/x3dh-protocol/what-is-x3dh","title":"Four-Handshake Agreement","description":"Extended Triple Diffie-Hellman Explained","source":"@site/docs/research/Tutorials/signal-protocol-tutorial/x3dh-protocol/10-what-is-x3dh.mdx","sourceDirName":"research/Tutorials/signal-protocol-tutorial/x3dh-protocol","slug":"/research/Tutorials/signal-protocol-tutorial/x3dh-protocol/what-is-x3dh","permalink":"/docs/research/Tutorials/signal-protocol-tutorial/x3dh-protocol/what-is-x3dh","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"title":"Four-Handshake Agreement"},"sidebar":"signalProtocolTutorial","previous":{"title":"Wax Seals","permalink":"/docs/research/Tutorials/signal-protocol-tutorial/foundations/cryptographic-signatures"},"next":{"title":"Four Types of Keys","permalink":"/docs/research/Tutorials/signal-protocol-tutorial/x3dh-protocol/public-key-types"}}');var r=s(74848),l=s(28453);const o={title:"Four-Handshake Agreement"},t="\ud83e\udd1d What is X3DH?",c={},a=[{value:"Extended Triple Diffie-Hellman Explained",id:"extended-triple-diffie-hellman-explained",level:2},{value:"\ud83c\udfaf The Simple Story",id:"-the-simple-story",level:2},{value:"\ud83e\udde0 Mental Model",id:"-mental-model",level:2},{value:"\ud83d\udcca See It Happen",id:"-see-it-happen",level:2},{value:"\ud83c\udfad The Story: Alice and Sleeping Beauty",id:"-the-story-alice-and-sleeping-beauty",level:2},{value:"\ud83c\udfae Try It Yourself",id:"-try-it-yourself",level:2},{value:"\ud83d\udd22 The Math",id:"-the-math",level:2},{value:"X3DH Step-by-Step",id:"x3dh-step-by-step",level:3},{value:"\ud83d\udca1 Why We Care",id:"-why-we-care",level:2},{value:"Why X3DH Matters",id:"why-x3dh-matters",level:3},{value:"Signal Protocol Flow",id:"signal-protocol-flow",level:3},{value:"\u2705 Quick Check",id:"-quick-check",level:2},{value:"\ud83d\udccb Key Takeaways",id:"-key-takeaways",level:2},{value:"\ud83c\udf89 What You'll Learn Next",id:"-what-youll-learn-next",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",br:"br",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components},{Details:s}=n;return s||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"-what-is-x3dh",children:"\ud83e\udd1d What is X3DH?"})}),"\n",(0,r.jsx)(n.h2,{id:"extended-triple-diffie-hellman-explained",children:"Extended Triple Diffie-Hellman Explained"}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"In 10 minutes:"})," Understand X3DH - the initial handshake for Signal Protocol",(0,r.jsx)(n.br,{}),"\n",(0,r.jsx)(n.strong,{children:"Prerequisite:"})," Diffie-Hellman + Signatures"]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-the-simple-story",children:"\ud83c\udfaf The Simple Story"}),"\n",(0,r.jsx)(n.p,{children:"Alice wants to send a message to Bob, but Bob is offline."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Problem:"})," Alice has never met Bob. How can she trust Bob's keys?"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Solution:"})," X3DH - Extended Triple Diffie-Hellman (actually ",(0,r.jsx)(n.strong,{children:"four"})," Diffie-Hellman operations!)"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Bob publishes keys to a server (while offline)"}),"\n",(0,r.jsx)(n.li,{children:"Alice downloads Bob's public keys"}),"\n",(0,r.jsx)(n.li,{children:"Alice sends an initial message"}),"\n",(0,r.jsx)(n.li,{children:"Four Diffie-Hellman operations combine to create a shared secret"}),"\n",(0,r.jsx)(n.li,{children:"Alice and Bob both derive the same secret!"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Even if Eve watches, she can't compute the same secret!"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-mental-model",children:"\ud83e\udde0 Mental Model"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Hold this picture in your head:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"X3DH = Extended Triple Diffie-Hellman\n\nActually uses FOUR Diffie-Hellman operations:\n\n DH1 = Alice_Identity \xd7 Bob_SignedPrekey\n DH2 = Alice_Ephemeral \xd7 Bob_Identity\n DH3 = Alice_Ephemeral \xd7 Bob_SignedPrekey\n DH4 = Alice_Ephemeral \xd7 Bob_OneTimePrekey\n\n Shared Secret = KDF(DH1 || DH2 || DH3 || DH4)\n\nAlice computes all 4 \u2192 gets S\nBob computes all 4 \u2192 gets S\n\nEve watches everything, still can't compute S!\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Think of it like:"})}),"\n",(0,r.jsxs)(n.p,{children:["\ud83e\udd1d ",(0,r.jsx)(n.strong,{children:"Four-handshake agreement"})," (Four layers of security)"]}),"\n",(0,r.jsxs)(n.p,{children:["\ud83d\udd10 ",(0,r.jsx)(n.strong,{children:"Quad-lock security"})," (Need to unlock 4 doors)"]}),"\n",(0,r.jsxs)(n.p,{children:["\u2694\ufe0f ",(0,r.jsx)(n.strong,{children:"Four-shield protection"})," (Aim for 4 weaknesses to break)"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-see-it-happen",children:"\ud83d\udcca See It Happen"}),"\n",(0,r.jsx)(n.p,{children:"Let's watch the X3DH handshake:"}),"\n",(0,r.jsx)(n.mermaid,{value:"sequenceDiagram\n participant Bob as Bob (Offline)\n participant Server as Server (Stores Keys)\n participant Alice as Alice
1(Online)\n participant Eve as Eve (Watches)\n\n Note over Bob: Bob is offline\n Note over Bob: Step 1: Bob creates keys\n\n Bob->>Server: Upload bob_identity_key\n Bob->>Server: Upload bob_signed_prekey\n Bob->>Server: Upload bob_one_time_prekey (optional)\n Bob->>Server: Upload signature of signed_prekey\n\n Note over Bob: Bob goes offline \u274c\n\n Note over Alice,Bob: 6 months later...\n Note over Alice: Alice wants to message Bob!\n\n Note over Alice: Step 2: Alice downloads keys\n\n Alice->>Server: Download Bob's public keys\n Server->>Alice: Send bob_identity_key\n Server->>Alice: Send bob_signed_prekey\n Server->>Alice: Send bob_one_time_prekey\n Server->>Alice: Send signature\n\n Note over Eve: Eve watches all keys\n\n Note over Alice: Step 3: Alice verifies keys\n\n Alice->>Alice: Verify signature on bob_signed_prekey\n Note over Alice: \u2705 Verified (Bob's keys, not Eve's!)\n\n Note over Alice: Step 4: Alice generates ephemeral\n\n Alice->>Alice: alice_ephemeral_key\n\n Note over Alice: Step 5: Alice computes 4 DH operations\n\n Alice->>Alice: DH1 = alice_identity \xd7 bob_signed_prekey\n Alice->>Alice: DH2 = alice_ephemeral \xd7 bob_identity\n Alice->>Alice: DH3 = alice_ephemeral \xd7 bob_signed_prekey\n Alice->>Alice: DH4 = alice_ephemeral \xd7 bob_one_time_prekey\n\n Note over Alice: Step 6: Alice derives shared secret\n\n Alice->>Alice: S = KDF(DH1 || DH2 || DH3 || DH4)\n\n Note over Alice: Step 7: Alice sends initial message\n\n Alice->>Server: Send initial message (with alice_ephemeral)\n Server->>Bob: Wait for Bob to come online...\n\n Note over Bob: Bob comes online! \u2705\n\n Note over Bob: Step 8: Bob receives\n\n Bob->>Bob: Get alice_ephemeral from message\n\n Note over Bob: Step 9: Bob computes 4 DH operations\n\n Bob->>Bob: DH1 = bob_signed_prekey \xd7 alice_identity\n Bob->>Bob: DH2 = bob_identity \xd7 alice_ephemeral\n Bob->>Bob: DH3 = bob_signed_prekey \xd7 alice_ephemeral\n Bob->>Bob: DH4 = bob_one_time_prekey \xd7 alice_ephemeral\n\n Note over Bob: Step 10: Bob derives shared secret\n\n Bob->>Bob: S = KDF(DH1 || DH2 || DH3 || DH4)\n\n Note over Alice,Bob: Both have S! Eve doesn't!\n\n Note over Eve: Eve saw everything\n Eve->>Eve: Can't compute S (missing ephemeral keys when Bob wasn't online)"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-the-story-alice-and-sleeping-beauty",children:"\ud83c\udfad The Story: Alice and Sleeping Beauty"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Bob"})," is always busy. He sleeps for months at a time (goes offline)."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Alice"})," needs to message Bob secretly. But Alice never met Bob!"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 1:"})," Bob prepares before sleeping"]}),"\n",(0,r.jsx)(n.p,{children:"Bob creates keys:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Identity key (permanent)"}),"\n",(0,r.jsx)(n.li,{children:"Signed pre-key (changes every week)"}),"\n",(0,r.jsx)(n.li,{children:"One-time pre-key (used once then deleted)"}),"\n",(0,r.jsx)(n.li,{children:"Signature of signed pre-key"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Bob uploads all to a server, then powers down his computer (offline)."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 2:"})," Six months later, Alice needs to message Bob"]}),"\n",(0,r.jsx)(n.p,{children:'Alice wakes up and realizes: "I need to send Bob a secret!"'}),"\n",(0,r.jsx)(n.p,{children:"Alice downloads Bob's public keys from the server."}),"\n",(0,r.jsx)(n.p,{children:"Alice verifies: Is this really Bob's signed pre-key? (Checks signature)"}),"\n",(0,r.jsx)(n.p,{children:"Alice generates: alice_ephemeral (temporary key, only for this message)"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 3:"})," Alice computes 4 DH operations"]}),"\n",(0,r.jsx)(n.p,{children:"Alice computes:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"DH1 = alice_identity \xd7 bob_signed_prekey"}),"\n",(0,r.jsx)(n.li,{children:"DH2 = alice_ephemeral \xd7 bob_identity"}),"\n",(0,r.jsx)(n.li,{children:"DH3 = alice_ephemeral \xd7 bob_signed_prekey"}),"\n",(0,r.jsx)(n.li,{children:"DH4 = alice_ephemeral \xd7 bob_one_time_prekey"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Alice derives: S = KDF(DH1 || DH2 || DH3 || DH4) (shared secret)"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 4:"})," Alice sends initial message"]}),"\n",(0,r.jsx)(n.p,{children:"Alice sends encrypted initial message + alice_ephemeral to Bob's server."}),"\n",(0,r.jsx)(n.p,{children:"Server holds it until Bob comes online."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 5:"})," Bob wakes up!"]}),"\n",(0,r.jsx)(n.p,{children:"Bob receives Alice's message, extracts alice_ephemeral."}),"\n",(0,r.jsx)(n.p,{children:"Bob computes the SAME 4 DH operations:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"DH1: bob_signed_prekey \xd7 alice_identity (same as Alice's, just reversed)"}),"\n",(0,r.jsx)(n.li,{children:"DH2: bob_identity \xd7 alice_ephemeral (same)"}),"\n",(0,r.jsx)(n.li,{children:"DH3: bob_signed_prekey \xd7 alice_ephemeral (same)"}),"\n",(0,r.jsx)(n.li,{children:"DH4: bob_one_time_prekey \xd7 alice_ephemeral (same)"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Bob derives: S = KDF(DH1 || DH2 || DH3 || DH4) (same S as Alice!)"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Step 6:"})," Both Alice and Bob have S!"]}),"\n",(0,r.jsx)(n.p,{children:"Now they can use S for the Double Ratchet (forward secrecy encryption)."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Eve's problem:"})," Eve watched all keys except... Alice's ephemeral! Alice hasn't even created it when Bob uploaded his keys. So Eve can't compute DH2, DH3, DH4!"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Result:"})," Alice and Bob share a secret, Eve can't compute it!"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-try-it-yourself",children:"\ud83c\udfae Try It Yourself"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Question 1:"})," Why does X3DH need FOUR Diffie-Hellman operations? Why not just one?"]}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsx)("summary",{children:"Show Answer"}),(0,r.jsx)(n.p,{children:"Because each DH operation provides a different type of security!"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"DH1"})," (Alice_Identity \xd7 Bob_SignedPrekey): Long-term security"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"DH2"})," (Alice_Ephemeral \xd7 Bob_Identity): Forward secrecy property"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"DH3"})," (Alice_Ephemeral \xd7 Bob_SignedPrekey): Mixes into entropy"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"DH4"})," (Alice_Ephemeral \xd7 Bob_OneTimePrekey): Deniability + extra security"]}),"\n"]}),(0,r.jsx)(n.p,{children:"Each operation:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Adds more entropy (randomness)"}
1),"\n",(0,r.jsx)(n.li,{children:"Covers different compromise scenarios"}),"\n",(0,r.jsx)(n.li,{children:"Creates a stronger shared secret than any single DH"}),"\n"]}),(0,r.jsx)(n.p,{children:"One DH operation would be vulnerable to:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Compromise of Alice's identity key"}),"\n",(0,r.jsx)(n.li,{children:"Compromise of Bob's identity key"}),"\n",(0,r.jsx)(n.li,{children:"Replay attacks"}),"\n"]}),(0,r.jsx)(n.p,{children:"Four operations cover all these cases and more!"}),(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Answer: Each DH adds different security properties, combined provide stronger security"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Question 2:"})," What if Eve steals Alice's ephemeral key after Alice sends the message?"]}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsx)("summary",{children:"Show Answer"}),(0,r.jsx)(n.p,{children:"Eve still can't compute the shared secret!"}),(0,r.jsx)(n.p,{children:"Why? Because Alice's ephemeral key was created AFTER Bob uploaded his keys!"}),(0,r.jsx)(n.p,{children:"Eve didn't have:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Alice_ephemeral when Bob uploaded keys"}),"\n",(0,r.jsx)(n.li,{children:"So Eve couldn't precompute: alice_ephemeral \xd7 Bob's keys"}),"\n"]}),(0,r.jsx)(n.p,{children:"By the time Eve gets alice_ephemeral from Alice's message:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Alice already used Bob's one-time pre-key (it's deleted)"}),"\n",(0,r.jsx)(n.li,{children:"Eve can't recompute DH4 (Bob's one-time pre-key is gone if Eve tries to impersonate Alice to Bob)"}),"\n"]}),(0,r.jsxs)(n.p,{children:["Each one-time pre-key is used ",(0,r.jsx)(n.strong,{children:"once"})," then ",(0,r.jsx)(n.strong,{children:"deleted"}),"!"]}),(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Answer: Bob's one-time pre-key is used once then deleted, Eve can't compute DH4"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Question 3:"}),' Why is the "Triple" DH actually ',(0,r.jsx)(n.strong,{children:"FOUR"})," diffie-hellman operations?"]}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsx)("summary",{children:"Show Answer"}),(0,r.jsx)(n.p,{children:"Historical naming! The protocol evolved:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Original: Triple DH (3 operations)"}),"\n",(0,r.jsx)(n.li,{children:"Later: Added DH4 (ephemeral \xd7 one-time pre-key) for extra properties"}),"\n",(0,r.jsx)(n.li,{children:'Name stayed "Triple DH" but operation count is 4!'}),"\n"]}),(0,r.jsx)(n.p,{children:"DH4 provides:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Deniability (Alice can deny sending the message)"}),"\n",(0,r.jsx)(n.li,{children:"Extra security against compromise"}),"\n",(0,r.jsx)(n.li,{children:"Better forward secrecy"}),"\n"]}),(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Answer: Historical name, but protocol evolved to 4 DH operations"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-the-math",children:"\ud83d\udd22 The Math"}),"\n",(0,r.jsx)(n.h3,{id:"x3dh-step-by-step",children:"X3DH Step-by-Step"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Setup (Bob uploads to server):"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Bob creates:\n - IK_B (Identity Key Bob) = public/private key pair\n - SPK_B (Signed Pre-Key Bob) = public/private key pair\n - OPK_B (One-Time Pre-Key Bob) = public/private key (optional, deleted after use)\n\nBob signs: SIG_B = Sign(SPK_B, IK_B) (signature of signed pre-key with identity key)\n\nBob uploads to server:\n - pk(IK_B), pk(SPK_B), pk(OPK_B), SIG_B\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Alice downloads from server:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Alice downloads:\n - pk(IK_B), pk(SPK_B), pk(OPK_B), SIG_B\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Alice verifies:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Alice checks: Is SIG_B valid for pk(SPK_B) using pk(IK_B)?\n - If yes: Bob's keys, proceed\n - If no: Eve replaced keys, reject!\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Alice generates ephemeral:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Alice creates:\n - EK_A (Ephemeral Key Alice) = public/private key pair\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Alice computes 4 DH operations:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"DH1 = DH(sk(IK_A), pk(SPK_B)) \u2190 Alice_identity \xd7 Bob_signed_prekey\nDH2 = DH(sk(EK_A), pk(IK_B)) \u2190 Alice_ephemeral \xd7 Bob_identity\nDH3 = DH(sk(EK_A), pk(SPK_B)) \u2190 Alice_ephemeral \xd7 Bob_signed_prekey\nDH4 = DH(sk(EK_A), pk(OPK_B)) \u2190 Alice_ephemeral \xd7 Bob_one_time_prekey\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Shared Secret:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"SK = KDF(DH1 || DH2 || DH3 || DH4)\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Alice sends:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Alice sends encrypted message + pk(EK_A) to Bob\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Bob receives and computes:"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"Bob extracts: pk(EK_A) from Alice's message\n\nBob computes DH1, DH2, DH3, DH4 (using his private keys)\n\nBob derives: SK = KDF(DH1 || DH2 || DH3 || DH4)\n"})}),"\n",(0,r.jsx)(n.p,{children:"Both now have the same shared secret SK!"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-why-we-care",children:"\ud83d\udca1 Why We Care"}),"\n",(0,r.jsx)(n.h3,{id:"why-x3dh-matters",children:"Why X3DH Matters"}),"\n",(0,r.jsx)(n.p,{children:"Without X3DH:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Alice can't establish trust with offline Bob"}),"\n",(0,r.jsx)(n.li,{children:"No secure way to start a conversation"}),"\n",(0,r.jsx)(n.li,{children:"Eve could replace Bob's keys with hers"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"With X3DH:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Alice can message offline Bob securely"}),"\n",(0,r.jsx)(n.li,{children:"Four layers of DH operations ensure security"}),"\n",(0,r.jsx)(n.li,{children:"Each one-time pre-key used once (deleted after)"}),"\n",(0,r.jsx)(n.li,{children:"Eve can't compute shared secret (missing ephemeral keys at key upload time)"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"signal-protocol-flow",children:"Signal Protocol Flow"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"X3DH (Initial Handshake):\n Alice downloads Bob's keys\n Alice verifies signatures\n Alice generates ephemeral\n Alice computes 4 DH \u2192 Shared secret SK\n Alice sends initial message\n\n Bob receives message\n Bob extracts ephemeral\n Bob computes 4 DH \u2192 Shared secret SK\n\n Alice and Bob both have SK!\n\nDouble Ratchet (Ongoing conversation):\n Use SK to derive root key (RK)\n Use RK to derive chain keys and message
1keys\n Encrypt messages with new key each time\n Delete keys after use (forward secrecy)\n\nWe'll learn Double Ratchet next!\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-quick-check",children:"\u2705 Quick Check"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Can you explain X3DH to a 5-year-old?"})}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsx)("summary",{children:"Try saying this out loud:"}),(0,r.jsx)(n.p,{children:"\"Bob leaves his keys in a mailbox while he's sleeping. Alice comes along and wants to leave him a secret. She takes his keys, adds her own secret key, and creates a special lock. Bob wakes up, uses his key and Alice's key, and opens the same secret. Both have the same secret, but a bad person watching can't figure it out!\""})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Why four DH operations?"})}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsx)("summary",{children:"Four benefits:"}),(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"DH1: Long-term identity security"}),"\n",(0,r.jsx)(n.li,{children:"DH2: Forward secrecy"}),"\n",(0,r.jsx)(n.li,{children:"DH3: Extra entropy"}),"\n",(0,r.jsx)(n.li,{children:"DH4: Deniability + one-time use"}),"\n"]}),(0,r.jsx)(n.p,{children:"Combined = Maximum security!"})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-key-takeaways",children:"\ud83d\udccb Key Takeaways"}),"\n",(0,r.jsxs)(n.p,{children:["\u2705 ",(0,r.jsx)(n.strong,{children:"X3DH"})," = Extended Triple Diffie-Hellman (actually 4 DH operations)",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Purpose:"})," Establish initial shared secret with offline user",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Four DH:"})," Identity \xd7 signed-prekey, ephemeral \xd7 identity, ephemeral \xd7 signed-prekey, ephemeral \xd7 one-time",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"One-time pre-key:"})," Used once then deleted",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Shared secret:"})," Derived from combining all 4 DH results",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Alice's role:"})," Generate ephemeral, download Bob's keys, compute 4 DH",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Bob's role:"})," Uses ephemeral from Alice, computes same 4 DH",(0,r.jsx)(n.br,{}),"\n","\u2705 ",(0,r.jsx)(n.strong,{children:"Next:"})," Use shared secret for Double Ratchet"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h2,{id:"-what-youll-learn-next",children:"\ud83c\udf89 What You'll Learn Next"}),"\n",(0,r.jsx)(n.p,{children:"Now you understand X3DH! Next, we'll learn about the different types of keys X3DH uses."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.a,{href:"/docs/research/Tutorials/signal-protocol-tutorial/x3dh-protocol/public-key-types",children:"\ud83d\udddd\ufe0f Continue: Four Types of Keys"})})}),"\n",(0,r.jsx)(n.p,{children:"We'll explore identity keys, signed pre-keys, one-time pre-keys, and ephemeral keys - what each does and why!"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.em,{children:"X3DH explained! Now let's learn about the four types of keys used in X3DH."})})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},28453(e,n,s){s.d(n,{R:()=>o,x:()=>t});var i=s(96540);const r={},l=i.createContext(r);function o(e){const n=i.useContext(l);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.