PageSourceSearch

https://vas3k.com/blog/end_to_end_encryption/

html vas3k.com collected 2026-09-24 10:19:24 UTC 48,991 bytes, 687 lines download raw bytes

1<!DOCTYPE html>
2<html lang="ru">
3    <head>
4        <title>
5    End-to-end Encryption — How We Stopped Trusting Clouds and Started Encrypting our Data —  Vastrik
6</title>
7        <meta charset="UTF-8">
8        <meta name="description" content="My blog about surviving in the world of technology and the cyberpunk going on around us">
9        <meta name="keywords" content="">
10        <meta name="author" content="@vas3k">
11        <meta name="yandex-verification" content="5f66353ad89fbe6f">
12        <meta name="fediverse:creator" content="@[email protected]">
13        <meta name="google-site-verification" content="B8zgWa65q_o7zEV-YAA3rmgq4AlT-l37W-2nNbDE6pc">
14        <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
15        <meta name="format-detection" content="telephone=no">
16        <link rel="canonical" href="https://vas3k.com/blog/end_to_end_encryption/">
17        
18    <meta name="robots" content="index, follow">
19    <meta property="author" content="@vas3k">
20    <meta property="article:publisher" content="https://vas3k.com">
21    <meta property="article:author" content="https://vas3k.com">
22    <meta property="article:published_time" content="2025-01-29 04:00:00">
23
24    <meta property="og:type" content="article">
25    <meta property="og:title" content="End-to-end Encryption" />
26    <meta property="og:description" content="How We Stopped Trusting Clouds and Started Encrypting our Data" />
27    <meta property="og:image" content="https://i.vas3k.blog/1c9f81b4798551233f074fa18dee74cb04167a1f9920817fdae35cee551bcaa4.jpg" />
28    <meta property="og:url" content="https://vas3k.com/blog/end_to_end_encryption/" />
29
30    <meta name="twitter:card" content="summary_large_image">
31    <meta name="twitter:title" content="End-to-end Encryption">
32    <meta name="twitter:description" content="How We Stopped Trusting Clouds and Started Encrypting our Data">
33    <meta name="twitter:image" content="https://i.vas3k.blog/1c9f81b4798551233f074fa18dee74cb04167a1f9920817fdae35cee551bcaa4.jpg">
34    <meta name="twitter:image:src" content="https://i.vas3k.blog/1c9f81b4798551233f074fa18dee74cb04167a1f9920817fdae35cee551bcaa4.jpg">
35    <meta name="twitter:creator" content="@vas3k">
36
37        <link rel="alternate" type="application/rss+xml" title="Full feed" href="https://vas3k.com/rss/"/>
38
39        
40<link rel="icon" type="image/png" href="/static/images/favicon_32.png" sizes="32x32">
41<link rel="icon" type="image/png" href="/static/images/favicon_64.png" sizes="64x64">
42<link rel="icon" type="image/png" href="/static/images/favicon_128.png" sizes="128x128">
43<link rel="shortcut icon" type="image/png" href="/static/images/favicon_square.png">
44<link rel="apple-touch-icon" type="image/png" href="/static/images/favicon_square.png">
45<link rel="mask-icon" href="/static/images/favicon_128.png" color="#5954ca">
46
47        
48<link rel="stylesheet" href="/static/css/normalize.css">
49<link rel="stylesheet" href="/static/css/fonts.css">
50<link rel="stylesheet" href="/static/css/theme.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
51<link rel="stylesheet" href="/static/css/base.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
52<link rel="stylesheet" href="/static/css/layout.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
53<link rel="stylesheet" href="/static/css/cards.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
54<link rel="stylesheet" href="/static/css/posts.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
55<link rel="stylesheet" href="/static/css/comments.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
56<link rel="stylesheet" href="/static/css/donates.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
57<link rel="stylesheet" href="/static/css/users.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
58<link rel="stylesheet" href="/static/css/fontawesome.css?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea">
59<link rel="stylesheet" href="/static/css/highlight/monokai_sublime.css">
60
61        
62
63<script src="/static/js/vendor/highlight.pack.js" async></script>
vendor: 1 bytes, line 63
63
64<script src="/static/js/vendor/tweemoji.min.js"></script>
vendor: 1 bytes, line 64
64
65<script src="/static/js/vendor/lightense.min.js"></script>
vendor: 1 bytes, line 65
65
66<script src="/static/js/vendor/htmx.min.js"></script>
vendor: 1 bytes, line 66
66
67<script src="/static/js/main.js?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea"></script>
vendor: 1 bytes, line 67
67
68<script src="/static/js/comments.js?v=fcf4fd7c4bc02ec5ef905a7487e93933b8cbe9ea"></script>
68
69
70<script>
71    window.addEventListener("htmx:configRequest", (event) => {
72        event.detail.headers["X-CSRFToken"] = "FXTRpqtQUtLwbAbRO91n7hvtNR5xOmAXK4WL7EbPrSMFn3XedT7SI9n4VcDyJcQU";
73    })
74</script>
74
75
76        
77        
77<script>
78            const theme = localStorage.getItem('theme') ||
79                  (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
80            document.documentElement.setAttribute('theme', theme);
81
82            htmx.onLoad(function() {
83                const themeSwitch = document.querySelector('.theme-switcher input[type="checkbox"]');
84                if (themeSwitch) {
85                    themeSwitch.checked = (theme === 'dark');
86                }
87            });
88        </script>
88
89    </head>
90    <body class="
91    
92" style="
93    
94    
95">
96        
97            
98
99
100<div class="header h-card">
101    <a href="/" class="header-logo u-url">
102        <img src="/static/images/logo.png" alt="" class="header-logo-image u-photo">
103        <span class="header-logo-title p-name">Vastrik</span>
104    </a>
105
106    <div class="button button-inverted button-round header-burger show-on-iphone"
107         onclick="return document.getElementById('header-menu').classList.toggle('header-menu-visible');"
108    >
109        ≡
110    </div>
111
112    <div class="header-menu hide-on-iphone" id="header-menu" hx-boost="true">
113        <a href="/all/" class="button button-inverted header-menu-item">
114            <span>✏️</span>
115            <span>Blog</span>
116        </a>
117
118        
119
120        <a href="/subscribe/" class="button button-inverted header-menu-item">
121            <span>✅</span>
122            <span>Subscribe</span>
123        </a>
124
125        <a href="/donate/" class="button button-inverted header-menu-item">
126            <span>👍</span>
127            <span>Donate</span>
128        </a>
129
130        <div class="button button-inverted button-round header-menu-item header-menu-round" onclick="return toggleHeaderSearch(event, '#header-search');">
131            🔍
132        </div>
133
134        
135    </div>
136</div>
137
138<div class="header-search header-search-hidden" id="header-search">
139    <div class="header-search-form">
140        <form action="https://www.google.ru/search?q=site%3Avas3k.com+">
141            <input type="hidden" name="domains" value="vas3k.com">
142            <input type="hidden" name="sitesearch" value="vas3k.com">
143            <input type="text" name="q" placeholder="Search the site..." class="header-search-form-input">
144            <button type="submit" class="header-search-form-submit">🔍</button>
145        </form>
146    </div>
147</div>
148
149        
150
151        
152<section class="content h-entry">
153    
154        <div class="container container-width-full">
155            
156
157
158
159<style>
160
161
162
163</style>
164
165<div class="headline">
166    
167        <div class="headline-image" style="background-image: url('https://i.vas3k.blog/cd8576e62f0513d8599e828d305186a0d09c936fa42a1eeab03a3738e5af085b.png');">
168            <img src="https://i.vas3k.blog/cd8576e62f0513d8599e828d305186a0d09c936fa42a1eeab03a3738e5af085b.png" alt="" class="the-cover">
169        </div>
170    
171
172    <div class="headline-info">
173        <div class="headline-info-inner">
174            <div class="headline-info-title-customize">
175                <div class="headline-info-title the-title p-name">
176                    
177                    End-to-end Encryption
178                </div>
179            </div>
180            
181                <div class="clearfix20"></div>
182                <div class="headline-info-subtitle the-subtitle p-summary">How We Stopped Trusting Clouds and Started Encrypting our Data</div>
183            
184            <div class="clearfix10"></div>
185            
186                <div class="headline-info-date hide-on-iphone dt-published">29 january 2025 — 0&nbsp;comments — 20145&nbsp;views — 4032&nbsp;words</div>
187            
188            <a rel="author" class="p-author h-card" href="https://vas3k.com" style="display: none;">@vas3k</a>
189        </div>
190    </div>
191</div>
192
193        </div>
194    
195
196    
197        
198            
199
200
201
202
203    <section class="block post-translations">
204        <div class="post-translations-title">This post is available in other languages 👉</div>
205        
206            <a href="https://es.vas3k.blog/blog/end_to_end_encryption/" class="button post-translation">
207                <div class="post-translation-language">Español</div>
208            </a>
209        
210            <a href="https://vas3k.blog/blog/end_to_end_encryption/" class="button post-translation">
211                <div class="post-translation-language">Russian</div>
212            </a>
213        
214    </section>
215
216
217        
218    
219
220    
221        <div class="container container-width-full h-entry">
222            <div class="post e-content">
223                <div class="block-text " id=""><p>Remember the situation: you want to send that fresh dank meme to your friend (let's say) Greg. You open your favorite messenger, find the chat with Greg, attach the meme and hit send.</p>
224<p>Behind the scenes, your messenger goes to some cloud, reads your chat history from a database, uploads your meme and pings your friend with a push notification that new top-tier content just arrived.</p>
225<p>That's how every chat app has worked since forever. Even a junior who just finished a &quot;Learn Python in 21 seconds from YouTube Shorts&quot; course, nowadays can build it in one evening with a couple of beers.</p>
226<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/64466b8d1e25fbe5c81af04a20ee07dc035612ea0080d128f8e43e7d675e8e2a.png" alt=""></figure>
227</div>
228<p>It was a great time! We lived happily in this simple and peaceful world until some governments (<a href="https://en.wikipedia.org/wiki/Online_Safety_Act_2023">1</a>, <a href="https://en.wikipedia.org/wiki/Regulation_to_Prevent_and_Combat_Child_Sexual_Abuse">2</a>, <a href="https://www.forbes.com/sites/zakdoffman/2025/02/24/fbis-new-iphone-android-security-warning-is-now-critical/">3</a>) decided that now they also want to read our spicy memes in our private correspondence and decide (spoilers for you, westerners) for which ones we should go straight to jail for.</p>
229<p>Welcome to the brave new internet!</p>
230<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/172260d00bde036cc0437a703034d88367362462aa79634f2f5f8a26019001dc.png" alt=""></figure>
231</div>
232<p>
232The good news is that end-to-end encryption was invented exactly for this – sending dank memes through &quot;untrusted&quot; channels so only the recipient can read them.</p>
233<p>You encrypt data at your end and can still store it on some random server that you don't really trust. Yes, we haven't ascended to <em>peer-to-peer enlightenment</em> yet – that comes in the next part, where we'll see how German and French parliaments exchange <em>le memes</em> through Matrix. So <a href="https://vas3k.com/subscribe/">subscribe</a> for the next post, or whatever content creators say.</p>
234<p>All cool kids today prefer end-to-end encryption (E2EE) and trying to distance themselves from the &quot;clouds&quot;. Not just because suffering makes them brave and sexy. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> though it does </span></span>
235
236 But because they're young and practical, they understand that clouds are still cheap and convenient for most non-geeky people.</p>
237<p>As long as &quot;real&quot; peer-to-peer software remains about as user-friendly as a 1988 cassette player, we're stuck with clouds. We just need to get creative on how we use them.</p>
238<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/b4793217d272533ad49978aee45ac24764b5af443034ee35e2502556219b5a21.png" alt=""></figure>
239</div>
240<p>For now, let's go back to the situation where we were sending our dank meme to Greg. Greg lives a thousand miles away from us, so we still need to use that sketchy thing called <em>The Internet</em>. No way around it.</p>
241<p>Time to dive into how encryption actually works.</p>
242<br><br>
243
244
245</div>
246<div class="block-text " id=""><p>We covered asymmetric encryption with its &quot;public&quot; and &quot;private&quot; keys in my old <a href="https://vas3k.com/blog/blockchain/">Blockchain post</a>, but nobody remembers that, so let's start fresh.</p>
247<p>All modern encryption can be divided into two categories: symmetric (AES) and asymmetric (RSA).</p>
248<p>Symmetric encryption is pretty straightforward – Greg and I agree beforehand on a special &quot;secret key&quot; that both encrypts and decrypts all our messages. It's like if we both had keys to the same apartment and could drop by anytime for drinks.</p>
249<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/d06d458fe576f64750eea8e8346ecf2155e20503e433d0ef77f88ee1224a0364.png" alt=""></figure>
250</div>
251<p>The problem? We somehow need to give each other that key in the first place.</p>
252<p>With apartment keys, Greg and I could meet in some quiet alley for the handoff. But on <em>The Internet</em>, there's no safe place – we're constantly at risk of having our data stolen or copied without even knowing it.</p>
253<p>So symmetric keys aren't great for starting new connections.</p>
254<p>But don't throw them out in a garbage just yet. Symmetric keys have major advantages: they're way shorter than asymmetric ones and much faster.</p>
255<p>Just look at an example: a 128-bit AES key is just 22 characters in base64. That's literally something you could write down on your palm.</p>
256<p>Yet it provides solid protection by today's standards.</p>
257<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/cf12116df3b130840d3bdf8f41965b65b407b8c044414b6b28df723b84c5b6f9.png" alt=""></figure>
258</div>
259<p>Just don't get it tattooed, please.</p>
260<div class="block-cite"><p>🔥 Fun fact: if you take your keyboard and smack your head with it about ten times, the result could work as a <del>terrible</del> symmetric key. Try it now!</p>
261</div>
262<p>The simplicity and speed of symmetric keys will come in handy when we encrypt huge files later.</p>
263<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/2fa9c838d6a130ced05fdb38b01c8f331231731fb0c1e55abe98faf62b59ba1a.png" alt=""></figure>
264</div>
265<p>To avoid sending secret keys across the internet, smart people invented asymmetric encryption.</p>
266<p>With asymmetric encryption, everyone gets two keys – <strong>a public key and a private key</strong>. These are basically two really long prime numbers connected by a simple math formula that I won't tell you yet...</p>
267<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/fae51920c885631828cc58bc1bf5afcd43b738d0bb11286f9a86113bd0936a19.png" alt=""></figure>
268</div>
269<p>Your private key is super-secret because it can decrypt anything encrypted with your public key. But your public key? Share it freely.</p>
270<p>You can send your public key to Greg, post it on your website, or even <a href="https://x.com/vas3k/status/1884032191950447078">tweet it</a>. Anyone can use it to encrypt a message that only you can read.</p>
271<p>To read it, of course, you need the private key. So keep that one safe :)</p>
272<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/976729a82f17c055c77c1eb9d96ecbfd2a6912abefbf24f63dba7184c4585df3.png" alt=""></figure>
273</div>
274<p>The public-private key pair has a cool reverse trick too: if you encrypt something with your private key, anyone who knows your public key can verify that YOU sent it, without even knowing your private key.</p>
275<p>What's that good for? Digital signatures! Like the ones you use in online banking or government services.</p>
276<div class="block-cite"><p>If you're amazed by all this math wizardry, check out <a href="https://en.wikipedia.org/wiki/The_Code_Book">&quot;The Code Book&quot; by Simon Singh</a>
276. It came out in the early 2000s, but nobody's written anything clearer about encryption from ancient times to (almost) modern TLS for regular folks.</p>
277</div>
278<p>Now you might be jumping up yelling: <em>Dude, if these asynchronous keys are so awesome, why'd you waste my time with that AES stuff?</em></p>
279<p>First, it's asymmetric, not asynchronous – read more carefully!</p>
280<p>Second, here's what a typical key pair looks like:</p>
281<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/94f70e01b875a73f524163604211de871537203c9a0128ce283feb8c077e621a.png" alt=""></figure>
282</div>
283<p>See the problem? These chunky boys can, at best, eat your entire bucket of KFC, but ask them to encrypt a 10TB file and they'll say <em>OOOFF</em> like your grandpa on a treadmill.</p>
284<p>That's why modern internet uses both types of keys, usually together, to cancel out each other's weaknesses.</p>
285<p>And I have even better news – you can mathematically derive one from the other!</p>
286<p>Meet the famous <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Hellman algorithm</a>, which makes crypto-nerds wet because it lets you elegantly create a symmetric key using just two asymmetric pieces: your private key and someone else's public key.</p>
287<p>It's beautiful and simple: if keys are just numbers, so with simple math operations (raising to powers, modulo division), both sides can end up with identical results, using just the over side's public keys and their own privates. Without exposing them. Brilliant!</p>
288<p>No joke. Every time you visit an https website (including this post), your browser performs a modern version of Diffie-Hellman to establish a secure connection with my server in Germany and show you the little green lock icon on top of your browser.</p>
289<p>So this isn't just nerdy stuff – you've been using it all along. Deal with it!</p>
290<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/ec2c04a7201ccc2aa0ba7b6aadcd6a72d984f43be42db091d7a30c01588bb5da.png" alt=""></figure>
291</div>
292<p>Great, encryption basics covered! Now you can add &quot;security expert&quot; to your resume and start cashing in.</p>
293<p>So we just exchange public keys, encrypt our stuff, and send it? That's it? Why do we need a whole post then? We've got TikToks to watch!</p>
294<p>TikToks can wait – we've got a problem here.</p>
295<p>Everything I've described only works for one-on-one chats between me and Greg. But these days, we're all living in group chats, and there, this approach falls apart completely.</p>
296<p>Let's tackle that next.</p>
297<br><br>
298
299
300</div>
301<div class="header-1" id="the-group-encryption-pro"><a href="#the-group-encryption-pro">The Group Encryption Problem</a></div>
302<div class="block-text " id=""><p>Houston, we have a problem. We've learned how to encrypt one-on-one messages, but now we've got a chat with 100+ people, and we want it all beautifully end-to-end encrypted so evil clouds can't look at our dank group memes.</p>
303<p>Let's think through some possible solutions:</p>
304<br><br>
305
306
307</div>
308<div class="block-text " id=""><div class="header-2" id="option-1-everyone-enc"><a href="#option-1-everyone-enc">🌚 Option 1: Everyone encrypts messages for everyone else</a></div>
309<p>We could think of a 100-person group chat as simply 100 different one-on-one chats. Why not, right?</p>
310<p>We know everyone else's public keys, so we can encrypt each message separately for each person and send it so that only they can decrypt it, while everyone else can just ignore it.</p>
311<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/a0de296e14550df04f56e7e9787c4edac531be6ad10f7b3a08cf1bf1973e033f.png" alt=""></figure>
312</div>
313<p>This means when we write a message to the chat, we encrypt it 100 times. Or 1000 times. Or a million times if there are a million participants.</p>
314<p>See the problem?</p>
315<p>With this approach, even if you want to send your buddies one meme, your little iPhone will struggle trying to encrypt it a thousand times that it won't just freeze for several minutes - it'll drain your battery enough that you can't call an Uber and have to walk home.</p>
316<p>But forget about your iPhone - there will be new one next year anyway. There's another problem: instead of one 1MB image, you need to store 1,000 identical encrypted files, about 1 GIGABYTE of data for each meme. No server will like it.</p>
317<p>After just a couple of memes, your friend chat will take up more space on the server than atoms in the universe, and your monthly data allowance will last about fifteen seconds.</p>
318<p>Is this the future you want? Doesn't seem like it. So forget this option - it's trash. Let's look at the next one.</p>
319<br><br>
320
321
322</div>
323<div class="block-text " id=""><div class="header-2" id="option-2-one-shared-e"><a href="#option-2-one-shared-e">🤝 Option 2: One shared encryption key for everyone</a></div>
324<p>Everyone agrees on one common encryption key for the whole chat, which can use to encrypt and decrypt any messages inside. This key is symmetric for everyone, as we learned earlier.</p>
325<p>In practice, usually the person who started the chat generates it and then shares through &quot;some&quot; secure connection with all other participants (using their asymmetric keys, for example).</p>
326<p>Don't smile - this is actually a decent option. Many &quot;old&quot; encrypted chats worked exactly this way for years, why not?</p>
327<p>The shared key gets transmitted over the network in encrypted form, it's easy to add new people to the chat by giving them our key, and the evil cloud never knows it. Our messages are safe!</p>
328<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/ddeb022b00a17e117784b2d63a0315d0aeef9fdc0d87fba141d61494934cffc2.png" alt=""></figure>
329</div>
330<p>But there are still some issues.</p>
331<p>First: <strong>how do we remove users from the chat?</strong></p>
332<p>Okay, if my dudes and I have more than 130 ICQ points (in total), we might invent a system where when one user gets removed, everyone else generates a new shared key to protect future messages.</p>
333<p>But this creates new technical problems with communicating this new key to participants who are offline right now - they temporarily lose access to the chat until they come back online and receive the new key.</p>
334<p>Fine, eventually everyone will get it - we can write this off as a &quot;UX problem&quot;. Maybe we send a special push notification to them, asking to go online and update their keys. Solvable.</p>
335<p>But there's a more serious issue: <strong>key leakage.</strong></p>
336<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/6d22f5d921fc11eda170a91efd6635587888c52ad4b48d291222055bb8164539.png" alt=""></figure>
337</div>
338<p>In a chat with a thousand people, this will happen sooner or later - someone will upload an unencrypted backup to iCloud, leave their phone in a bar, or future hackers might just brute-force our key. The probability of the latter is extremely small, but never zero. A chat might use the same key for years, giving hackers plenty of time to buy all the GPUs and hack you.</p>
339<p>Serious memes need more serious guarantees.</p>
340<p>Though we won't completely trash this method. Telegram's MTProto protocol in secret chats works exactly this way, despite all the downsides. They try to 
340smooth it over with UX tricks, offering, for example, auto-deletion of messages after 20 seconds.</p>
341<div class="block-cite"><p>🧠 You can easily confirm this right now by creating a secret chat in Telegram - it'll tell you something like <em>&quot;waiting for the other person to come online and exchange keys with you&quot;</em> and won't let you send any messages until then. Now you know why :)</p>
342</div>
343<div class="block-media block-media block-media__body width-75" id=""><figure><img src="https://i.vas3k.blog/0264b25ae20e5248d529fdab8dfd7dd812a19d2c5046bf91841bedb88125e514.png" alt=""></figure>
344</div>
345<p>Later we'll learn that even the god-loved Matrix uses a &quot;session key&quot; (which is the same thing) to improve performance in large chats. It just rotates more frequently. So it's not all black and white.</p>
346<br><br>
347
348
349</div>
350<div class="block-text " id=""><div class="header-2" id="option-3-each-new-me"><a href="#option-3-each-new-me">⚙️ Option 3: Each new message is encrypted with a new key</a></div>
351<p>This is similar to the previous option, but now we agree on a new shared key for each message sent. Now one key leakage isn't scary - it could only decrypt one specific message <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> which got probably leaked too </span></span>
352
353, not the entire chat.</p>
354<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/5e555a584ee188a2cc4b288146f9d416c1b0be8bffcb87f871774fea5dacd246.png" alt=""></figure>
355</div>
356<p>But we already found out that sending a new key between all participants each time is madness. We need some tricky trick here.</p>
357<p>So, imagine our chat is just starting. Participants exchange keys and get one shared key. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> this is easy to do at the beginning because each user clicks the Join Chat button themselves </span></span>
358
359 But in this third option, besides the key, they also agree on one more thing - a special algorithm that lets each participant mathematically derive the next key without asking others for help.</p>
360<p>You can visualize this as a magic box where we put our old key in one side, turn a handle, and it spits out a new one.</p>
361<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/db765e12e3967bf973dbdc3f78486b016b132d3f7232b14f281095b428ac9e69.png" alt=""></figure>
362</div>
363<p>Given the same input key, the box will always produce the same result. For all users. Even offline. And it'll be physically and mathematically impossible to turn the handle backward and get the original key from the new one.</p>
364<p>How? It's simple, even a schoolkid could understand: <strong>we can multiply our key by some prime number.</strong></p>
365<p>Here's a thought experiment: I give you a piece of paper with two numbers - <strong><em>107</em></strong> and <strong><em>283</em></strong>, and ask you to multiply them. You pull a calculator from your pocket and instantly tell me the answer - 30281.</p>
366<p>Took about four seconds, right?</p>
367<p>Now imagine the reverse: I give you a paper with <strong><em>30281</em></strong> written on it and ask you to tell me which two numbers I just multiplied to get this result.</p>
368<p>Difficult? Calculator not helping? Exactly.</p>
369<p>This example is very simplified but helps understand how our magic box might work - easily deriving a new key from an old one, but not vice versa. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> This sounds like Diffie-Hellman? It should! </span></span>
370
371 Crypto folks call this process <a href="https://en.wikipedia.org/wiki/Key_derivation_function">derivation</a>, and the new key is a &quot;derived key.&quot; That's just a fancy term you can drop to impress your friends.</p>
372<p>An algorithm that works in one direction but not the other is called a <strong><em>Ratchet mechanism</em></strong>. You've probably seen a ratchet screwdriver or <a href="https://www.google.com/search?q=ratchet%20key">wrench</a> that easily turns in one direction but not the other. That's where the name comes from.</p>
373<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/f53eccc7f49b07eacf7250fa07d8527b1896deb6461
3737d850fc8510aabc6c9545.png" alt=""></figure>
374</div>
375<p>From now on, I'll just call this mathemagical key generator a &quot;ratchet&quot;.</p>
376<br><br>
377
378
379</div>
380<div class="block-text " id=""><div class="block-media " id=""><figure><img src="https://i.vas3k.blog/150e91325e13c55c192acedfe0e54c8a5fb258ee5476ea0aad24e1ec88ab3ba9.png" alt=""></figure>
381</div>
382<p>OK, so our ratchet gives us a new key for each new message.</p>
383<p>If one key leaks, hackers won't be able to turn the ratchet backward to get old keys and read previous messages - that's good. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> crypto folks call this property &quot;Forward Secrecy,&quot; though it's more like Backward Secrecy, but who are we to judge smart people here? </span></span>
384
385 But what about new messages? The ratchet can still be turned forward easily.</p>
386<p>The problem is that there are only a finite number of <a href="https://en.wikipedia.org/wiki/Key_derivation_function">algorithms</a> for our ratchet. Maybe a dozen standard ones. Or up to a hundred if you count non-standard ones.</p>
387<p>We don't invent a new ratcheting algorithm every time for each new app. In cryptography, inventing own algorithms is a very bad practice!</p>
388<p>But this means a hacker who steals one key can simply try all the known algorithms from Wikipedia and find the right one to decrypt all our future messages. We need to fix this. Our memes are still in danger!</p>
389<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/8fff0da9e0e90bc89f7bedfbb834e1d30e90ae7469d5fcb7e1ba910b009ca277.png" alt=""></figure>
390</div>
391<p>What if our ratchet had some kind of code on it, like a combination lock? And two identical ratchets would only produce the same result if the code on them matches?</p>
392<p>Basically, as programmers would say, the ratchet now has a state that affects how it works.</p>
393<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/f801b278887b50ccd3c7d54966fa97d3d0e4164f47ce4fb382b8422ec1403223.png" alt=""></figure>
394</div>
395<div class="block-cite"><p>Anyone who remembers how the famous <a href="https://en.wikipedia.org/wiki/Enigma_machine">Enigma</a> encryption machine worked should be having war flashbacks right now. We're literally reinventing the same thing over and over...</p>
396</div>
397<p>But wait, doesn't this throw us back to Option 2 with all its problems? How will we all agree on this code? How will we tell it to the people who are offline?</p>
398<p>What if another chat participant is drinking beer at a neighborhood bar and can't stop right now to generate you a new public key?</p>
399<p>No worries. Let them finish their drink. Watch closely: we don't need to agree on a new code for every message - only when the other person wants to reply to us. Like this:</p>
400<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/ff4073876199722f7896dfbb481634a8f20ead8632550c34da1cb8df15dd5d11.png" alt=""></figure>
401</div>
402<p>So the code only changes when the second participant comes online and decides to write us back. Until then, we keep generating our keys with the same code.</p>
403<p>This means we can use our familiar Diffie-Hellman algorithm to exchange the new code.</p>
404<p>The second participant attaches their new public key to their messages, and we calculate a new shared code and set our ratchet to it to decrypt what they wrote.</p>
405<p>This creates a completely asynchronous exchange - we don't need to be in the chat and respond. We'll read and calculate all the codes and ratchets when we come back online.</p>
406<p>Next time when we want to write back, we'll similarly attach our new public key, and the other participant can take it (often right from the message) and calculate the next code on their side. The offline problem is solved!</p>
407<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/670636d040bbfece0868ee3fb799103a8e9f03520314e9cfe45ae9ede24ad439.png" alt=""></figure>
408</div>
409<p>Even if a hacker breaks into our chat somewhere in the middle of my monologue, they might decrypt a few messages, but after a new code exchange, they'll lose the ability to decrypt our cozy little chat again.</p>
410<p>This algorithm is called <a href="https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm">Double Ratchet</a> and its ability to <a href="https://eprint.iacr.org/2016/221.pdf">&quot;
410self-heal&quot;</a> after a breach is one of its main features.</p>
411<p>I recommend you to watch this great video:</p>
412<div class="block-media block-media block-iframe" id=""><figure><span class="ratio-16-9"><iframe loading="lazy" src="https://www.youtube.com/embed/7uEeE3TUqmU?autoplay=0&amp;controls=1&amp;showinfo=1&amp;vq=hd1080"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen"allowfullscreen></iframe></span></figure>
413</div>
414<p>All encrypted one-on-one chats in modern messengers like <strong>WhatsApp, Signal, Matrix</strong> use some variation of the Double Ratchet mechanism. Except Telegram, which doesn't encrypt regular chats at all, uses the old shared key method for secret chats and can't encrypt group chats at all.</p>
415<p>You know who else can't encrypt group chats? Double Ratchet 🤡🤡🤡</p>
416<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/1c6d17eb83c3c40476524346af20b34cf34acdf7205d2efd114655832ece8a37.png" alt=""></figure>
417</div>
418<p>Wait, what? What about group chats? We went through all this just to arrive at an algorithm that only works for one-on-one chats AGAIN? Are you high or something?</p>
419<p>Yes. So this post isn't over yet. You'll have to put up with me a bit longer.</p>
420<br><br>
421
422
423</div>
424<div class="header-1" id="how-it-actually-works-br"><a href="#how-it-actually-works-br">How It Actually Works<br><small>Messaging Layer Security</small></a></div>
425<div class="block-text " id=""><p>Modern messengers almost always use different types of algorithms for group chats versus one-on-one chats. Double Ratchet works great for 1-1 chats. Group chat logic is far more complex and usually full of tricks that developers use to balance between security and good UX.</p>
426<p>So far, they're not doing great :) Anyone who's seriously used Matrix, especially in groups with 500+ people, knows exactly what I'm talking about.</p>
427<p><em>&quot;Unable to decrypt message&quot;</em> still comes to me while I'm sleeping.</p>
428<p>Anyway, to give you a perspective on how cutting-edge this topic is - the first real encryption standard for group chat messages, MLS (Messaging Layer Security), was only released in 2023. That's newer than ChatGPT, folks! We're literally talking about bleeding edge stuff here. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> though of course they'd been developing it since the previous decade </span></span>
429
430</p>
431<p>Before MLS, every chat app invented their own mind-blowing encryption algorithms for groups, but now everyone's finally getting their act together and gradually moving to this standard.</p>
432<p>So put your Double Ratchet in the drawer and meet - Ratchet Tree!</p>
433<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/b6c14571709e460c9dc35892a48eac0c543545de954c97758b95cc78189196c2.png" alt=""></figure>
434</div>
435<p>The main problem this tree solves is how to quickly agree on a single &quot;key&quot; for our encryption ratchets as a group without transmitting it N×N times between each participant.</p>
436<p>It's built pretty simply: first, each chat participant starts at the very bottom of a basic binary tree.</p>
437<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/02aedfd2f744c1361d8452d96131bd95e7163b41ee94693836332587af06679a.png" alt=""></figure>
438</div>
439<p>Not all branches of the tree have to be occupied. The chat might have an odd number of participants, and people come and go.</p>
440<p>Then there are nodes higher up - from users to the root. These intermediate nodes don't do anything; they're just a convenient abstraction for getting a common root key.</p>
441<p>Each tree node has its own public-private key pair. Something like this:</p>
442<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/48a437c902b0dc18dc4daec950f5f1e979ed29394a7ddb90c294c82520e48838.png" alt=""></figure>
443</div>
444<p>Public keys aren't secret, so all chat participants can know them. But private keys are more interesting.</p>
445<p>In the MLS standard, private keys from tree nodes are only known to users who have a direct path from themselves to the root of the tree. So Greg, for example, only knows these private keys:</p>
446<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/9a20bee242734d5e46dc6feecdfc0b0c7a925ea9c190ab2700924b59d63d1a47.png" alt=""></figure>
447</div>
448<p>Each chat participant stores the entire tree locally.</p>
449<p>For &quot;their&quot; nodes (which come from them to the root), they know the private keys; for &quot;others&quot; - only public keys. But the most important thing, the whole reason for this circus - <strong>every chat participant knows the private key of the very top node of the tree</strong>. Its root. This key is the &quot;code&quot; that everyone enters into their ratchet boxes to read and sign new messages.</p>
450<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/94bc0a977680e35bfa98e1f76335cca0ebabca7a85390322d4568ec8a4b6882c.png" alt=""></figure>
451</div>
452<p>All users in such a chat live in harmony and peace, generating new keys using the common root, and encrypting messages with them. Everything's nice and peaceful.</p>
453<p>And then one day, Greg says: &quot;Hey, let's invite Bob to the chat?&quot; After all, group chats were invented to invite people into them, right?</p>
454<p>Bob bursts into the chat. First thing, he takes any free spot in the tree. <span class="block-spoiler"><span class="block-spoiler-button">?</span><span class="block-spoiler-text"> If there are no free spots, the whole tree grows and recalculates ke
454ys for new intermediate nodes. </span></span>
455
456</p>
457<p>Greg takes Bob's public key, encrypts the current tree snapshot with all the keys (except private ones) and forwards it to Bob. This is called a Welcome Message.</p>
458<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/bab39e84e2a433e171bd39032399a9bda584a259b6b859f8b40776e8ec6a6b80.png" alt=""></figure>
459</div>
460<p>There's an immediate problem - Bob doesn't have any private keys yet. So he can't yet encrypt messages with us yet. For that, he needs the root key.</p>
461<p>And we can't just tell him the old private keys up the tree, because then he could read our previous messages, and what if there were unflattering memes about him?</p>
462<p>Time to create a new root key!</p>
463<p>The beauty of our tree is that any chat participant (except Bob) can create a new root key.</p>
464<p>So let Greg do the work for everyone.</p>
465<p><strong><em>Step 1:</em></strong> Greg throws away his keys and creates new ones. He can create them from scratch or use a ratchet for style - it doesn't matter.</p>
466<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/2337c26b4c9dcc43817c652d031c6fa4a2b0a02b0891cc2bfab21df81d22df5c.png" alt=""></figure>
467</div>
468<p><strong><em>Step 2:</em></strong> Greg turns his ratchet handle to generate new keys for all nodes from himself up the tree to the very root. This upward regeneration is why it's called a Ratchet Tree.</p>
469<p>Now Greg knows the new root key, but others don't yet.</p>
470<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/93760bad381976b117b91bcdfc1ae7bb16bc1346360c2d6ba9b6e94d74022a36.png" alt=""></figure>
471</div>
472<p><strong><em>Step 3:</em></strong> Now Greg needs to safely communicate the new key to other chat participants.</p>
473<p>Let's start with Greg's closest neighbor. They live nearby, so they both know the key directly above them in the tree.</p>
474<p>Greg can encrypt the new key with the old public key of this shared node and send this message to his neighbor - <em>&quot;Bob, catch, use this now.&quot;</em></p>
475<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/9900c0c0be833c149f1145fa65b51f290881443f25243f10eb5389df687be744.png" alt=""></figure>
476</div>
477<p>Bob can decrypt and read it since he also knows the shared node key, and then fire up his ratchet and, just like Greg did earlier, calculate all the keys from himself up the tree. And since everyone's ratchet works the same way, the magic of math happens and Bob gets exactly the same keys that Greg got earlier! Including the new root key!</p>
478<p><strong><em>Step 4:</em></strong> With neighbors from another district, it's roughly the same story. Greg takes the well-known key of the neighboring subtree, encrypts the new private key with it, and passes it to the workers in the chat.</p>
479<p>And the workers don't need to regenerate their keys - they can stay as they are; they just need to learn the new root key.</p>
480<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/dd8d12b196ae66da062ec4dabae8cb36f60c3c89213b9b7c074cd67c3d644b3c.png" alt=""></figure>
481</div>
482<p>The same happens with the rest of the tree. You can figure this out by analogy - you're not dumb.</p>
483<p>In total, Greg only needs to send 3 messages for all 8 chat participants to learn the new root key. With small numbers this might seem trivial, but if there are, say, 15,000 people in the chat, a complete key rotation will take just 14 transmissions, not 15,000. For that kind of efficiency, developers deserve at least a case of beer.</p>
484<div class="block-cite"><p>Those who crammed LeetCode all night for interviews should now explain to everyone that we went from O(n) complexity to O(log), which is why everything got so beautifully, expensively, richly better.</p>
485</div>
486<div class="block-media " id=""><figure><img src="https://i.vas3k.blog/23d21dcb9e633dfd342993f2ad6c176c781aa1280d060bc4e8e96464472cc6df.png" alt=""></figure>
487</div>
488<p>The same situation happens when removing a user from the chat. The root key rotates so the removed person can't read new messages. The person responsible for key rotation in this case is either the one who did the remov
488ing or just some random unfortunate person from the chat.</p>
489<p>Voilà!</p>
490<p>This key tree doesn't even need to be stored directly on the server - it can be virtual and stored directly on each chat participant's computer. That's the second strength of MLS - it works great in peer-to-peer chats.</p>
491<p>But we'll talk about those next time.</p>
492<br><br>
493
494
495</div>
496
497            </div>
498        </div>
499    
500
501    
502        <div class="container container-width-max">
503            
504
505
506<section class="post-footer">
507    
508        <a href="/donate/" class="button button-red button-huuuuge">🍺 Say thanks to the author</a>
509    
510
511    
512
513<section class="post-links">
514    <div class="post-links-header">
515        ✅ Subscribe to new posts
516    </div>
517
518    <div class="post-links-description">
519        Subscribe to any of my channels so you don&#x27;t miss new posts. Email is usually the most reliable way but the Gen Z hate it, so I have socials too.
520    </div>
521
522    <div class="post-links-form">
523        <form action="/subscribe/" method="post">
524            <label class="post-links-form-label" for="inside_email">Your e-mail address:</label>
525            <div class="post-links-form-fields">
526                <input type="hidden" name="csrfmiddlewaretoken" value="FXTRpqtQUtLwbAbRO91n7hvtNR5xOmAXK4WL7EbPrSMFn3XedT7SI9n4VcDyJcQU">
527                <input type="text" name="name" style="position: absolute; left: -99999px;">
528                <input type="email" id="inside_email" name="email" placeholder="[email protected]" required="required">
529                <button type="submit" class="button button-red">Subscribe</button>
530            </div>
531            <div class="post-links-form-hint">
532                * no spam or ads, only new post notifications
533            </div>
534        </form>
535    </div>
536
537    <div class="post-links-sub-header">
538        Socials 👇
539    </div>
540
541    <div class="post-links-items">
542        
543        <a href="https://mas.to/@vas3kcom" class="button">Mastodon</a>
544        <a href="https://bsky.app/profile/vas3k.bsky.social" class="button">Bsky</a>
545        <a href="https://x.com/vas3kcom" class="button">Twitter</a>
546        <a href="https://ko-fi.com/vas3k" class="button">Ko-fi</a>
547        <a href="/rss/" class="button">RSS</a>
548    </div>
549</section>
550
551</section>
552
553        </div>
554    
555
556    
557        <div class="container">
558            
559
560
561
562<div class="comments">
563    
564
565    <div class="comments-list" id="comments-list">
566        
567    </div>
568</div>
569
570
571        </div>
572    
573
574    
575        <div class="container container-width-full">
576            
577
578
579
580
581
582    <section class="post-related">
583        <div class="post-related-title"><span><b>More?</b> Here you go</span></div>
584        <div class="cards-group cards-group-3x">
585            
586                
587
588<a href="/blog/bus_2022/" class="card card-post card-horizontal h-entry" style="background-image: url('https://i.vas3k.blog/deffc1ab5f94011f74afd7dbca5d6192674d1696659484f466c9715893f3c218.jpg');">
589    
590    <span class="card-views"><i class="fas fa-eye"></i>&nbsp;54.8K</span>
591    <span class="card-info">
592        <span >
593            <span class="card-title p-name">Vastrik Bus</span>
594        </span>
595        
596            <span class="clearfix10"></span>
597            <span class="card-subtitle p-summary">Second year. Exterior and «off-road» stuff</span>
598        
599    </span>
600</a>
601
602            
603                
604
605<a href="/blog/team/" class="card card-post card-horizontal h-entry" style="background-image: url('https://i.vas3k.blog/bced2c2166dc8f3246a53a78c702fcd14b34ee0f64e0d8918a7d3921b64d3755.jpg');">
606    
607    <span class="card-views"><i class="fas fa-eye"></i>&nbsp;46.2K</span>
608    <span class="card-info">
609        <span style="font-size: 130%;">
610            <span class="card-title p-name">A Team</span>
611        </span>
612        
613            <span class="clearfix10"></span>
614            <span class="card-subtitle p-summary">How to build awesome teams without bullshit</span>
615        
616    </span>
617</a>
618
619            
620                
621
622<a href="/blog/nocode/" class="card card-post card-horizontal h-entry" style="background-image: url('https://i.vas3k.ru/63e4025ac35bd9936e06ac390b08bc73029e8e2c62a62f509899c8567d725918.jpg');">
623    
624    <span class="card-views"><i class="fas fa-eye"></i>&nbsp;93.3K</span>
625    <span class="card-info">
626        <span style="font-size: 130%;">
627            <span class="card-title p-name">No Code</span>
628        </span>
629        
630    </span>
631</a>
632
633            
634        </div>
635    </section>
636
637
638        </div>
639    
640</section>
641
642
643        
644            <footer class="footer">
645                
646                    <div class="contacts">
647                        <div>Contact me &rarr;</div>
648                        <a href="mailto:[email protected]" class="contacts-item" target="_blank" rel="me">
649                            <i class="fas fa-envelope"></i>
650                            <span>[email protected]</span>
651                        </a>
652                        <a href="https://t.me/vas3k" class="contacts-item" target="_blank" rel="me">
653                            <i class="fab fa-telegram"></i>
654                            <span>Telegram</span>
655                        </a>
656                        <a href="https://x.com/vas3kcom" class="contacts-item" target="_blank" rel="me">
657                            <i class="fab fa-twitter-square"></i>
658                            <span>Twitter</span>
659                        </a>
660                    </div>
661                
662
663                <div class="footer-warning">
664                    You can use quotes, images and screenshots from my posts in your articles or presentations if you put a link to the original post nearby. Nothing can be used for commercial purposes.
665                </div>
666
667                <div class="footer-buttons">
668                    
669                        
670                            <a href="https://vas3k.blog" class="button button-inverted button-round header-menu-item header-menu-round">RU</a>
671                        
672                    
673                        
674                    
675
676                    <label class="theme-switcher button button-inverted button-round header-menu-item header-menu-round" onclick="return toggleTheme(event);" for="checkbox">
677                        <input type="checkbox" id="checkbox" />
678                        <span class="slider round"></span>
679                    </label>
680                </div>
681            </footer>
682        
683
684        
685    
685<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"f6c2372657ce4330b99d3af5fb724edd","r":1,"spa":2}' crossorigin="anonymous"></script>
685
686</body>
687</html>

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.