mirror of
https://github.com/He4eT/oddsquat.git
synced 2026-05-04 12:27:23 +00:00
Compare commits
38 commits
f0052a982b
...
ea6dd3ed9a
| Author | SHA1 | Date | |
|---|---|---|---|
| ea6dd3ed9a | |||
| 4d74847879 | |||
| 5845885ce8 | |||
| 6b5efce0c8 | |||
| 84bcd31301 | |||
| c7c9a038fe | |||
| ac7c41b185 | |||
| 9b2eb33e8e | |||
| e53110547d | |||
| 3263be22c9 | |||
| 3b86481104 | |||
| eb0e83a8d6 | |||
| 96b59ff9be | |||
| 7a9c22f951 | |||
| d51908a57d | |||
| 9a5bf50577 | |||
| 202d46ec7d | |||
| e08a52b636 | |||
| f167c06915 | |||
| 6065693999 | |||
| 07a44e6aad | |||
| efaf5a7c7e | |||
| 73ae752260 | |||
| d178592399 | |||
| 32a4df554d | |||
| d56506351e | |||
| 59abfb674e | |||
| 755035f978 | |||
| 1cc052b3a2 | |||
| b865797d8f | |||
| 47286f9e69 | |||
| 77bb66fbfa | |||
| 1c6a769e66 | |||
| a52760e71c | |||
| 89a193971a | |||
| e219ad07dc | |||
| c0c191c1f5 | |||
| 39fb5cf544 |
24 changed files with 976 additions and 56 deletions
|
|
@ -12,7 +12,7 @@
|
|||
<title>
|
||||
about | oddsquat
|
||||
</title>
|
||||
<meta name="description" content="General info about this website and the author">
|
||||
<meta name="description" content="General info about this website and the author.">
|
||||
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-32.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-27.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
|
||||
<p>
|
||||
I'm a front-end developer and a big fan of open-source,
|
||||
I’m a front-end developer and a big fan of open-source,
|
||||
customization, and minimalist software.<br>
|
||||
Member of the
|
||||
<a href='https://t.me/barbadbar' target='_blank'>BadBar</a> crew,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<title>
|
||||
oddsquat
|
||||
</title>
|
||||
<meta name="description" content="My own private fanzine">
|
||||
<meta name="description" content="My own private fanzine.">
|
||||
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-32.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-27.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ and so <strong>requires manual intervention by the user</strong>.</p>
|
|||
</header>
|
||||
<section class='description'>
|
||||
Interactive articles about physics, math, and engineering.
|
||||
It's probably the best website on the entire internet.<br>
|
||||
It’s probably the best website on the entire internet.<br>
|
||||
My favorite post is the one about
|
||||
<a href='https://ciechanow.ski/bicycle/' target='_blank'>bicycles</a>.
|
||||
</section>
|
||||
|
|
@ -283,7 +283,7 @@ and so <strong>requires manual intervention by the user</strong>.</p>
|
|||
<section class='description'>
|
||||
Torrenting can leave traces.<br>
|
||||
Check torrent downloads and distributions
|
||||
for your own or your neighbor's IP address.
|
||||
for your own or your neighbor’s IP address.
|
||||
</section>
|
||||
</article>
|
||||
</li>
|
||||
|
|
@ -338,7 +338,7 @@ and so <strong>requires manual intervention by the user</strong>.</p>
|
|||
<header>
|
||||
<strong>
|
||||
<a href='https://news.ycombinator.com/item?id=42492508' target='_blank'>
|
||||
Ask HN: Programmers who don't use autocomplete/LSP, how do you do it?
|
||||
Ask HN: Programmers who don’t use autocomplete/LSP, how do you do it?
|
||||
</a>
|
||||
</strong>
|
||||
</header>
|
||||
|
|
@ -352,7 +352,7 @@ and so <strong>requires manual intervention by the user</strong>.</p>
|
|||
<header>
|
||||
<strong>
|
||||
<a href='https://sneak.berlin/20201112/your-computer-isnt-yours/' target='_blank'>
|
||||
Your Computer Isn't Yours
|
||||
Your Computer Isn’t Yours
|
||||
</a>
|
||||
</strong>
|
||||
</header>
|
||||
|
|
@ -449,7 +449,7 @@ and so <strong>requires manual intervention by the user</strong>.</p>
|
|||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
Most software tutorials suck. Here's how to make one that doesn't.
|
||||
Most software tutorials suck. Here’s how to make one that doesn’t.
|
||||
</section>
|
||||
</article>
|
||||
</li>
|
||||
|
|
|
|||
427
docs/posts/2026/encrypted_XMPP/index.html
Normal file
427
docs/posts/2026/encrypted_XMPP/index.html
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32">
|
||||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||||
|
||||
|
||||
<title>
|
||||
encrypted XMPP | oddsquat
|
||||
</title>
|
||||
<meta name="description" content="Secure and private messaging with XMPP and OMEMO encryption.">
|
||||
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-32.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-27.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans-25.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans-24.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans-17.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/fonts.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/typography.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/main.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="stripesContainer">
|
||||
<div class="stripes">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">oddsquat</a></li>
|
||||
|
||||
|
||||
<li><a href="/posts/">
|
||||
posts</a></li>
|
||||
|
||||
|
||||
<li><a href="/posts/#2026">
|
||||
2026</a></li>
|
||||
|
||||
|
||||
<li>encrypted XMPP</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<article>
|
||||
<h1 id="end-to-end-encryption-inxmpp-with-omemo">End-to-End Encryption in XMPP with OMEMO</h1>
|
||||
<p>I find it funny that twenty years ago I was already trying
|
||||
to get people to switch to XMPP.</p>
|
||||
<p>For a long time, ICQ was extremely popular around me,
|
||||
but the proprietary messenger kept breaking things for people
|
||||
using alternative clients, which was quite annoying.
|
||||
After yet another round of this pointless battle
|
||||
I realized clearly that I prefer protocols over services.</p>
|
||||
<p>I didn’t have much success back then,
|
||||
but fortunately, XMPP (and I hope I have too)
|
||||
has continued moving forward over the past two decades.
|
||||
It has developed slowly, sometimes awkwardly, but steadily.</p>
|
||||
<p>Here, I won’t talk about why XMPP is great or how it works.
|
||||
You can check
|
||||
<a
|
||||
href='https://contrapunctus.codeberg.page/the-quick-and-easy-guide-to-xmpp.html'
|
||||
target='_blank'>
|
||||
this guide</a>
|
||||
(one of many) and I’d rather not write another one.
|
||||
In this post,
|
||||
I want to focus specifically on end-to-end encryption
|
||||
and the practical aspects of using it.</p>
|
||||
<h2 id="short-glossary">Short Glossary</h2>
|
||||
<p><strong>End-to-end encryption</strong> is a way
|
||||
to keep your chats truly private.<br>
|
||||
Only you and the person you’re messaging can read the messages.
|
||||
Not even the server owner has the keys
|
||||
needed to decrypt or modify them.</p>
|
||||
<p><strong>XMPP</strong> is an extensible protocol for instant messaging.
|
||||
It’s open, decentralized, and mature.</p>
|
||||
<p><strong>OMEMO</strong> is a <a
|
||||
href='https://omemo.top/'
|
||||
target='_blank'>widely supported</a>
|
||||
XMPP Extension Protocol (XEP)
|
||||
for secure multi-client end-to-end encryption.
|
||||
You can read more about
|
||||
it on a <a
|
||||
href='https://conversations.im/omemo/'
|
||||
target='_blank'>dedicated page by Daniel Gultsch</a>.</p>
|
||||
<p><strong>Client</strong>, in this post,
|
||||
means a specific instance
|
||||
of an XMPP application on a user device.
|
||||
<br>OMEMO-related documentation uses the term Device,
|
||||
but I find it potentially confusing:
|
||||
in practice, a single physical device
|
||||
can run multiple independent clients.</p>
|
||||
<h2 id="basic-concepts">Basic Concepts</h2>
|
||||
<p>This section introduces some basics of end-to-end encryption.</p>
|
||||
<p>If you’re already familiar with the concepts and terminology,
|
||||
you can skip ahead to <a
|
||||
href='#practical-aspects-of-omemo-and-xmpp'>how end-to-end encryption
|
||||
affects the XMPP user experience</a>,
|
||||
or jump straight to the <a
|
||||
href='#step-by-step-guide'>step-by-step workflow</a> I personally use.</p>
|
||||
<h3 id="trade-offs-between-safety-and-convenience">Trade-offs Between Safety and Convenience</h3>
|
||||
<p>Unfortunately, things that are truly secure are rarely convenient.
|
||||
They often require some initial efforts
|
||||
and a bit of ongoing attention.</p>
|
||||
<p>Telegram, which used to be a benchmark for messenger usability
|
||||
before its long dive into enshitification,
|
||||
really draws the line between convenience and security.
|
||||
Regular chats are easy and flexible,
|
||||
but “secret” chats come with a full set of limitations:
|
||||
they’re one-on-one only,
|
||||
can’t be synced to another device,
|
||||
aren’t available on desktop at all,
|
||||
and so on.</p>
|
||||
<p>All commercial so-called “secure” messengers, like Signal or WhatsApp,
|
||||
end up with pretty similar limitations,
|
||||
because it’s tricky to make end-to-end encrypted chats
|
||||
work the way users expect.</p>
|
||||
<p>Luckily, protocols and cryptography don’t care about
|
||||
convenience or user expectations.
|
||||
Many XMPP clients let you do almost anything you’re trying to do.
|
||||
Sometimes it’s clunky and unintuitive,
|
||||
sometimes it’s the kind of freedom
|
||||
that lets you shoot yourself in the foot.
|
||||
At the end of the day, you’d better understand what you’re doing.</p>
|
||||
<p>It might sound messy, but for that price, XMPP actually
|
||||
gives you a lot of handy features:
|
||||
your chats are secured with Signal-grade end-to-end encryption,
|
||||
and you can use as many devices as you want,
|
||||
all at the same time,
|
||||
without being tied to any proprietary service.</p>
|
||||
<p>In general, the XMPP experience today
|
||||
could be described as a “WhatsApp with benefits and frictions”.
|
||||
It’s kinda ironic, considering that WhatsApp’s protocol
|
||||
is actually based on XMPP, but incompatibly altered and defederated.</p>
|
||||
<h3 id="keys-fingerprints-and-trust">Keys, Fingerprints and Trust</h3>
|
||||
<p>OMEMO is based on the <a
|
||||
href='https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm'
|
||||
target='_blank'>
|
||||
Double Ratchet Algorithm</a>.
|
||||
While the internal details are quite interesting,
|
||||
for practical purposes it’s enough to know that
|
||||
each client stores some cryptographic keys
|
||||
and can derive a hash from them, commonly called a fingerprint.</p>
|
||||
<p>Keys are usually managed automatically by the XMPP client,
|
||||
and in normal use you should never need to handle them manually.
|
||||
In fact, you probably don’t even need to know what they look like.</p>
|
||||
<p>A fingerprint lets you identify
|
||||
a specific client of your contact
|
||||
and verify that it hasn’t been spoofed.
|
||||
Fingerprints for an account are not secret:
|
||||
clients publish their own fingerprints to the XMPP server
|
||||
and automatically receive the fingerprints of others.
|
||||
Only fingerprints you explicitly mark as trusted are relevant.</p>
|
||||
<p>In an typical scenario, the contact should confirm in person
|
||||
or through an already trusted and secure communication channel
|
||||
that the fingerprint belongs to their device,
|
||||
and only then you mark it as trusted.</p>
|
||||
<p>The list of trusted fingerprints
|
||||
is used at the moment a message is sent.
|
||||
Behind the scenes,
|
||||
OMEMO performs a certain amount of key management,
|
||||
and only the clients that are present in the trusted list
|
||||
at the time of encryption
|
||||
will be able to decrypt the message later.</p>
|
||||
<p>It’s important to understand
|
||||
that trust cannot be applied retroactively:
|
||||
it’s not possible to “extend” trust to new clients
|
||||
after a message has already been encrypted and sent.</p>
|
||||
<h2 id='practical-aspects-of-omemo-and-xmpp'>
|
||||
Practical Aspects of OMEMO and XMPP
|
||||
</h2>
|
||||
|
||||
<h3 id="chat-history">Chat History</h3>
|
||||
<p>In theory, XMPP supports server-side message history storage via
|
||||
<strong>XEP-0313: Message Archive Management</strong>.</p>
|
||||
<p>In practice, support for this XEP,
|
||||
as well as retention policies and message lifetime,
|
||||
depends on the specific server.
|
||||
You should never assume that all conversations are stored
|
||||
indefinitely by default.
|
||||
From a practical standpoint,
|
||||
the server-side MAM archive is better considered a cache:
|
||||
it can help you handle recent messages after a short period offline
|
||||
or synchronize conversations across multiple devices.</p>
|
||||
<p>At the end of the day,
|
||||
keeping your chat history is your responsibility,
|
||||
and this is a good place to apply a local-first approach.</p>
|
||||
<h3 id="synchronisation">Synchronisation</h3>
|
||||
<p>Seamless switching between clients is handled by
|
||||
<strong>XEP-0280: Message Carbons</strong>.
|
||||
Before its introduction, only incoming messages were synced between devices,
|
||||
while your own outgoing messages were not.
|
||||
Protocol-level mirroring of your own messages
|
||||
is a rather non-obvious feature :D</p>
|
||||
<p>It’s important to note that with end-to-end encryption,
|
||||
the concept of trusted fingerprints also applies to your own clients.
|
||||
For seamless synchronisation of outgoing messages,
|
||||
all your clients must trust each other’s fingerprints.
|
||||
A new client,
|
||||
or an old one that was not trusted
|
||||
at the time messages were sent,
|
||||
will receive the full history from MAM
|
||||
but will not be able to decrypt it.
|
||||
<br>Yes, even your own messages.</p>
|
||||
<p>In theory, re-encrypting messages on already trusted clients
|
||||
could solve this issue, but no XMPP client implements it yet.
|
||||
So in practice you may need to manually resend
|
||||
some data to a new device.</p>
|
||||
<h3 id="message-correction">Message Correction</h3>
|
||||
<p>It’s worth keeping in mind that
|
||||
features that seem simple and straightforward at first glance,
|
||||
such as message editing and deletion,
|
||||
actually rely on client-side implementation
|
||||
and may not behave for your recipient the way you expect.</p>
|
||||
<p>They’re fine to use and are well supported in some clients,
|
||||
but you shouldn’t rely on them to hide anything.</p>
|
||||
<h3 id="maintenance">Maintenance</h3>
|
||||
<p>OMEMO was designed as a set-it-and-forget-it solution
|
||||
and mostly succeeds in that goal.
|
||||
If you have a basic understanding of how the protocol works
|
||||
and check in online from time to time,
|
||||
there shouldn’t be any surprises.</p>
|
||||
<p>All maintenance comes down to making regular backups
|
||||
and notifying your contacts
|
||||
when fingerprints are added or no longer valid
|
||||
so they can keep their trust list up to date.</p>
|
||||
<h2 id="step-by-step-guide">Step-by-Step Guide</h2>
|
||||
<p>Let’s say I have a XMPP account, <code>me@some.server</code>,
|
||||
and a few devices:
|
||||
a phone, a laptop, and a desktop computer.
|
||||
First I’ll describe my mindset at a high level,
|
||||
then I’ll add some notes about specific clients.</p>
|
||||
<h3 id="client-roles">Client Roles</h3>
|
||||
<p>On the one hand, I have my phone.
|
||||
It’s almost always with me and almost always online.
|
||||
That’s where I keep the full chat history
|
||||
and get real-time notifications.</p>
|
||||
<p>On the other hand, I have a couple of desktop applications.
|
||||
I only open them
|
||||
when I need to discuss something using my keyboard
|
||||
or share some text between devices.
|
||||
I like to think of them as satellite clients.</p>
|
||||
<h3 id="before-the-start">Before the Start</h3>
|
||||
<p>First, enable OMEMO encryption
|
||||
on every client if it isn’t enabled by default.</p>
|
||||
<p>The next step is to add
|
||||
all clients to the trust list on each device:
|
||||
my phone should trust all my computers,
|
||||
and my computers should trust each other
|
||||
as well as my phone.</p>
|
||||
<p>Fingerprints do not have to be secret,
|
||||
so they can be published on
|
||||
your website or even on social media profiles.
|
||||
Here is my page with the fingerprints, for example:
|
||||
<br><a href='https://oddsquat.org/about/keys/' target='_blank'>
|
||||
https://oddsquat.org/about/keys/
|
||||
</a></p>
|
||||
<h3 id="start-the-conversation-inperson">Start the Conversation in Person</h3>
|
||||
<p>Let’s say I meet Alice,
|
||||
we start talking,
|
||||
and then decide to continue the conversation online.</p>
|
||||
<p>I open a special QR code on my phone,
|
||||
and Alice scans it with her client.
|
||||
This QR code already contains
|
||||
the fingerprints of all my devices,
|
||||
so no extra steps are needed on her phone.
|
||||
After that, I do the same
|
||||
and scan her QR code as well.</p>
|
||||
<p>Later at home,
|
||||
I manually mark her devices as trusted on my computers
|
||||
using the trusted list on my phone, and she does the same.</p>
|
||||
<p>Now we are both sure
|
||||
that it is really us in the conversation,
|
||||
and that all messages will be available
|
||||
on all our devices and only on them.</p>
|
||||
<h3 id="start-the-conversation-online">Start the Conversation Online</h3>
|
||||
<p>Let’s say Bob and I start discussing something
|
||||
on a forum or in the Fediverse,
|
||||
and then decide to continue the discussion on XMPP.</p>
|
||||
<p>Before starting the chat,
|
||||
Bob can confirm it’s really me using my page with fingerprints.
|
||||
I can confirm it’s really him
|
||||
by asking him to send his fingerprints
|
||||
in a private message on the same forum or via email.</p>
|
||||
<p>Ideally, Bob also has a public page with his fingerprints.
|
||||
That way, we can both independently verify
|
||||
that we are who we say we are.</p>
|
||||
<p>In an alternative scenario,
|
||||
where there has been no prior communication or public pages
|
||||
and only a single JID is known,
|
||||
things play out a bit differently:
|
||||
Bob starts the chat,
|
||||
I trust the first device he messages me from,
|
||||
and then we exchange fingerprints for our other devices,
|
||||
if we have any.
|
||||
This approach is called TOFU (Trust On First Use).</p>
|
||||
<h3 id="new-orlost-devices">New or Lost Devices</h3>
|
||||
<p>If I start using a new device
|
||||
or install another client application,
|
||||
the first thing I do is add it to the list
|
||||
of trusted clients on my existing devices.</p>
|
||||
<p>If I lose one of my devices
|
||||
or delete any private keys,
|
||||
the first thing I do is remove the corresponding client
|
||||
from the trusted list on my other devices.</p>
|
||||
<p>Once I’ve updated all my personal lists,
|
||||
I should inform my contacts about changes via trusted channels.</p>
|
||||
<p>I can simply ask Alice to scan
|
||||
my new QR code the next time we meet,
|
||||
and send Bob a message introducing
|
||||
my new client or letting him know
|
||||
that the lost device is no longer trusted
|
||||
and that no real messages will ever come from it again.</p>
|
||||
<h2 id="client-applications">Client Applications</h2>
|
||||
<p>This section describes
|
||||
how OMEMO is used in specific client applications
|
||||
that I personally use.</p>
|
||||
<h3 id="conversations-and-forks">Conversations and Forks</h3>
|
||||
<p><a
|
||||
href='https://conversations.im/'
|
||||
target='_blank'>
|
||||
Conversations</a> is a modern,
|
||||
fully featured chat application for Android.
|
||||
It supports everything a messaging app should support:
|
||||
chats, voice calls, video calls, and sharing files of any kind.</p>
|
||||
<p>There are several forks of it where
|
||||
the UI or UX may differ,
|
||||
but the core features work exactly the same.
|
||||
I personally use <a
|
||||
href='https://codeberg.org/monocles/monocles_chat'
|
||||
target='_blank'>
|
||||
Monocles Chat</a>.</p>
|
||||
<p>On the Contact Details screen (including your own account),
|
||||
you can see a list of published fingerprints
|
||||
and manually mark them as trusted or revoke trust.</p>
|
||||
<p>To simplify all these routine operations,
|
||||
a QR-code-based system is used:
|
||||
you can show your own QR code or scan other people’s codes
|
||||
directly from the main screen.
|
||||
This makes device verification during in-person meetings
|
||||
simple and effortless.</p>
|
||||
<h3 id="dino">Dino</h3>
|
||||
<p><a
|
||||
href='https://dino.im/'
|
||||
target='_blank'>
|
||||
Dino</a> is a lightweight GTK-based GUI client.</p>
|
||||
<p>It can be considered a fully functional one,
|
||||
although some non-essential features are still not implemented.
|
||||
For example,
|
||||
it is not possible to clear local chat history
|
||||
using built-in methods :D</p>
|
||||
<p>Trust and untrust decisions can be easily managed
|
||||
in the Encryption tab of the Conversation Details window.</p>
|
||||
<p>It is important to note that,
|
||||
by default, Dino is configured
|
||||
to automatically trust new fingerprints.
|
||||
I recommend disabling this feature.</p>
|
||||
<h3 id="profanity">Profanity</h3>
|
||||
<p><a
|
||||
href='https://profanity-im.github.io/'
|
||||
target='_blank'>
|
||||
Profanity</a> is a powerful TUI client
|
||||
where everything is controlled through a built-in command system.</p>
|
||||
<p>If you somehow intend to use it,
|
||||
you can find a small cheat sheet for the <code>omemo</code> command below.
|
||||
However, I strongly recommend reading the full documentation.</p>
|
||||
<ul>
|
||||
<li><p>Generate a key and add your other clients:</p>
|
||||
<pre><code class="language-text">/omemo gen
|
||||
/omemo trust me@some.server some-cool-fingerprint-01
|
||||
/omemo trust me@some.server another-cool-fingerprint
|
||||
/omemo qrcode</code></pre>
|
||||
</li>
|
||||
<li><p>View the list of your own or someone else’s fingerprints:</p>
|
||||
<pre><code class="language-text">/omemo fingerprint me@some.server
|
||||
/omemo fingerprint alice@another.server</code></pre>
|
||||
<p>Trusted ones will be marked as <code>trusted</code>.</p>
|
||||
</li>
|
||||
<li><p>Start an encrypted conversation:</p>
|
||||
<pre><code class="language-text">/omemo start alice@another.server</code></pre>
|
||||
</li>
|
||||
<li><p>Add fingerprints to the trusted list:</p>
|
||||
<pre><code class="language-text">/omemo trust alice@another.server some-cool-fingerprint-02
|
||||
/omemo trust alice@another.server some-cool-fingerprint-03
|
||||
/omemo trust bob@another.server some-cool-fingerprint-04</code></pre>
|
||||
</li>
|
||||
<li><p>Revoke trust for a specific client:</p>
|
||||
<pre><code class="language-text">/omemo untrust alice@another.server some-cool-fingerprint-02</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="late-disclaimer">Late Disclaimer</h2>
|
||||
<p>This post was originally intended
|
||||
as a collection of answers to questions
|
||||
I had when I first started using XMPP with OMEMO.</p>
|
||||
<p>It isn’t meant to be exhaustive or formal,
|
||||
but rather to clarify the practical side of things
|
||||
and reduce that initial feeling of being lost
|
||||
when you keep running into
|
||||
“The message was not encrypted for this device”
|
||||
over and over again.</p>
|
||||
<p>From now on, I hope you won’t encounter such errors
|
||||
or any other issues
|
||||
connected to end-to-end encryption in XMPP.</p>
|
||||
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
2026-04-16
|
||||
</footer>
|
||||
|
||||
<script async
|
||||
data-goatcounter="https://he4et.goatcounter.com/count"
|
||||
src="https://gc.zgo.at/count.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
25
docs/posts/2026/index.html
Normal file
25
docs/posts/2026/index.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta
|
||||
name="description"
|
||||
content="Redirect to '/posts/#2026'.">
|
||||
<meta
|
||||
http-equiv="Refresh"
|
||||
content="0; URL=/posts/#2026">
|
||||
<title>
|
||||
Redirect | oddsquat
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
Redirect to
|
||||
<a
|
||||
style="color: inherit;"
|
||||
href="/posts/#2026">
|
||||
/posts/#2026
|
||||
</a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
<title>
|
||||
ugly_keyboards | oddsquat
|
||||
ugly keyboards | oddsquat
|
||||
</title>
|
||||
<meta name="description" content="Почему нас окружают уродливые клавиатуры и что с этим можно сделать.">
|
||||
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
2026</a></li>
|
||||
|
||||
|
||||
<li>ugly_keyboards</li>
|
||||
<li>ugly keyboards</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<title>
|
||||
posts | oddsquat
|
||||
</title>
|
||||
<meta name="description" content="Сomplete list of posts">
|
||||
<meta name="description" content="Сomplete list of posts.">
|
||||
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-32.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/open_sans_condensed-27.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@
|
|||
<li><article class='entry'>
|
||||
<header>
|
||||
<strong>
|
||||
Cantor MX Tastatura
|
||||
Cantor MX Tastatura
|
||||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
Huge custom ergonomic mechanical Dactyl-Manuform (5×6) keyboard.
|
||||
Huge custom ergonomic mechanical Dactyl-Manuform (5×6) keyboard.
|
||||
</section>
|
||||
<section>
|
||||
<a href='https://github.com/He4eT/oddkb' target='_blank'>repository</a>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ layout: post
|
|||
lang: 'en'
|
||||
|
||||
title: 'about'
|
||||
description: 'General info about this website and the author'
|
||||
description: 'General info about this website and the author.'
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ description: 'General info about this website and the author'
|
|||
</div>
|
||||
|
||||
<p>
|
||||
I'm a front-end developer and a big fan of open-source,
|
||||
I’m a front-end developer and a big fan of open-source,
|
||||
customization, and minimalist software.<br>
|
||||
Member of the
|
||||
<a href='https://t.me/barbadbar' target='_blank'>BadBar</a> crew,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
layout: post
|
||||
lang: 'en'
|
||||
date: '2026-04-05'
|
||||
section: 'about'
|
||||
|
||||
title: 'keys'
|
||||
description: 'Public keys and fingerprints.'
|
||||
|
||||
section: 'about'
|
||||
date: '2026-04-05'
|
||||
|
||||
---
|
||||
|
||||
# Public Keys and Fingerprints
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
|
||||
description: 'My own private fanzine'
|
||||
description: 'My own private fanzine.'
|
||||
|
||||
css:
|
||||
- index
|
||||
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ in the middle of a conversation.
|
|||
</header>
|
||||
<section class='description'>
|
||||
Interactive articles about physics, math, and engineering.
|
||||
It's probably the best website on the entire internet.<br>
|
||||
It’s probably the best website on the entire internet.<br>
|
||||
My favorite post is the one about
|
||||
<a href='https://ciechanow.ski/bicycle/' target='_blank'>bicycles</a>.
|
||||
</section>
|
||||
|
|
@ -245,7 +245,7 @@ in the middle of a conversation.
|
|||
<section class='description'>
|
||||
Torrenting can leave traces.<br>
|
||||
Check torrent downloads and distributions
|
||||
for your own or your neighbor's IP address.
|
||||
for your own or your neighbor’s IP address.
|
||||
</section>
|
||||
</article>
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ in the middle of a conversation.
|
|||
<header>
|
||||
<strong>
|
||||
<a href='https://news.ycombinator.com/item?id=42492508' target='_blank'>
|
||||
Ask HN: Programmers who don't use autocomplete/LSP, how do you do it?
|
||||
Ask HN: Programmers who don’t use autocomplete/LSP, how do you do it?
|
||||
</a>
|
||||
</strong>
|
||||
</header>
|
||||
|
|
@ -314,7 +314,7 @@ in the middle of a conversation.
|
|||
<header>
|
||||
<strong>
|
||||
<a href='https://sneak.berlin/20201112/your-computer-isnt-yours/' target='_blank'>
|
||||
Your Computer Isn't Yours
|
||||
Your Computer Isn’t Yours
|
||||
</a>
|
||||
</strong>
|
||||
</header>
|
||||
|
|
@ -411,7 +411,7 @@ in the middle of a conversation.
|
|||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
Most software tutorials suck. Here's how to make one that doesn't.
|
||||
Most software tutorials suck. Here’s how to make one that doesn’t.
|
||||
</section>
|
||||
</article>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ layout: post
|
|||
lang: 'en'
|
||||
|
||||
title: 'posts'
|
||||
description: 'Сomplete list of posts'
|
||||
description: 'Сomplete list of posts.'
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
|
||||
lang: 'ru'
|
||||
date: '2020-11-08'
|
||||
|
||||
year: '2020'
|
||||
section: 'posts'
|
||||
|
||||
title: 'initial post'
|
||||
description: 'Первый пост в этом фэнзине, рассказывающий о его внутреннем устойстве.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2020'
|
||||
date: '2020-11-08'
|
||||
|
||||
---
|
||||
|
||||
# Initial Post
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
|
||||
lang: 'ru'
|
||||
date: '2020-11-18'
|
||||
|
||||
year: '2020'
|
||||
section: 'posts'
|
||||
|
||||
title: 'typographic linter'
|
||||
description: 'Prettier для текста. Автоматизация рутинной типографики.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2020'
|
||||
date: '2020-11-18'
|
||||
|
||||
---
|
||||
|
||||
# Типографика как code style
|
||||
|
|
|
|||
|
|
@ -4,4 +4,3 @@ layout: redirect
|
|||
redirectTarget: '/posts/#2024'
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
|
||||
lang: 'ru'
|
||||
date: '2024-01-15'
|
||||
|
||||
year: '2024'
|
||||
section: 'posts'
|
||||
|
||||
title: 'selfhosted LLM'
|
||||
description: 'Персональные LLM в docker-контейнере на твоём компьютере.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2024'
|
||||
date: '2024-01-15'
|
||||
|
||||
---
|
||||
|
||||
# Your Own Private Large Language Models
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
|
||||
lang: 'ru'
|
||||
date: '2024-07-27'
|
||||
|
||||
year: '2024'
|
||||
section: 'posts'
|
||||
|
||||
title: 'wrapped bw'
|
||||
description: 'Превращаем fully-featured Bitwarden command-line interface в удобный.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2024'
|
||||
date: '2024-07-27'
|
||||
|
||||
---
|
||||
|
||||
# Интеграция Bitwarden CLI с fzf и буфером обмена
|
||||
|
|
|
|||
6
src/pages/posts/2026.md
Normal file
6
src/pages/posts/2026.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
layout: redirect
|
||||
redirectTarget: '/posts/#2026'
|
||||
|
||||
---
|
||||
463
src/pages/posts/2026/encrypted_XMPP.md
Normal file
463
src/pages/posts/2026/encrypted_XMPP.md
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
lang: 'en'
|
||||
|
||||
title: 'encrypted XMPP'
|
||||
description: 'Secure and private messaging with XMPP and OMEMO encryption.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2026'
|
||||
date: '2026-04-16'
|
||||
|
||||
---
|
||||
|
||||
# End-to-End Encryption in XMPP with OMEMO
|
||||
|
||||
I find it funny that twenty years ago I was already trying
|
||||
to get people to switch to XMPP.
|
||||
|
||||
For a long time, ICQ was extremely popular around me,
|
||||
but the proprietary messenger kept breaking things for people
|
||||
using alternative clients, which was quite annoying.
|
||||
After yet another round of this pointless battle
|
||||
I realized clearly that I prefer protocols over services.
|
||||
|
||||
I didn’t have much success back then,
|
||||
but fortunately, XMPP (and I hope I have too)
|
||||
has continued moving forward over the past two decades.
|
||||
It has developed slowly, sometimes awkwardly, but steadily.
|
||||
|
||||
Here, I won’t talk about why XMPP is great or how it works.
|
||||
You can check
|
||||
<a
|
||||
href='https://contrapunctus.codeberg.page/the-quick-and-easy-guide-to-xmpp.html'
|
||||
target='_blank'>
|
||||
this guide</a>
|
||||
(one of many) and I’d rather not write another one.
|
||||
In this post,
|
||||
I want to focus specifically on end-to-end encryption
|
||||
and the practical aspects of using it.
|
||||
|
||||
## Short Glossary
|
||||
|
||||
**End-to-end encryption** is a way
|
||||
to keep your chats truly private.<br>
|
||||
Only you and the person you’re messaging can read the messages.
|
||||
Not even the server owner has the keys
|
||||
needed to decrypt or modify them.
|
||||
|
||||
**XMPP** is an extensible protocol for instant messaging.
|
||||
It’s open, decentralized, and mature.
|
||||
|
||||
**OMEMO** is a <a
|
||||
href='https://omemo.top/'
|
||||
target='_blank'>widely supported</a>
|
||||
XMPP Extension Protocol (XEP)
|
||||
for secure multi-client end-to-end encryption.
|
||||
You can read more about
|
||||
it on a <a
|
||||
href='https://conversations.im/omemo/'
|
||||
target='_blank'>dedicated page by Daniel Gultsch</a>.
|
||||
|
||||
**Client**, in this post,
|
||||
means a specific instance
|
||||
of an XMPP application on a user device.
|
||||
<br>OMEMO-related documentation uses the term Device,
|
||||
but I find it potentially confusing:
|
||||
in practice, a single physical device
|
||||
can run multiple independent clients.
|
||||
|
||||
## Basic Concepts
|
||||
|
||||
This section introduces some basics of end-to-end encryption.
|
||||
|
||||
If you’re already familiar with the concepts and terminology,
|
||||
you can skip ahead to <a
|
||||
href='#practical-aspects-of-omemo-and-xmpp'>how end-to-end encryption
|
||||
affects the XMPP user experience</a>,
|
||||
or jump straight to the <a
|
||||
href='#step-by-step-guide'>step-by-step workflow</a> I personally use.
|
||||
|
||||
### Trade-offs Between Safety and Convenience
|
||||
|
||||
Unfortunately, things that are truly secure are rarely convenient.
|
||||
They often require some initial efforts
|
||||
and a bit of ongoing attention.
|
||||
|
||||
Telegram, which used to be a benchmark for messenger usability
|
||||
before its long dive into enshitification,
|
||||
really draws the line between convenience and security.
|
||||
Regular chats are easy and flexible,
|
||||
but “secret” chats come with a full set of limitations:
|
||||
they’re one-on-one only,
|
||||
can’t be synced to another device,
|
||||
aren’t available on desktop at all,
|
||||
and so on.
|
||||
|
||||
All commercial so-called “secure” messengers, like Signal or WhatsApp,
|
||||
end up with pretty similar limitations,
|
||||
because it’s tricky to make end-to-end encrypted chats
|
||||
work the way users expect.
|
||||
|
||||
Luckily, protocols and cryptography don’t care about
|
||||
convenience or user expectations.
|
||||
Many XMPP clients let you do almost anything you’re trying to do.
|
||||
Sometimes it’s clunky and unintuitive,
|
||||
sometimes it’s the kind of freedom
|
||||
that lets you shoot yourself in the foot.
|
||||
At the end of the day, you’d better understand what you’re doing.
|
||||
|
||||
It might sound messy, but for that price, XMPP actually
|
||||
gives you a lot of handy features:
|
||||
your chats are secured with Signal-grade end-to-end encryption,
|
||||
and you can use as many devices as you want,
|
||||
all at the same time,
|
||||
without being tied to any proprietary service.
|
||||
|
||||
In general, the XMPP experience today
|
||||
could be described as a “WhatsApp with benefits and frictions”.
|
||||
It’s kinda ironic, considering that WhatsApp’s protocol
|
||||
is actually based on XMPP, but incompatibly altered and defederated.
|
||||
|
||||
### Keys, Fingerprints and Trust
|
||||
|
||||
OMEMO is based on the <a
|
||||
href='https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm'
|
||||
target='_blank'>
|
||||
Double Ratchet Algorithm</a>.
|
||||
While the internal details are quite interesting,
|
||||
for practical purposes it’s enough to know that
|
||||
each client stores some cryptographic keys
|
||||
and can derive a hash from them, commonly called a fingerprint.
|
||||
|
||||
Keys are usually managed automatically by the XMPP client,
|
||||
and in normal use you should never need to handle them manually.
|
||||
In fact, you probably don’t even need to know what they look like.
|
||||
|
||||
A fingerprint lets you identify
|
||||
a specific client of your contact
|
||||
and verify that it hasn’t been spoofed.
|
||||
Fingerprints for an account are not secret:
|
||||
clients publish their own fingerprints to the XMPP server
|
||||
and automatically receive the fingerprints of others.
|
||||
Only fingerprints you explicitly mark as trusted are relevant.
|
||||
|
||||
In an typical scenario, the contact should confirm in person
|
||||
or through an already trusted and secure communication channel
|
||||
that the fingerprint belongs to their device,
|
||||
and only then you mark it as trusted.
|
||||
|
||||
The list of trusted fingerprints
|
||||
is used at the moment a message is sent.
|
||||
Behind the scenes,
|
||||
OMEMO performs a certain amount of key management,
|
||||
and only the clients that are present in the trusted list
|
||||
at the time of encryption
|
||||
will be able to decrypt the message later.
|
||||
|
||||
It’s important to understand
|
||||
that trust cannot be applied retroactively:
|
||||
it’s not possible to “extend” trust to new clients
|
||||
after a message has already been encrypted and sent.
|
||||
|
||||
<h2 id='practical-aspects-of-omemo-and-xmpp'>
|
||||
Practical Aspects of OMEMO and XMPP
|
||||
</h2>
|
||||
|
||||
### Chat History
|
||||
|
||||
In theory, XMPP supports server-side message history storage via
|
||||
**XEP-0313: Message Archive Management**.
|
||||
|
||||
In practice, support for this XEP,
|
||||
as well as retention policies and message lifetime,
|
||||
depends on the specific server.
|
||||
You should never assume that all conversations are stored
|
||||
indefinitely by default.
|
||||
From a practical standpoint,
|
||||
the server-side MAM archive is better considered a cache:
|
||||
it can help you handle recent messages after a short period offline
|
||||
or synchronize conversations across multiple devices.
|
||||
|
||||
At the end of the day,
|
||||
keeping your chat history is your responsibility,
|
||||
and this is a good place to apply a local-first approach.
|
||||
|
||||
|
||||
### Synchronisation
|
||||
|
||||
Seamless switching between clients is handled by
|
||||
**XEP-0280: Message Carbons**.
|
||||
Before its introduction, only incoming messages were synced between devices,
|
||||
while your own outgoing messages were not.
|
||||
Protocol-level mirroring of your own messages
|
||||
is a rather non-obvious feature :D
|
||||
|
||||
It’s important to note that with end-to-end encryption,
|
||||
the concept of trusted fingerprints also applies to your own clients.
|
||||
For seamless synchronisation of outgoing messages,
|
||||
all your clients must trust each other’s fingerprints.
|
||||
A new client,
|
||||
or an old one that was not trusted
|
||||
at the time messages were sent,
|
||||
will receive the full history from MAM
|
||||
but will not be able to decrypt it.
|
||||
<br>Yes, even your own messages.
|
||||
|
||||
In theory, re-encrypting messages on already trusted clients
|
||||
could solve this issue, but no XMPP client implements it yet.
|
||||
So in practice you may need to manually resend
|
||||
some data to a new device.
|
||||
|
||||
### Message Correction
|
||||
|
||||
It’s worth keeping in mind that
|
||||
features that seem simple and straightforward at first glance,
|
||||
such as message editing and deletion,
|
||||
actually rely on client-side implementation
|
||||
and may not behave for your recipient the way you expect.
|
||||
|
||||
They’re fine to use and are well supported in some clients,
|
||||
but you shouldn’t rely on them to hide anything.
|
||||
|
||||
### Maintenance
|
||||
|
||||
OMEMO was designed as a set-it-and-forget-it solution
|
||||
and mostly succeeds in that goal.
|
||||
If you have a basic understanding of how the protocol works
|
||||
and check in online from time to time,
|
||||
there shouldn’t be any surprises.
|
||||
|
||||
All maintenance comes down to making regular backups
|
||||
and notifying your contacts
|
||||
when fingerprints are added or no longer valid
|
||||
so they can keep their trust list up to date.
|
||||
|
||||
## Step-by-Step Guide
|
||||
|
||||
Let’s say I have a XMPP account, `me@some.server`,
|
||||
and a few devices:
|
||||
a phone, a laptop, and a desktop computer.
|
||||
First I’ll describe my mindset at a high level,
|
||||
then I’ll add some notes about specific clients.
|
||||
|
||||
### Client Roles
|
||||
|
||||
On the one hand, I have my phone.
|
||||
It’s almost always with me and almost always online.
|
||||
That’s where I keep the full chat history
|
||||
and get real-time notifications.
|
||||
|
||||
On the other hand, I have a couple of desktop applications.
|
||||
I only open them
|
||||
when I need to discuss something using my keyboard
|
||||
or share some text between devices.
|
||||
I like to think of them as satellite clients.
|
||||
|
||||
### Before the Start
|
||||
|
||||
First, enable OMEMO encryption
|
||||
on every client if it isn’t enabled by default.
|
||||
|
||||
The next step is to add
|
||||
all clients to the trust list on each device:
|
||||
my phone should trust all my computers,
|
||||
and my computers should trust each other
|
||||
as well as my phone.
|
||||
|
||||
Fingerprints do not have to be secret,
|
||||
so they can be published on
|
||||
your website or even on social media profiles.
|
||||
Here is my page with the fingerprints, for example:
|
||||
<br><a href='https://oddsquat.org/about/keys/' target='_blank'>
|
||||
https://oddsquat.org/about/keys/
|
||||
</a>
|
||||
|
||||
### Start the Conversation in Person
|
||||
|
||||
Let’s say I meet Alice,
|
||||
we start talking,
|
||||
and then decide to continue the conversation online.
|
||||
|
||||
I open a special QR code on my phone,
|
||||
and Alice scans it with her client.
|
||||
This QR code already contains
|
||||
the fingerprints of all my devices,
|
||||
so no extra steps are needed on her phone.
|
||||
After that, I do the same
|
||||
and scan her QR code as well.
|
||||
|
||||
Later at home,
|
||||
I manually mark her devices as trusted on my computers
|
||||
using the trusted list on my phone, and she does the same.
|
||||
|
||||
Now we are both sure
|
||||
that it is really us in the conversation,
|
||||
and that all messages will be available
|
||||
on all our devices and only on them.
|
||||
|
||||
### Start the Conversation Online
|
||||
|
||||
Let’s say Bob and I start discussing something
|
||||
on a forum or in the Fediverse,
|
||||
and then decide to continue the discussion on XMPP.
|
||||
|
||||
Before starting the chat,
|
||||
Bob can confirm it’s really me using my page with fingerprints.
|
||||
I can confirm it’s really him
|
||||
by asking him to send his fingerprints
|
||||
in a private message on the same forum or via email.
|
||||
|
||||
Ideally, Bob also has a public page with his fingerprints.
|
||||
That way, we can both independently verify
|
||||
that we are who we say we are.
|
||||
|
||||
In an alternative scenario,
|
||||
where there has been no prior communication or public pages
|
||||
and only a single JID is known,
|
||||
things play out a bit differently:
|
||||
Bob starts the chat,
|
||||
I trust the first device he messages me from,
|
||||
and then we exchange fingerprints for our other devices,
|
||||
if we have any.
|
||||
This approach is called TOFU (Trust On First Use).
|
||||
|
||||
### New or Lost Devices
|
||||
|
||||
If I start using a new device
|
||||
or install another client application,
|
||||
the first thing I do is add it to the list
|
||||
of trusted clients on my existing devices.
|
||||
|
||||
If I lose one of my devices
|
||||
or delete any private keys,
|
||||
the first thing I do is remove the corresponding client
|
||||
from the trusted list on my other devices.
|
||||
|
||||
Once I’ve updated all my personal lists,
|
||||
I should inform my contacts about changes via trusted channels.
|
||||
|
||||
I can simply ask Alice to scan
|
||||
my new QR code the next time we meet,
|
||||
and send Bob a message introducing
|
||||
my new client or letting him know
|
||||
that the lost device is no longer trusted
|
||||
and that no real messages will ever come from it again.
|
||||
|
||||
## Client Applications
|
||||
|
||||
This section describes
|
||||
how OMEMO is used in specific client applications
|
||||
that I personally use.
|
||||
|
||||
### Conversations and Forks
|
||||
|
||||
<a
|
||||
href='https://conversations.im/'
|
||||
target='_blank'>
|
||||
Conversations</a> is a modern,
|
||||
fully featured chat application for Android.
|
||||
It supports everything a messaging app should support:
|
||||
chats, voice calls, video calls, and sharing files of any kind.
|
||||
|
||||
There are several forks of it where
|
||||
the UI or UX may differ,
|
||||
but the core features work exactly the same.
|
||||
I personally use <a
|
||||
href='https://codeberg.org/monocles/monocles_chat'
|
||||
target='_blank'>
|
||||
Monocles Chat</a>.
|
||||
|
||||
On the Contact Details screen (including your own account),
|
||||
you can see a list of published fingerprints
|
||||
and manually mark them as trusted or revoke trust.
|
||||
|
||||
To simplify all these routine operations,
|
||||
a QR-code-based system is used:
|
||||
you can show your own QR code or scan other people’s codes
|
||||
directly from the main screen.
|
||||
This makes device verification during in-person meetings
|
||||
simple and effortless.
|
||||
|
||||
### Dino
|
||||
|
||||
<a
|
||||
href='https://dino.im/'
|
||||
target='_blank'>
|
||||
Dino</a> is a lightweight GTK-based GUI client.
|
||||
|
||||
It can be considered a fully functional one,
|
||||
although some non-essential features are still not implemented.
|
||||
For example,
|
||||
it is not possible to clear local chat history
|
||||
using built-in methods :D
|
||||
|
||||
Trust and untrust decisions can be easily managed
|
||||
in the Encryption tab of the Conversation Details window.
|
||||
|
||||
It is important to note that,
|
||||
by default, Dino is configured
|
||||
to automatically trust new fingerprints.
|
||||
I recommend disabling this feature.
|
||||
|
||||
### Profanity
|
||||
|
||||
<a
|
||||
href='https://profanity-im.github.io/'
|
||||
target='_blank'>
|
||||
Profanity</a> is a powerful TUI client
|
||||
where everything is controlled through a built-in command system.
|
||||
|
||||
If you somehow intend to use it,
|
||||
you can find a small cheat sheet for the `omemo` command below.
|
||||
However, I strongly recommend reading the full documentation.
|
||||
|
||||
- Generate a key and add your other clients:
|
||||
```text
|
||||
/omemo gen
|
||||
/omemo trust me@some.server some-cool-fingerprint-01
|
||||
/omemo trust me@some.server another-cool-fingerprint
|
||||
/omemo qrcode
|
||||
```
|
||||
|
||||
- View the list of your own or someone else’s fingerprints:
|
||||
```text
|
||||
/omemo fingerprint me@some.server
|
||||
/omemo fingerprint alice@another.server
|
||||
```
|
||||
Trusted ones will be marked as `trusted`.
|
||||
|
||||
- Start an encrypted conversation:
|
||||
```text
|
||||
/omemo start alice@another.server
|
||||
```
|
||||
|
||||
- Add fingerprints to the trusted list:
|
||||
```text
|
||||
/omemo trust alice@another.server some-cool-fingerprint-02
|
||||
/omemo trust alice@another.server some-cool-fingerprint-03
|
||||
/omemo trust bob@another.server some-cool-fingerprint-04
|
||||
```
|
||||
|
||||
- Revoke trust for a specific client:
|
||||
```text
|
||||
/omemo untrust alice@another.server some-cool-fingerprint-02
|
||||
```
|
||||
|
||||
## Late Disclaimer
|
||||
|
||||
This post was originally intended
|
||||
as a collection of answers to questions
|
||||
I had when I first started using XMPP with OMEMO.
|
||||
|
||||
It isn’t meant to be exhaustive or formal,
|
||||
but rather to clarify the practical side of things
|
||||
and reduce that initial feeling of being lost
|
||||
when you keep running into
|
||||
“The message was not encrypted for this device”
|
||||
over and over again.
|
||||
|
||||
From now on, I hope you won’t encounter such errors
|
||||
or any other issues
|
||||
connected to end-to-end encryption in XMPP.
|
||||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
layout: post
|
||||
lang: 'ru'
|
||||
|
||||
title: 'ugly keyboards'
|
||||
description: 'Почему нас окружают уродливые клавиатуры и что с этим можно сделать.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2026'
|
||||
date: '2026-03-18'
|
||||
section: 'posts'
|
||||
|
||||
title: 'ugly_keyboards'
|
||||
description: 'Почему нас окружают уродливые клавиатуры и что с этим можно сделать.'
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ Incomplete list of my projects and experiments.
|
|||
- <article class='entry'>
|
||||
<header>
|
||||
<strong>
|
||||
Cantor MX Tastatura
|
||||
Cantor MX Tastatura
|
||||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
|
|
@ -141,7 +141,7 @@ Incomplete list of my projects and experiments.
|
|||
</strong>
|
||||
</header>
|
||||
<section class='description'>
|
||||
Huge custom ergonomic mechanical Dactyl-Manuform (5×6) keyboard.
|
||||
Huge custom ergonomic mechanical Dactyl-Manuform (5×6) keyboard.
|
||||
</section>
|
||||
<section>
|
||||
<a href='https://github.com/He4eT/oddkb' target='_blank'>repository</a>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
---
|
||||
|
||||
layout: post
|
||||
|
||||
lang: 'en'
|
||||
date: '2020-10-30'
|
||||
|
||||
year: '2020'
|
||||
section: 'posts'
|
||||
|
||||
title: 'markdown test page'
|
||||
description: 'A test document written using the Markdown language.'
|
||||
|
||||
section: 'posts'
|
||||
year: '2020'
|
||||
date: '2020-10-30'
|
||||
|
||||
---
|
||||
|
||||
# Markdown: Syntax
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ const tp = new Typograf({
|
|||
|
||||
const enabledRules = [
|
||||
'common/nbsp/*',
|
||||
'common/punctuation/apostrophe',
|
||||
'common/punctuation/quote',
|
||||
'en-US/dash/main',
|
||||
'ru/dash/main',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue