<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.rubdos.be/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.rubdos.be/" rel="alternate" type="text/html" /><updated>2026-05-07T12:48:03+00:00</updated><id>https://www.rubdos.be/feed.xml</id><title type="html">I’m Ruben. Welcome to my thoughts.</title><subtitle>I&apos;m (dr. ir.) Ruben De Smet (rubdos), I&apos;m about 30 years old, and I like computers with free software.
</subtitle><entry><title type="html">My Sailfish OS Journey: Apps for my daily needs</title><link href="https://www.rubdos.be/2026/04/17/my-sailfish-os-journey-apps.html" rel="alternate" type="text/html" title="My Sailfish OS Journey: Apps for my daily needs" /><published>2026-04-17T00:00:00+00:00</published><updated>2026-04-17T00:00:00+00:00</updated><id>https://www.rubdos.be/2026/04/17/my-sailfish-os-journey-apps</id><content type="html" xml:base="https://www.rubdos.be/2026/04/17/my-sailfish-os-journey-apps.html"><![CDATA[<p>I have been daily driving Sailfish OS since 2014,
and that has been made possible by the many apps I rely on.
In <a href="/2026/04/15/my-sailfish-os-journey.html">the first post of this series</a>,
I elaborated on where Sailfish OS comes from,
and on how I got to using it.
In this post, I’ll cover what apps I value most,
and the quirks that come with them.</p>

<h1 id="native-apps">Native apps</h1>

<p>The native Sailfish OS experience revolves around gesture based control,
very much like on the Nokia N9.
On the Nokia N9, you had a nice curved glass on the sides of the phone,
which elegantly captured the swiping motion you used to minimize an app.
Sailfish OS inherits those gestures,
and I find this way of navigating rather convenient.</p>

<p><img src="/assets/sfos-animations/swipe-away.webp" alt="Animation of swiping away an app" width="50%" /></p>

<p>How well those gestures work, depends on the quality of the port of Sailfish OS.
I have never had many troubles with this myself,
and I was told Jolla is taking extra care on the new Jolla Phone.</p>

<p>Native apps are built using stacked <em>pages</em>.
Clicking items in an app opens a page,
and moves in with an animation from the right.</p>

<p><img src="/assets/sfos-animations/push-page.webp" alt="Animation opening a page" width="50%" /></p>

<p>Closing a page follows the opposite motion:
swiping on the page to the right will “pop” the page from the stack,
more or less the analogue of Android’s “back” button.
Sailfish OS shows a little indicator on the top-left if this back-action is available.</p>

<p><img src="/assets/sfos-animations/swipe-back.webp" alt="Animation closing a page" width="50%" /></p>

<p>These gestures, together with colours, headers, font sizes, icons and more,
form a <a href="https://sailfishos.org/design/ux-framework/">consistent <em>design language</em> for the whole operating system</a>.
This is one of many reasons why I prefer native apps to Android AppSupport:
everything feels (and is!) integrated with the operating system.
Android Apps just feel <em>off</em>,
and they’re really a necessity rather than a convenience.</p>

<h1 id="my-day-on-sailfish-os">My day on Sailfish OS</h1>

<p>I am one of those people for whom waking up is a nightmare.
I get woken up by the lights in <a href="https://www.home-assistant.io/">my bedroom turning on 100% brightness, thanks to Home Assistant</a>.
If I need to access something in Home Assistant,
I open the user interface in the Sailfish OS
<a href="https://github.com/sailfishos/sailfish-browser/"><img src="/assets/sfos-icons/icon-launcher-browser.png" alt="Sailfish OS Browser icon" class="inline-icon" /> Browser</a>
(more on browsers below).
Home Assistant’s web interface works well enough for me.
The native Home Assistant apps aren’t to my liking,
and the Android app feels way more out of place than the browser does.</p>

<p>I usually grab my phone to scroll Reddit
<a href="https://github.com/abranson/quickddit">on <img src="https://raw.githubusercontent.com/abranson/Quickddit/7529b6c19dfe901138f9e4a2ec9666c491469d0e/sailfish/harbour-quickddit.svg" alt="Quickddit icon" class="inline-icon" /> Quickddit</a>
a bit before I get out of bed.
Or, admittedly, Instagram.
It happens. I’m sorry. At least I’m using the Android app in the AppSupport container,
as not to pollute my browser.
These days though, I really like <a href="https://mastodon.social/@rubdos">Mastodon</a>,
and I’ll usually have a quick scroll through
<a href="https://github.com/poetaster/harbour-tooter/">with <img src="https://github.com/poetaster/harbour-tooter/blob/bd87353166274cc4a9bb117ff001e5c11ae534ec/icons/128x128/harbour-tooterb.png?raw=true" alt="Tooter β icon" class="inline-icon" /> Tooter β</a>
as well.</p>

<p><img src="/assets/2026-sfos/quickddit.png" alt="Quickddit" width="23%" />
<img src="/assets/2026-sfos/tooter.png" alt="Tooter β" width="23%" />
<img src="/assets/2026-sfos/instagram.png" alt="Instagram Android" width="23%" />
<img src="/assets/2026-sfos/calendar.png" alt="Jolla Calendar" width="23%" /></p>

<p>(<img src="https://raw.githubusercontent.com/abranson/Quickddit/7529b6c19dfe901138f9e4a2ec9666c491469d0e/sailfish/harbour-quickddit.svg" alt="Quickddit icon" class="inline-icon" /> Quickddit,
<img src="https://github.com/poetaster/harbour-tooter/blob/bd87353166274cc4a9bb117ff001e5c11ae534ec/icons/128x128/harbour-tooterb.png?raw=true" alt="Tooter β icon" class="inline-icon" /> Tooter β,
Instagram Android,
<img src="/assets/sfos-icons/icon-launcher-calendar.png" alt="Jolla Calendar icon" class="inline-icon" /> Calendar)</p>

<p>Anyway, I should be telling those things to my therapist instead of blogging them.
At this point, I’ll unplug my phone around 80% battery charge,
because I limit the charging to preserve the battery life.
What my phone does after, depends entirely on the planning of the day.
To check my planning, I use the built-in <img src="/assets/sfos-icons/icon-launcher-calendar.png" alt="Jolla Calendar icon" class="inline-icon" /> Calendar application.
This app <a href="https://forum.sailfishos.org/t/open-sourcing-proceeding/24689/44?u=rubdos">is still closed source</a> as far as I can tell.
However, it’s excellent,
and it’s built on <a href="https://github.com/sailfishos/nemo-qml-plugin-calendar">the open source Nemo QML calendar plugin</a>.
Unless you’re a rebel with a cause,
you can’t legally <a href="https://together.jolla.com/question/58459/source-code-of-calendar-app/">find the Calendar app source code on <code class="language-plaintext highlighter-rouge">/usr/share/jolla-calendar</code></a> on your device.
I host my calendars on my Nextcloud instance at home.
Furthermore, I wrote a script that spits out my <a href="https://gitlab.com/rubdos/twics">Taskwarrior tasks as an ICS</a> file on scheduled and due dates, which is also ingested by the Calendar app.</p>

<p>Most of my days, I walk to my office at VUB.
It’s a short walk, and the shortest route passes by an incredibly nice sourdough bakery.
I can’t pay with my phone’s NFC there, which I honestly don’t mind.
They take cash and normal cards.</p>

<h1 id="driving">Driving</h1>

<p>I drive an EV, a Renault Zoe ZE40 from 2017.
It’s a lovely little thing.
Renault provides an Android app, which you can use to change some charging parameters,
or to remote start the climate control.
This is one of the very few Android apps that manages to detect the “non-legitimacy of my device”,
and I have <em>no clue whatsoever</em> why Renault would want to enforce a locked bootloader.
I had the app configured on a “real” Android device,
after which I could use the account via Home Assistant.
My <img src="/assets/sfos-icons/icon-launcher-browser.png" alt="Sailfish OS Browser icon" class="inline-icon" /> Browser has a shortcut to open the page for the car,
and I’m quite convinced that works even faster than opening the app.
Another advantage: I can built automations around this!</p>

<p>When driving, I will usually either listen to a podcast or to an album.
My Renault’s infotainment system connects to the phone via Bluetooth
(calls work fine, although there’s a microphone audio quality issue on the Xperia 10 IV and V).
I noticed that the car automatically triggers a Play action when it connects.
I abuse this by making a paused playlist when I’m heading out,
which then automatically starts when the car has booted up.
This is all just regular <a href="https://specifications.freedesktop.org/mpris/latest/">MPRIS over D-Bus</a> at the Sailfish OS side.</p>

<p><img src="/assets/2026-sfos/home-assistant-zoe.png" alt="Home Assistant in the Browser" width="23%" />
<img src="/assets/2026-sfos/unplayer.png" alt="Unplayer" width="23%" />
<img src="/assets/2026-sfos/gpodder.png" alt="gPodder" width="23%" />
<img src="/assets/2026-sfos/whisperfish.png" alt="Whisperfish" width="23%" /></p>

<p>(Home Assistant in the <img src="/assets/sfos-icons/icon-launcher-browser.png" alt="Sailfish OS Browser icon" class="inline-icon" /> Browser, controlling my car,
<img src="https://github.com/equeim/unplayer/blob/798fbe4cbf776470b89b3de5677ab17b349c66f8/icons/hicolor/128x128/apps/harbour-unplayer.png?raw=true" alt="Unplayer icon" class="inline-icon" /> Unplayer,
<img src="https://github.com/gpodder/gpodder-sailfish/blob/02cfe94dd5bba8d90009705f32e21f01b5f86b74/icons/128x128/apps/harbour-org.gpodder.sailfish.png?raw=true" alt="gPodder Sailfish icon" class="inline-icon" /> gPodder,
<img src="https://gitlab.com/whisperfish/whisperfish/-/raw/7151ac297d05e7761f4f3e8578a9827d5ee8820f/icons/128x128/harbour-whisperfish.png" alt="Whisperfish Icon" class="inline-icon" /> Whisperfish)</p>

<p>If it’s music I’m listening to,
<del>I generally use <a href="https://github.com/equeim/unplayer/"><img src="https://github.com/equeim/unplayer/blob/798fbe4cbf776470b89b3de5677ab17b349c66f8/icons/hicolor/128x128/apps/harbour-unplayer.png?raw=true" alt="Unplayer icon" class="inline-icon" /> Unplayer</a>.
It doesn’t have gapless playback, and hasn’t been updated in some centuries,
but it’s otherwise fast and easy to use.</del>
(See post-scriptum below.)
My music is stored on a 64GB µSD card in <a href="https://opus-codec.org/">Opus VBR format</a>.
I have yet to test whether <a href="https://openrepos.net/content/carmenfdezb/deadbeef-silica-armv7hlaarch64i486"><img src="https://openrepos.net/sites/default/files/styles/thumbnail/public/packages/5984/icon-deadbeef-silica_0.png?itok=g6rxDz2r" alt="DeadBeef Silica Icon" class="inline-icon" /> DeadBeef Silica</a> works for me;
I <a href="https://social.nah.re/@alex/116320711143099936">was told it supports Opus <em>and</em> gapless playback</a>.</p>

<p>Often, I’ll be listening to music over Bluetooth.
I have Sennheiser Momentum earbuds (MTW4).
I can’t recommend them, the MTW series has quality control issues.
My current ones didn’t break yet.
They sound incredible (even without Apt-X support, not sure which magic drives them currently),
and their noise cancellation is terrific.
I also have a <a href="https://www.smsl-audio.com/portal/product/detail/id/830.html">Bluetooth DAC</a>
and a <a href="https://www.smsl-audio.com/portal/product/detail/id/565.html">Bluetooth DAC-and-AMP</a> from SMSL.
In general, Bluetooth audio works rather well, as far as Bluetooth audio goes.
The Xperia 10 IV and V issue regarding Bluetooth microphone quality is annoying,
and so is the lack of Apt-X support.
I am quite confident that the former will not be an issue on the Jolla Phone,
and the latter doesn’t really bother me.
It’s Bluetooth after all.
If it’s quality that I’m after, the SMSL’s have USB and optical inputs.</p>

<p><del>For podcasts, <a href="https://github.com/gpodder/gpodder-sailfish"><img src="https://github.com/gpodder/gpodder-sailfish/blob/02cfe94dd5bba8d90009705f32e21f01b5f86b74/icons/128x128/apps/harbour-org.gpodder.sailfish.png?raw=true" alt="gPodder Sailfish icon" class="inline-icon" /> gPodder</a>
is pretty much perfect.</del>
(See post-scriptum below.)
I currently have a bug where its start-up takes some minutes because one of the podcasts is super slow to load.
Haven’t had the time to debug it yet.</p>

<h1 id="back-home">Back home</h1>

<p>The one app which I use the most is <a href="https://gitlab.com/whisperfish/whisperfish/"><img src="https://gitlab.com/whisperfish/whisperfish/-/raw/7151ac297d05e7761f4f3e8578a9827d5ee8820f/icons/128x128/harbour-whisperfish.png" alt="Whisperfish Icon" class="inline-icon" /> Whisperfish</a>.
I somehow got most of my friends and family on Signal,
and Whisperfish is my way of staying in touch with everyone I care about.
Whisperfish has <a href="https://gitlab.com/whisperfish/whisperfish/-/wikis/Version-history">quite some history</a>,
and I think it deserves an “intermezzo” post in this series,
not only because I co-maintain this app.
I have Whisperfish open <em>all the time</em>, 24/7, everywhere I go.</p>

<p>I own a <a href="https://eu.switch-bot.com/products/switchbot-mini-robot-vacuum-k10">SwitchBot K10+ robot vacuum</a>.
I chose this vacuum because it supports a local API,
because they <a href="https://eu.switch-bot.com/pages/home-assistant">officially support Home Assistant</a>,
and because it’s nice and compact for my 74m² flat.
Getting it connected is another story, however.
This required a “real” Android device, again,
this time because of Bluetooth:
Jolla’s Android AppSupport doesn’t currently pass through Bluetooth.
Lack of Bluetooth on AppSupport is a major nuisance for users,
but <a href="https://translate.sailfishos.org/projects/appsupport-bridge-bt/">Jolla seems to have it figured out</a>.
After connecting, the SwitchBot app connects on my Sailfish OS device as well.
The SwitchBot is usable on a daily basis (obviously I automated it such that it runs when I’m away from home).
If I want it to clean a specific room,
I need to start the Android phone, because the map doesn’t render correctly on AppSupport,
and this makes the app completely unusable.
It’s really odd, and it’s the only rendering issue I’ve ever seen on AppSupport.
I should file an issue about this…</p>

<p>Other daily apps are the banking apps.
My main bank is Argenta.
I also follow <a href="https://www.bogleheads.org/wiki/Investing_from_Belgium">Bogle’s advice</a>,
for which I have accounts at a few brokers.
All these apps work just fine, no complaints and no issues.
In Belgium, we also generally use Itsme,
an identity provider built by a private company, founded and funded by a banking consortium.
Lately their authentication procedure changed to requiring the scan of a QR code,
which the Xperia 10 IV can’t do, because it misses camera drivers.
Allegedly <a href="https://forum.sailfishos.org/t/belgian-sailfish-os-users/28955/38?u=rubdos">this mostly works on other devices with a camera</a>.</p>

<h1 id="camera">Camera</h1>

<p>Camera support has generally worked on Sailfish OS,
except now for the Xperia 10 IV and V.
Because of that, <a href="https://forum.sailfishos.org/t/fisheye-fish-your-pictures-from-your-sony-camera/19585">I’ve taken to a new hobby</a>;
I’ve taken to photography with a supercompact Sony RX100.
It fits in my pocket, and the photos are fantastic.
I wrote a little app called <a href="https://gitlab.com/rubdos/fisheye/"><img src="https://gitlab.com/rubdos/fisheye/-/raw/a346aa712cec79540333fdf8214cbd07c44901a9/icons/128x128/harbour-fisheye.png" alt="FishEye icon" class="inline-icon" /> FishEye</a> to quickly transfer pictures from the camera to my phone, as to share them via <a href="https://gitlab.com/whisperfish/whisperfish/"><img src="https://gitlab.com/whisperfish/whisperfish/-/raw/7151ac297d05e7761f4f3e8578a9827d5ee8820f/icons/128x128/harbour-whisperfish.png" alt="Whisperfish Icon" class="inline-icon" /> Whisperfish</a>.
Sailfish OS isn’t up-to-speed with modern smartphone photo processing techniques,
as you might expect.
If you want “iPhone quality photos”, you should probably either get an iPhone,
or dive into photography like I now did.
It’s fun, the water’s warm (and not oversaturated blue), join the dark side!</p>

<h1 id="browsers">Browsers</h1>

<p>My main nuisance on a daily basis is the Sailfish OS <img src="/assets/sfos-icons/icon-launcher-browser.png" alt="Sailfish OS Browser icon" class="inline-icon" /> Browser.
Compared to using Android Fennec on AppSupport, the built-in browser feels a lot more snappy.
However, it’s currently built on Gecko ESR 91.
That’s old; 2022 is a long time ago.
It’s not just old as in “websites tell you to update”,
it’s old enough that certain sites don’t even render anymore.
It turns out that <a href="https://www.flypig.co.uk/gecko">developing a browser is really darn difficult</a>,
and requires a lot of work.
Just the ESR 91 port took little over a year.</p>

<p>For things that don’t render (or things that I think require some more sandboxing),
I use Fennec from F-Droid.
It’s annoying, but it works well enough.
I know that people use Firefox or Fennec on AppSupport all the time,
and never use the built-in browser.</p>

<p>Something <em>new</em> popped up some days ago though.
A few days ago, we got to know that <a href="https://forum.sailfishos.org/t/sailfish-community-news-16-april-2026-5-1-translation-round/29116#p-173403-main-interface-16">several Wayland and Lipstick dependencies were bumped and improved</a>,
to support native Qt6 and Gtk applications.
The same person has <a href="https://github.com/n2klb/firefox">an interesting repository on Github called “Firefox”</a>,
and has been committing to it <a href="https://forum.sailfishos.org/t/sailfish-community-news-16-april-2026-5-1-translation-round/29116/6?u=rubdos">with an email address ending in <code class="language-plaintext highlighter-rouge">@jolla.com</code></a>.
If you’re lost in technicalities:
this is extremely good news, and means we could get a more maintainable browser soon!</p>

<h1 id="more-apps">More apps</h1>

<p>The above covered the more “interesting” apps.
Either they were interesting because of how surprisingly <em>well</em> they work,
or to mention their quirks.
There are plenty of other apps though, which I don’t necessarily on a daily basis.
Let’s get them through in two or three sentences.
Not because they’re not cool, but because I’d need at least two more of these posts to decently cover them.
<a href="https://github.com/a-dekker/BarWal"><img src="https://github.com/a-dekker/BarWal/blob/71a8af71c65f775fbdc0783884960a4a8d4d656f/icons/128x128/harbour-barwal.png?raw=true" alt="BarWal Icon" class="inline-icon" /> BarWal</a> is an app for storing <a href="https://mastodon.nu/@DonMasto/116424555248245110"><del>loyalty cards</del></a> any kind of barcodes,
which I use for loyalty cards.
<a href="https://github.com/rinigus/pure-maps"><img src="https://raw.githubusercontent.com/rinigus/pure-maps/acfe9b13d71d0fe79ab3941a7b5db3182a18b6d8/qml/icons/pure-maps.svg" alt="Pure Maps Icon" class="inline-icon" /> Pure Maps</a> is amazing;
it renders a map with pluggable back-end provider
(I use <a href="https://github.com/rinigus/osmscout-server/"><img src="https://github.com/rinigus/osmscout-server/blob/3abf2fe90363f166bc768890528325cb64971b61/gui/icons/128x128/harbour-osmscout-server.png?raw=true" alt="OSM Scout Server Icon" class="inline-icon" /> OSM Scout Server</a> for hybrid offline-online support),
and has a built-in navigation system.
<a href="https://gitlab.com/elBoberido/kuri/"><img src="https://gitlab.com/elBoberido/kuri/-/raw/b78646052925cc599a10a57c9acc1c989b951ee7/icons/128x128/harbour-kuri.png" alt="Kuri Icon" class="inline-icon" /> Kuri</a> is an app to track workouts (or share your hikes with friends and family, because it supports Strava uploads).</p>

<p><img src="/assets/2026-sfos/gallery.png" alt="Gallery" width="23%" />
<img src="/assets/2026-sfos/kuri.png" alt="Kuri" width="23%" />
<img src="/assets/2026-sfos/pure-maps.png" alt="Pure maps" width="23%" />
<img src="/assets/2026-sfos/travel.png" alt="My collection of travel-related apps" width="23%" /></p>

<p>(<img src="/assets/sfos-icons/icon-launcher-gallery.png" alt="Gallery icon" class="inline-icon" /> Gallery,
<img src="https://gitlab.com/elBoberido/kuri/-/raw/b78646052925cc599a10a57c9acc1c989b951ee7/icons/128x128/harbour-kuri.png" alt="Kuri Icon" class="inline-icon" /> Kuri,
<img src="https://raw.githubusercontent.com/rinigus/pure-maps/acfe9b13d71d0fe79ab3941a7b5db3182a18b6d8/qml/icons/pure-maps.svg" alt="Pure Maps Icon" class="inline-icon" /> Pure Maps,
collection of travel apps I use)</p>

<p>Another bunch of “boring” apps are
<img src="/assets/sfos-icons/icon-launcher-phone.png" alt="Phone Icon" class="inline-icon" /> Phone, and
<img src="/assets/sfos-icons/icon-launcher-people.png" alt="People Icon" class="inline-icon" /> People.
Calling people works as you’d expect,
and my contacts sync with Nextcloud.
The <img src="/assets/sfos-icons/icon-launcher-gallery.png" alt="Gallery Icon" class="inline-icon" /> Gallery
is relatively simple, although its Nextcloud integration is now quite neat.</p>

<h1 id="a-story-about-app-stores">A story about app stores</h1>

<p>This article is becoming way too long,
but I believe I conveyed my message by now.
There are many very neat native apps which just work.</p>

<p>One thing which may be confusing to newcomers is the many <em>sources</em> for apps.
Sailfish OS apps are RPM packages.
There are three important sources for Sailfish OS packages and apps:
the Jolla Store (“Harbour”),
OpenRepos (via Storeman),
and Chum.</p>

<p>First is the
<img src="/assets/sfos-icons/icon-launcher-store.png" alt="Jolla Store Icon" class="inline-icon" /> <strong><em>Jolla Store</em></strong>,
sometimes referred to as “Harbour”.
This is Jolla’s official app store, is curated by Jolla,
and also hosts some Android apps.
It is also your main way to install the commercial offering:
the Exchange plugin, the Android AppSupport.
Jolla is quite strict in what apps they allow,
and what those apps are allowed to do on your phone.</p>

<p>The apps on Harbour are high-quality,
but sometimes an app developer requires some more freedom than what Harbour currently allows.
There are two big community repositories that are more lenient.
<strong><em><a href="https://openrepos.net">OpenRepos</a></em></strong> is the oldest,
and also hosts apps for Harmattan, i.e. for the Nokia N9.
The most convenient way to access it,
is through
<a href="https://github.com/storeman-developers/harbour-storeman"><img src="https://github.com/storeman-developers/harbour-storeman/blob/f4824a2e3e2b1a3b56a8776aba02e6ca87ee5ae5/icons/128x128/harbour-storeman.png?raw=true" alt="Storeman Icon" class="inline-icon" /> Storeman</a>.</p>

<p>The newer, preferred source for community apps is <strong><em><a href="https://sailfishos-chum.github.io/">Chum</a></em></strong>.
These apps are centrally built on the <a href="https://build.sailfishos.org/">Sailfish OS Open Build Service</a>,
which gives some better form of quality control.
The <a href="https://github.com/sailfishos-chum/sailfishos-chum-gui/"><img src="https://raw.githubusercontent.com/sailfishos-chum/sailfishos-chum-gui/dea6f72be4117301ecb97652157ca3f475329e82/icons/sailfishos-chum-gui.svg" alt="Chum GUI Icon" class="inline-icon" /> Chum GUI</a>
app is the most convenient way to access these applications.</p>

<p>Generally, you should prefer <em>Harbour, then Chum, then OpenRepos</em>.</p>

<p>Android users are generally used to the Google Play Store.
Since AppSupport is not a Google product, and hopefully will never be a Google product,
it’s generally not recommended to install the Google Play Store (or anything Google Play).
As an alternative for your needs of proprietary Android applications, you should consider <a href="https://gitlab.com/AuroraOSS/AuroraStore">Aurora</a>.
It’s a free, GPLv3-licensed client for the Google Play Store.
You can download it from Harbour.
Some apps will expect Google Play to be present.
You might be interested in <a href="https://forum.sailfishos.org/t/installing-microg-on-sailfish-os/14375">microG</a> as an open source and controllable alternative.</p>

<p>Of course, <a href="https://f-droid.org/">F-Droid</a> needs mentioning as well.
F-Droid is a free store, which serves only free apps for Android.
F-Droid is fantastic, and your AppSupport experience would not be complete without it.</p>

<hr />

<p>At this point, this article <em>has</em> become way too long.
The plan is to end the series with a final post to tie some loose ends.
Did I miss an app?
<a href="https://mastodon.social/@rubdos/116409163779320729">Get in touch on Mastodon</a> and I’ll be happy to comment or cover in a follow-up!
Definitely have a scroll on <a href="https://mastodon.social/@rubdos/116421451633655625">the reaction on Mastodon</a>,
some people recommend podQast over gPodder, and FoilAuth over SailOTP.</p>

<p>In the next episode of this series, I’ll do a Whisperfish intermezzo: the app that I co-maintain, and share its story.
Talk to you soon.</p>

<h2 id="post-scriptum"><em>post scriptum</em></h2>

<p>Meanwhile,
I have switched from <img src="https://github.com/gpodder/gpodder-sailfish/blob/02cfe94dd5bba8d90009705f32e21f01b5f86b74/icons/128x128/apps/harbour-org.gpodder.sailfish.png?raw=true" alt="gPodder Sailfish icon" class="inline-icon" /> gPodder to <a href="https://gitlab.com/cy8aer/podqast/"><img src="https://gitlab.com/cy8aer/podqast/-/raw/f93a441c3b4c805eb62f01b2c8f1e3bb937af37d/icons/128x128/harbour-podqast.png" alt="podQast icon" class="inline-icon" /> podQast</a> for podcasts,
at <a href="https://mastodon.social/@ekari@mementomori.social/116424235557347319">the suggestion of several people on Mastodon</a>.
At the time of writing, the version on the Jolla Store does not support MPRIS, but the one in OpenRepos does.
I also swapped <a href="https://github.com/equeim/unplayer/"><img src="https://github.com/equeim/unplayer/blob/798fbe4cbf776470b89b3de5677ab17b349c66f8/icons/hicolor/128x128/apps/harbour-unplayer.png?raw=true" alt="Unplayer icon" class="inline-icon" /> Unplayer</a> for the built-in <img src="/assets/sfos-icons/icon-launcher-mediaplayer.png" alt="Jolla Media Player Icon" class="inline-icon" /> Media app.
I had some trouble with it indexing unrelated files, but some <code class="language-plaintext highlighter-rouge">touch .nomedia</code> later it’s actually pretty neat.</p>]]></content><author><name>Ruben De Smet</name></author><category term="sailfishos" /><category term="mobile" /><category term="privacy" /><category term="apps" /><category term="f-droid" /><category term="google" /><summary type="html"><![CDATA[I have been daily driving Sailfish OS since 2014, and that has been made possible by the many apps I rely on. In the first post of this series, I elaborated on where Sailfish OS comes from, and on how I got to using it. In this post, I’ll cover what apps I value most, and the quirks that come with them.]]></summary></entry><entry><title type="html">My Sailfish OS Journey</title><link href="https://www.rubdos.be/2026/04/15/my-sailfish-os-journey.html" rel="alternate" type="text/html" title="My Sailfish OS Journey" /><published>2026-04-15T11:36:00+00:00</published><updated>2026-04-15T11:36:00+00:00</updated><id>https://www.rubdos.be/2026/04/15/my-sailfish-os-journey</id><content type="html" xml:base="https://www.rubdos.be/2026/04/15/my-sailfish-os-journey.html"><![CDATA[<p>I have been daily driving Sailfish OS since 2014.
In this series of blog posts, I would like to jot down the why and the how.
This first post will be about some history and context.
The second in this series is <a href="/2026/04/17/my-sailfish-os-journey-apps.html">about the apps that I use the most</a>.
After that, I still want to write about the tiny hacks that I have on my device,
and I plan a final post about some loose ends that are worth mentioning.</p>

<h2 id="sailfish-os-the-most-usable-linux-in-your-pocket">Sailfish OS: the most usable Linux in your pocket</h2>

<p>Somewhere around 2010, I was happily using a Nokia clamshell phone.
It did what it had to, and it had worked for years.
At that time, it was apparent that the world was moving toward smartphones:
mobile devices with internet connection, a browser, a camera, a fancy screen,
and way more compute power than those old-fashioned GSM-era devices.
And apparently they could be used as a phone as well.</p>

<p>I was quite repelled by both the iPhones and Android phones at the time.
Both were, and still are built by monopolists.
Apple’s offering is marketed with privacy, but lacks the freedom to tinker:
the whole ecosystem is locked down, and not very suited for the tinkerer and hobbyist that I am.
Google’s offering was a more open ecosystem:
the base operating system was open source, mostly free, and Linux based.
However, something felt <em>off</em>.
Whereas the Android operating system might be free and open source,
its spirit is not.
Google dictates the direction of the system,
and <a href="https://keepandroidopen.org/nl/">their grip on the ecosystem keeps on tightening</a>.
Paradoxically, the free and open source Android seemed to be more privacy infringing than its proprietary rival.</p>

<p>At some point I learned about the <a href="https://en.wikipedia.org/wiki/Nokia_N9">Nokia N9</a>.
Contrary to iOS, this device was mostly free and open source.
And contrary to Android, it was built around existing, well-known software stacks.
The <a href="https://en.wikipedia.org/wiki/MeeGo">MeeGo</a> operating system (technically called Harmattan) was built around Qt and QML,
and the base Linux was an actual GNU/Linux.
The thing even shipped a terminal emulator!</p>

<p><a href="https://en.wikipedia.org/wiki/Nokia_N9#/media/File:Nokia_N9.jpg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Nokia_N9.jpg/960px-Nokia_N9.jpg" alt="By Animist" width="47%" title="By Animist" /></a> 
<a href="https://en.wikipedia.org/wiki/Jolla_(smartphone)#/media/File:Jolla_phone_vector.svg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Jolla_phone_vector.svg/960px-Jolla_phone_vector.svg.png" alt="By Rafael Fernandez" width="40%" title="By Rafael Fernandez" /></a></p>

<p>(left: <em>Nokia N9</em>, right: <em>Jolla</em>)</p>

<p>I got my hands on what was probably the very last device on sale in Belgium,
and it is still my favorite phone to date.
It was opinionated, featureful, and quick despite the rather limiting 1GHz single core processor.
Sadly, it became obsolete quickly. Nokia sold most of their smartphone business to Microsoft,
and Microsoft did what Microsoft does best: drop what is interesting, and then try and fail to make something nice out of the remaining pieces.</p>

<h2 id="jolla-and-sailfish-os---from-2014-to-2026">Jolla and Sailfish OS - from 2014 to 2026</h2>

<p>Some of the parts did not end up in Redmond hands.
Instead, a few brave souls at Nokia ran off and founded Jolla.
I was still happy with my N9 when they released the Jolla:
the spiritual successor to the Nokia N9 hit the market.
I got my hands on it some months after it started shipping,
especially when it became clear the N9 would not receive any more updates.
The Jolla itself got very mixed reviews.
Hardware-wise, it was a significant downgrade in many aspects.
The screen was a rather dim LCD (being used to the N9’s utterly fantastic OLED),
the more advanced and featureful software meant that the dual-core with 1GB RAM was quite limiting,
and the camera was akin to a potato compared to the Carl Zeiss glass in the N9.</p>

<p>Still, it was an attractive device.
It was backed by a company, and developed with <a href="https://forum.sailfishos.org">a community</a>.
The operating system, Sailfish OS, was a true GNU/Linux system,
which I usually explain as “OpenSUSE with a mobile-first Wayland shell”.
The thing works out-of-the-box.
You can browse the web, read and write emails, take pictures, look at videos,
open a terminal and use ssh, and text and make phone calls.
Their commercial offering was mainly “Alien Dalvik”, now Android App Support,
which is an LXC container for your Android apps.
Since 2014, Jolla has been through many rough waters.
I’m sure you’ll find plenty of articles covering those.
After the Jolla, their focus was on Sony Xperia devices (“Sailfish X”).
These smartphones had the “open device program”,
which made them relatively easier for Jolla to port to Sailfish OS.
My personal Sailfish OS journey after the Jolla phone was:
Jolla, community-ported Motorola Z Play, Xperia 10, Xperia 10 IV (with a lot of issues).
Until recently, the Xperia series was the best way to enjoy Sailfish OS.
Jolla announced the Jolla Phone (sometimes shortened to “the J2” by the community),
<a href="https://commerce.jolla.com/products/jolla-phone-preorder">a device with <em>actually really decent hardware specs</em></a> (if you decide to order one, feel free to add <code class="language-plaintext highlighter-rouge">Jolla-Phone-10K-0976f49b15f4</code> to the discount field <a href="https://forum.sailfishos.org/t/jolla-phone-update-referral-program/27123">as my referral code</a>).
Finally, we will have an official high-end Jolla device.
I am very much looking forward to this.
I may or may not have held one in my hands during the <a href="https://forum.sailfishos.org/t/next-meeting-for-french-speaking-sailfish-os-users-21-march-2026-in-lyon/27493">French speaking community meeting in Lyon</a>,
and my opinion has only improved.</p>

<p><img src="/assets/2026-lyon/DSC05294_modified.JPG" alt="My collection of Sailfish OS devices during the 2026 meetup in Lyon" title="My collection of phones" /></p>

<p>(left to right: <em>Xperia 10 IV, Jolla C2, Xperia 10, Jolla, Nokia N9</em>)</p>

<h2 id="sailfish-os-as-a-community">Sailfish OS as a community</h2>

<p>Between 2014 and 2019, I was a silent Sailfish OS user,
enjoying Linux in my pocket.
One of the apps I started to use the most was <em>Whisperfish</em>,
a <a href="https://signal.org/">Signal</a> client for Sailfish OS.
Whisperfish was developed and maintained by Andrew E. Bruno in Go,
but <a href="https://github.com/aebruno/whisperfish/issues/130">in 2019 he decided to call it quits</a>.
I took the initiative to completely overhaul Whisperfish, and write it against the upstream Signal libraries in Rust.
Since then, <a href="https://openrepos.net/content/rubdos/whisperfish">Whisperfish</a> has become one of the most downloaded apps,
and <a href="https://forum.sailfishos.org/t/whisperfish-the-unofficial-sailfishos-signal-client/3337/1676">the second most active topic on the Sailfish OS forum</a>.</p>

<p><img src="https://forum.sailfishos.org/uploads/db4219/original/2X/d/d4cda42f5bdd50e031be1dc143d240792c7e4de7.jpeg" alt="Picture of the community dinner 2026" /></p>

<p>(Community dinner 2026)</p>

<p>This is to say: Whisperfish got me from being a silent user to an active community member.
Every year, I look forward to engaging on FOSDEM,
and to attend <a href="https://forum.sailfishos.org/t/fosdem-2026-sailfish-os-meetup-and-bof/26813">the community dinner</a>.
Sailfish OS is not just an operating system.
It’s a group of friends with set of shared values:
the freedom to use your phone as you please,
a design language that feels consistent across the whole operating system,
and a chat with the CTO and the CEO about their preferred beer of the night,
somewhere during each winter.</p>

<h2 id="sailfish-os-as-a-daily-driver">Sailfish OS as a daily driver</h2>

<p>In my next two posts, I will dive deeper in the apps that I use,
the oddly specific tweaks that make my device really mine,
and generally how I have set up my device.
If you’re curious about Sailfish OS or my journey,
do send me your questions on <a href="https://mastodon.social/@rubdos/116409163779320729">Mastodon</a>!</p>

<p>This is what my phone, the Xperia 10 IV, usually looks like.
Yes, I am writing this when it’s 19°C outside.</p>

<p><img src="/assets/events-view.jpg" alt="Sailfish OS events view" width="47%" />
<img src="/assets/Screenshot_20260415_151059_001.png" alt="Sailfish OS main view" width="47%" /></p>

<p>(left: <em>events view</em>, right: <em>application drawer and application view</em>)</p>]]></content><author><name>Ruben De Smet</name></author><category term="sailfishos" /><category term="mobile" /><category term="privacy" /><category term="nokia" /><summary type="html"><![CDATA[I have been daily driving Sailfish OS since 2014. In this series of blog posts, I would like to jot down the why and the how. This first post will be about some history and context. The second in this series is about the apps that I use the most. After that, I still want to write about the tiny hacks that I have on my device, and I plan a final post about some loose ends that are worth mentioning.]]></summary></entry><entry><title type="html">VRT verspreidt desinformatie over communicatieapps</title><link href="https://www.rubdos.be/2025/03/26/vrt-verspreidt-desinformatie-over-signal.html" rel="alternate" type="text/html" title="VRT verspreidt desinformatie over communicatieapps" /><published>2025-03-26T13:18:00+00:00</published><updated>2025-03-26T13:18:00+00:00</updated><id>https://www.rubdos.be/2025/03/26/vrt-verspreidt-desinformatie-over-signal</id><content type="html" xml:base="https://www.rubdos.be/2025/03/26/vrt-verspreidt-desinformatie-over-signal.html"><![CDATA[<p>Beste VRT NWS,
beste Kenneth Lasoen,</p>

<p><em>Betreft: “Staatsgeheimen op Signal: waarom gebruiken toppolitici in VS de berichtenapp? En hoe (on)veilig is dat?”, VRT NWS, 25 maart 2025.</em></p>

<p>In uw interview van 25 maart 2025, getiteld <a href="https://www.vrt.be/vrtnws/nl/2025/03/25/signal-berichten-geheime-besprekingen-amerika/">“Staatsgeheimen op Signal: waarom gebruiken toppolitici in VS de berichtenapp? En hoe (on)veilig is dat?”</a>, verspreidt u gevaarlijke desinformatie over communicatieapps.
Signal is, zoals u <a href="https://www.vrt.be/vrtmax/a-z/terzake/2025/terzake-d20250320/">zelf nog rapporteerde in Terzake op 20 maart</a> de zogenaamde “gold standard” in veilige en private communicatie.
Dit is niet enkel de repliek van Signal zelf; dit is ook de conclusie van <a href="https://x.com/matthew_d_green/status/1904464484162273316">zowat alle onafhankelijke experts</a> en <a href="https://soatok.blog/2025/02/18/reviewing-the-cryptography-used-by-signal/">onderzoekers</a> wereldwijd.</p>

<p>Uw interview kwam dan ook als een totale verrassing.
Het is — uiteraard — verkeerd om een civiel kanaal zoals Signal te gebruiken voor staatsgeheimen,
vanwege de redenen genoemd in het interview.
Maar daarenboven argumenteert Kenneth Lasoen dat Signal “te prenetreren” valt en die “encryptie te kraken” valt door inlichtingendiensten.</p>

<blockquote>
  <p>“Natuurlijk zijn er wel inlichtingendiensten die over de capaciteiten beschikken om die app toch te penetreren en die encryptie te kraken” – Kenneth Lasoen</p>
</blockquote>

<p>Voor zulke brede claims is <em>op zijn minst</em> duiding nodig.
Er zijn geen publieke bronnen die deze claims ondersteunen.
In het beste geval verwijst professor Lasoen naar de enkele gevallen van gelekte Signalgesprekken,
waarbij de toestellen van de gebruikers zelf gecompromitteerd waren.</p>

<p>Daarna vertelt professor Lasoen dat Threema een beter alternatief is,
omdat het gebruikt wordt door veiligheidsdiensten, alsook veiligheidsdiensten in ons land.
Dat is op zich erg verontrustend, gegeven <a href="https://soatok.blog/2021/11/05/threema-three-strikes-youre-out/">het historisch slecht track record</a> van deze Zwitserse app.
Kijkt u gerust ook naar de presentatie van Kenny Paterson, professor cryptografie aan ETH Zürich, over de <a href="https://youtu.be/sthXs4zJ5XU?t=1892">veiligheid van Threema</a>.
Threema’s voornaamste voordeel <em>voor veiligheidsdiensten</em> is de mogelijkheid om de rol van gespreksdeelnemers te visualiseren:
Threema geeft weer of een deelnemer al dan niet een bekend contact is, of deel is van je eigen organisatie.</p>

<blockquote>
  <p>“De servers staan op een hoog beveiligde locatie in Zwitserland en vallen dus ook onder het Zwitserse recht. Daardoor is het bedrijf ook niet zomaar verplicht om die communicatie over te maken.” – Kenneth Lasoen</p>
</blockquote>

<p>Signal heeft <a href="https://signal.org/bigbrother/">een lijst van alle informatie die zij ooit hebben overgemaakt aan overheden</a>.
Of die alles bevat, of ze eventueel een subpoena hebben gekregen van een geheime rechtbank, is onbekend.
Wat wel bekend is, is dat Signal enkel toegang heeft tot volgende informatie: laatste datum van registratie, laatste contactmoment van de gebruiker.
Zwitserse servers kunnen een extra gevoel van veiligheid geven, maar het is niet omdat de servers in Zwitserland staan dat de communicatie veiliger is.</p>

<blockquote>
  <p>“Daarnaast kiest Threema ervoor om communicatiesleutels om de zoveel tijd veranderen. Wanneer een hacker de sleutel van jouw communicatie via Threema dus in handen zou krijgen, kan die jouw berichtgeving uit het verleden niet inzien.” – Kenneth Lasoen</p>
</blockquote>

<p>Dit is opnieuw, in het allerbeste geval, een misleidende uitspraak.
Het principe van sleutelrotatie is een standaardpraktijk in de cryptografie,
die populair gemaakt werd <em>door Signal</em>.
Daarnaast heeft Signal altijd zogenaamde “post compromise” security geboden, wat Threema pas recent heeft ingevoerd.
Dit is opmerkelijk, want zowel de specificatie als de implementatie van Signal zijn openlijk beschikbaar, zodat Threema dit kosteloos had kunnen overnemen.</p>

<blockquote>
  <p>“De kwantumcomputer zit eraan te komen. Daar is ook Threema niet tegen opgewassen” – Kenneth Lasoen</p>
</blockquote>

<p>De meningen rond toekomstige (of huidige) kwantumcomputers zijn verdeeld.
De meeste onderzoekers zijn wel van het “better safe than sorry” principe,
en hebben daarom algoritmes ontwikkeld die resistent zouden zijn tegen kwantumcomputers.
Threema is inderdaad niet zogenaamd “post-quantum secure”,
maar <a href="https://signal.org/blog/pqxdh/">Signal is dat sinds bijna twee jaar wel</a>,
net <a href="https://security.apple.com/blog/imessage-pq3/">zoals Apple’s iMessage</a>.</p>

<blockquote>
  <p>“Zo’n computer maakt honderden miljoenen keren sneller berekeningen dan de computers van vandaag. Het zorgwekkende is dat een kwantumcomputer daarom in staat is de meest complexe en geavanceerde codes in een fractie van een seconde te kraken.”</p>
</blockquote>

<p>Dit is een misvatting.
Quantumcomputers zijn niet sneller dan “gewone” computers.
Quantumcomputers hebben een aantal specifieke mogelijkheden die hen sneller maken in bepaalde, <em>erg specifieke</em> berekeningen,
waaronder <em>vermoedelijk</em> het breken van het RSA en het ECC algoritme.
Dit is exact waar de meningen verdeeld zijn:
sommige onderzoekers geloven dat het fysiek bouwen van die specifieke quantumcomputer fysisch niet mogelijk zal zijn.
De meeste huidige quantumcomputers die gebouwd worden,
zijn niet eens gebouwd met die specifieke doelen in het achterhoofd.</p>

<p>Door deze desinformatie te verspreiden, overtuigt u mensen om over te stappen op een minder veilig alternatief.
Dat brengt deze mensen potentieel in gevaar.
Signal wordt gebruikt door klokkenluiders en journalisten,
die in oorlogsgebieden en in dictatoriale regimes hun leven riskeren om de waarheid te kunnen rapporteren.
Uw repliek is hierdoor <em>levensgevaarlijk</em>.</p>]]></content><author><name>Ruben De Smet</name></author><summary type="html"><![CDATA[Beste VRT NWS, beste Kenneth Lasoen,]]></summary></entry><entry><title type="html">Hacker report: Sailathon 2024, Prague</title><link href="https://www.rubdos.be/2024/09/30/hacker-report-sailathon-2024-prague.html" rel="alternate" type="text/html" title="Hacker report: Sailathon 2024, Prague" /><published>2024-09-30T09:06:00+00:00</published><updated>2024-09-30T09:06:00+00:00</updated><id>https://www.rubdos.be/2024/09/30/hacker-report-sailathon-2024-prague</id><content type="html" xml:base="https://www.rubdos.be/2024/09/30/hacker-report-sailathon-2024-prague.html"><![CDATA[<p>Today is the final day of the Sailathon, the Sailfish OS hackathon in Prague.
At the peak this weekend, we were about 20 hackers from all around Europe,
working on various Sailfish OS related projects.
By today, Monday, most of the hackers have already left; the five remaining are still hacking strong!</p>

<h1 id="jolla-c2-discussions">Jolla C2 discussions</h1>

<p>The star of the show was probably the Jolla C2, a new device that Jolla has been working on.
Sailors Raine and Matti brought a prototype with them.
<a href="https://blog.mlich.cz/2024/09/sailathon-2024-sailfish-os-hackathon/">Jozef blogged about it and published some pictures</a>.
As expected, I was a bit sad with the screen on the device, but it seemed like a great device in any other regard.
Raine was interested in hearing our opinions on the home screen rotation feature, and we had a good discussion about it over a beer or two (or three or four, I lost count).
Looking forward to playing with it more when I get mine the next weeks!</p>

<h1 id="taak-and-rust-apps-in-obs">Taak, and Rust apps in OBS</h1>

<p><a href="https://gitlab.com/rubdos/taak/">Taak</a> is a simple frontend for TaskWarrior, written in Rust.
I wrote it with two intentions: to make the simplest, cleanest Rust-app for Sailfish OS that I could think of,
and to have a simple frontend for TaskWarrior on my phone.
It also serves as a test ground <a href="https://gitlab.com/whisperfish/sailo-rs">for my Rust apps</a>.</p>

<p><a href="https://forum.sailfishos.org/t/september-27-30-sailathon-24-in-prague/19912/125?u=rubdos">As @poetaster wrote on the forum</a>:</p>
<blockquote>
  <p>I wanted to add that those two [@xmlich02 and @rubdos] propelled @pherjung to get a nearly complete rust env running and integrate with obs. It’s now up to us to help @pherjung complete the process and document how you set up rust dependencies (vendor dir ahoi!) to compile on obs … or @nephros will simply provide a cheatsheet and we’re all set 🙂</p>
</blockquote>

<p>@pherjung and @xmlich02 were basically working on getting Rust apps – rubdos-style – to build in OBS, and as such Chum.
If they succeed to build Taak in OBS, Whisperfish will soon follow!</p>

<h1 id="progress-on-whisperfish">Progress on Whisperfish</h1>

<p>Matti and I have been working on <a href="https://gitlab.com/whisperfish/whisperfish/">Whisperfish</a>, a Signal client for Sailfish OS.
My personal goal for the weekend was to get voice calls working.
I’m still compiling and testing as I’m writing this post, but I’m confident that we’ll have something to show soon!</p>

<p>Matti guided <a href="https://forum.sailfishos.org/u/hoxifi/summary">hoxifi</a> to his <a href="https://gitlab.com/whisperfish/whisperfish/-/merge_requests?scope=all&amp;state=all&amp;author_username=hoxifi">first Whisperfish patches</a>.
The <a href="https://gitlab.com/whisperfish/whisperfish/-/merge_requests/632">first patch</a> is a much needed QtCreator project file,
to get new contributors started with Whisperfish development in the more familiar <a href="https://docs.sailfishos.org/Develop/Apps/Your_First_App/">Sailfish IDE</a>.</p>

<p>Meanwhile, Matti and I made quite some progress.
Linked devices was broken (again, again),
because of some missing exchange of key material.
Matti <a href="https://gitlab.com/whisperfish/whisperfish/-/merge_requests/610">implemented the remaining bits</a> to fix that issue.</p>

<p>With some help of poetaster, we got <a href="https://gitlab.com/whisperfish/whisperfish/-/merge_requests/615">voice note volume normalization</a> mostly done.
Turns out it’s difficult to test, because the Xperia 10 IV has a <a href="https://forum.sailfishos.org/t/feedback-on-xperia-10-iv/20113/15?u=rubdos">broken audio recorder</a> at the moment.</p>

<p>The bulk of my own energy went into <a href="https://gitlab.com/whisperfish/whisperfish/-/merge_requests/595/">voice call support</a> (and soon™ video call support).
As <a href="2024-09-08-building-ringrtc-for-whisperfish.md">reported earlier</a>, I had managed to get RingRTC and WebRTC to link in Whisperfish.
The remainder is “easy”: link up the RingRTC API to the Whisperfish storage, networking, GUI, and multimedia processing frameworks.
The past few days were spent integrating the ringing behaviour.
Raine Mäkeläinen helped a lot on Saturday: he provided me with a demo application for the necessary MCE and ring tone integrations,
which I could easily copy-paste into the Whisperfish QML code.
I’d also like to thank Sebix and Pherjung to call me several times during the day, so I could test the ringing behaviour.
At the time of writing (nephros just went home, three of us <a href="https://europeancoffeetrip.com/cafe/spalenykafe-prague/">left in the Spálený Kafe coffee shop</a>),
I’m figuring out the <a href="https://github.com/whisperfish/libsignal-service-rs/pull/327">networking</a> and multimedia.</p>

<p><img src="/assets/img/matti-voice-call.png" alt="Voice call UI element" /></p>

<h1 id="closing-note">Closing note</h1>

<p>I witnessed a lot of progress around me on several other apps (Tooter, Amazfish come to mind).
I hope the other community members will blog about their progress too;
this post would become way too long to summarize all the nice things that have been done.</p>

<p>Hereafter are some pictures to set the stage.
It was a rather pleasant experience meeting all those people,
and I hope to see this group again on the next Sailathon.</p>

<p><img src="/assets/2024-prague/DSC01930.JPG" alt="Me in his natural habitat: a coffee shop" />
<img src="/assets/2024-prague/DSC01986.JPG" alt="Xperia's on display in a Sony shop" />
<img src="/assets/2024-prague/DSC01989.JPG" alt="Early arrivals sharing dinner and beer" />
<img src="/assets/2024-prague/DSC02001.JPG" alt="Obligatory Tux selfie" />
<img src="/assets/2024-prague/DSC02004.JPG" alt="Half the group for lunch" />
<img src="/assets/2024-prague/DSC02074.JPG" alt="A closeby church by night" /></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Today is the final day of the Sailathon, the Sailfish OS hackathon in Prague. At the peak this weekend, we were about 20 hackers from all around Europe, working on various Sailfish OS related projects. By today, Monday, most of the hackers have already left; the five remaining are still hacking strong!]]></summary></entry><entry><title type="html">Building RingRTC and webrtc for Whisperfish</title><link href="https://www.rubdos.be/2024/09/08/building-ringrtc-for-whisperfish.html" rel="alternate" type="text/html" title="Building RingRTC and webrtc for Whisperfish" /><published>2024-09-08T13:05:00+00:00</published><updated>2024-09-08T13:05:00+00:00</updated><id>https://www.rubdos.be/2024/09/08/building-ringrtc-for-whisperfish</id><content type="html" xml:base="https://www.rubdos.be/2024/09/08/building-ringrtc-for-whisperfish.html"><![CDATA[<blockquote>
  <p><strong>NOTE Sept 2025</strong>: Whisperfish does <a href="https://gitlab.com/whisperfish/whisperfish/-/milestones/5"><em>not have support for calling</em></a>, yet.
To include support for calling, we need a lot more work than just compiling the RingRTC library.
This blog post documents the process of building and linking the RingRTC system into Whisperfish,
but some users have interpreted this as to imply voice and video calling support.
This is not the case. Currently, Whisperfish correctly decodes the calling state, and is able to
display a “missed call” notification, thanks to the below work.</p>
</blockquote>

<p>This post serves as documentation for my future self and others,
and might be useful for people apart from Whisperfish devs.
<a href="https://github.com/signalapp/ringrtc">RingRTC</a> is the library that Signal uses for its voice and video calls.
It’s a library containing a lot of Rust code specific to Signal’s needs,
see e.g. https://signal.org/blog/how-to-build-encrypted-group-calls/.
It wraps WebRTC, the Chromium-library that’s used for voice and video calls in browsers.
Specifically, it wraps <a href="https://github.com/signalapp/webrtc">a <em>fork</em> of WebRTC</a> that contains additional security features,
and some other Signal-specific changes.</p>

<p>Whisperfish is quite special in its use of RingRTC.
In Signal Android, RingRTC can be loaded as a JNI library, separated from other C libraries.
Whisperfish loads RingRTC as a Rust library, and it’s built as part of the Whisperfish build process.
The WebRTC library, however, ships its own set of dependencies, by default statically linked into the library.
This conflicts with our own shipping of OpenSSL 3 (as a dep for sqlcipher).</p>

<p>Building WebRTC without boringssl built-in is possible, but it’s not straightforward,
especially since the necessary patches are not yet present in Signal’s fork of WebRTC.
I have built WebRTC specifically for use in Whisperfish, and the resulting static libraries are available at
https://nas.rubdos.be/~rsmet/webrtc/ .
This post documents how I did that.</p>

<h2 id="cherry-picks">Cherry picks</h2>

<p>Specifically this commit was needed to build WebRTC with BoringSSL as a dynamic system library:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">459d6b1d9b - build: add options to configure libsrtp for boringssl or other libraries (9 days ago) &lt;Philipp Hancke&gt;</code>
This required a bit of merging to get it in.
I also toyed with versions of dependencies to get things to link, but in the end that didn’t seem to matter much.
They are in the <code class="language-plaintext highlighter-rouge">no-ssl</code> branch of my fork of WebRTC: https://github.com/whisperfish/webrtc/tree/no-ssl</li>
</ul>

<h2 id="downloading-webrtc">Downloading WebRTC</h2>

<p>One would hope that building WebRTC is as simple as <code class="language-plaintext highlighter-rouge">git clone</code> and <code class="language-plaintext highlighter-rouge">ninja build</code>,
but it’s not.
Google has a whole repository of shady-looking git wrappers and scripts to build WebRTC.
This is mostly because WebRTC is a huge project with a lot of dependencies.
Find the instructions at <code class="language-plaintext highlighter-rouge">https://webrtc.github.io/webrtc-org/native-code/development/</code>.
Crucially, you need to alter the <code class="language-plaintext highlighter-rouge">.gclient</code> file after checking out the repo,
to point to either Signal’s fork or now my fork:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">solutions</span><span class="w"> </span><span class="err">=</span><span class="w"> </span><span class="p">[</span><span class="w">
  </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"src"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://github.com/signalapp/webrtc"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"deps_file"</span><span class="p">:</span><span class="w"> </span><span class="s2">"DEPS"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"managed"</span><span class="p">:</span><span class="w"> </span><span class="err">False</span><span class="p">,</span><span class="w">
    </span><span class="nl">"custom_deps"</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span><span class="w">
  </span><span class="p">},</span><span class="w">
</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>

<p>or</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">solutions</span><span class="w"> </span><span class="err">=</span><span class="w"> </span><span class="p">[</span><span class="w">
  </span><span class="p">{</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"src"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://github.com/whisperfish/webrtc"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"deps_file"</span><span class="p">:</span><span class="w"> </span><span class="s2">"DEPS"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"managed"</span><span class="p">:</span><span class="w"> </span><span class="err">False</span><span class="p">,</span><span class="w">
    </span><span class="nl">"custom_deps"</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span><span class="w">
  </span><span class="p">},</span><span class="w">
</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>

<p>I am currently not sure how to tell <code class="language-plaintext highlighter-rouge">gclient</code> to use the <code class="language-plaintext highlighter-rouge">no-ssl</code> branch.
I created the <code class="language-plaintext highlighter-rouge">no-ssl</code> branch, and continued from there.
I think you can manually check out the branch, and then run <code class="language-plaintext highlighter-rouge">gclient sync</code> to get the correct dependencies on top.</p>

<h2 id="building">Building</h2>

<p>In the end, the following script yields four <code class="language-plaintext highlighter-rouge">libwebrtc.a</code> files:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash -ex</span>

<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="k">${</span><span class="nv">PWD</span><span class="k">}</span>/depot_tools:<span class="nv">$PATH</span>

<span class="nb">export </span><span class="nv">WEBRTC_VERSION</span><span class="o">=</span>6478k
<span class="nb">export </span><span class="nv">WEBRTC_REVISION</span><span class="o">=</span><span class="s2">"branch-heads/</span><span class="k">${</span><span class="nv">WEBRTC_VERSION</span><span class="k">}</span><span class="s2">"</span>

<span class="nb">pushd </span>src

<span class="nv">NO_SSL</span><span class="o">=</span><span class="s2">"rtc_build_ssl=false libsrtp_build_boringssl=false no_build_ssl=true"</span>

<span class="k">for </span><span class="nb">arch </span><span class="k">in </span>arm arm64 x86 x64<span class="p">;</span> <span class="k">do
    </span>gn gen out/<span class="nv">$arch</span> <span class="nt">--args</span><span class="o">=</span><span class="s2">"is_debug=false target_cpu=</span><span class="se">\"</span><span class="nv">$arch</span><span class="se">\"</span><span class="s2"> rtc_build_examples=false rtc_build_tools=false rtc_use_x11=false rtc_enable_sctp=false rtc_libvpx_build_vp9=true rtc_include_ilbc=false rtc_disable_metrics=true rtc_disable_trace_events=true rtc_include_tests=false rtc_enable_protobuf=false symbol_level=1 </span><span class="nv">$NO_SSL</span><span class="s2">"</span>

    ninja <span class="nt">-C</span> out/<span class="nv">$arch</span>
<span class="k">done

</span><span class="nb">popd</span>
</code></pre></div></div>

<p>Most of the build flags come from Signal’s build script,
and I added the ssl-related flags.</p>

<p>The resulting files are hosted on my home server, and include a SHA384 hash that is used in the Whisperfish CI build to verify the download.</p>

<p>The compiler that is shipped used in the ninja cross-build system is rather recent,
but luckily the new SailfishOS 4.6 SDK is recent enough to handle the artifacts.
The 4.5 SDK is not recent enough.</p>

<h3 id="building-against-openssl3">Building against OpenSSL3</h3>

<p>The above script builds WebRTC against the default OpenSSL 1.1.1 (since SailfishOS ships that).
Since most modern Linux systems ship OpenSSL 3.x,
we also need artifacts that are built against OpenSSL 3.x.</p>

<p>You can build this by downloading the OpenSSL 3.2.2 tarball, running <code class="language-plaintext highlighter-rouge">./configure</code>,
and then running the adapted script:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash -ex</span>

<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="k">${</span><span class="nv">PWD</span><span class="k">}</span>/depot_tools:<span class="nv">$PATH</span>

<span class="nb">export </span><span class="nv">WEBRTC_VERSION</span><span class="o">=</span>6478k
<span class="nb">export </span><span class="nv">WEBRTC_REVISION</span><span class="o">=</span><span class="s2">"branch-heads/</span><span class="k">${</span><span class="nv">WEBRTC_VERSION</span><span class="k">}</span><span class="s2">"</span>

<span class="nv">SSL_INCLUDE</span><span class="o">=</span><span class="s2">"rtc_ssl_root=</span><span class="se">\"</span><span class="k">${</span><span class="nv">PWD</span><span class="k">}</span><span class="s2">/openssl-3.2.2/include</span><span class="se">\"</span><span class="s2"> libsrtp_ssl_root=</span><span class="se">\"</span><span class="k">${</span><span class="nv">PWD</span><span class="k">}</span><span class="s2">/openssl-3.2.2/include</span><span class="se">\"</span><span class="s2">"</span>

<span class="nb">pushd </span>src

<span class="nv">NO_SSL</span><span class="o">=</span><span class="s2">"rtc_build_ssl=false libsrtp_build_boringssl=false no_build_ssl=true"</span>

<span class="k">for </span><span class="nb">arch </span><span class="k">in </span>arm arm64 x86 x64<span class="p">;</span> <span class="k">do
    </span>gn gen out/<span class="nv">$arch</span> <span class="nt">--args</span><span class="o">=</span><span class="s2">"is_debug=false target_cpu=</span><span class="se">\"</span><span class="nv">$arch</span><span class="se">\"</span><span class="s2"> rtc_build_examples=false rtc_build_tools=false rtc_use_x11=false rtc_enable_sctp=false rtc_libvpx_build_vp9=true rtc_include_ilbc=false rtc_disable_metrics=true rtc_disable_trace_events=true rtc_include_tests=false rtc_enable_protobuf=false symbol_level=1 </span><span class="nv">$NO_SSL</span><span class="s2"> </span><span class="nv">$SSL_INCLUDE</span><span class="s2">"</span>

    ninja <span class="nt">-C</span> out/<span class="nv">$arch</span>
<span class="k">done

</span><span class="nb">popd</span>
</code></pre></div></div>

<p>The includes seem to be architecture-independent enough, that we don’t need to <code class="language-plaintext highlighter-rouge">./configure</code> them for each architecture.</p>]]></content><author><name>Ruben De Smet</name></author><summary type="html"><![CDATA[NOTE Sept 2025: Whisperfish does not have support for calling, yet. To include support for calling, we need a lot more work than just compiling the RingRTC library. This blog post documents the process of building and linking the RingRTC system into Whisperfish, but some users have interpreted this as to imply voice and video calling support. This is not the case. Currently, Whisperfish correctly decodes the calling state, and is able to display a “missed call” notification, thanks to the below work.]]></summary></entry><entry><title type="html">The European Union must keep funding free software</title><link href="https://www.rubdos.be/privacy/2024/09/02/ngi-open-letter.html" rel="alternate" type="text/html" title="The European Union must keep funding free software" /><published>2024-09-02T00:00:00+00:00</published><updated>2024-09-02T00:00:00+00:00</updated><id>https://www.rubdos.be/privacy/2024/09/02/ngi-open-letter</id><content type="html" xml:base="https://www.rubdos.be/privacy/2024/09/02/ngi-open-letter.html"><![CDATA[<p>I have been involved in multiple projects with funding granted by NGI through NLnet.
Many more FOSS projects benefit from NGI funding.</p>

<p>Initially published by <a href="https://ps.zoethical.org/pub/lettre-publique-aux-ncp-au-sujet-de-ngi/">petites singularités</a>. English translation provided by <a href="https://www.ow2.org/view/Events/The_European_Union_must_keep_funding_free_software_open_letter">OW2</a>.</p>

<h1 id="open-letter-to-the-european-commission">Open Letter to the European Commission</h1>

<p>Since 2020, Next Generation Internet (NGI) programmes, part of European Commission’s Horizon programme, fund free software in Europe using a cascade funding mechanism (see for example NGI0 Commons Fund). This year, according to the Horizon Europe working draft detailing funding programmes for 2025, we notice that Next Generation Internet is not mentioned any more as part of Cluster 4.</p>

<p>NGI programmes have shown their strength and importance to supporting the European software infrastructure, as a generic funding instrument to fund digital commons and ensure their long-term sustainability. We find this transformation incomprehensible, moreover when NGI has proven efficient and economical to support free software as a whole, from the smallest to the most established initiatives. This ecosystem diversity backs the strength of European technological innovation, and maintaining the NGI initiative to provide structural support to software projects at the heart of worldwide innovation is key to enforce the sovereignty of a European infrastructure.
Contrary to common perception, technical innovations often originate from European rather than North American programming communities, and are mostly initiated by small-scaled organisations.</p>

<p>Previous Cluster 4 allocated 27 million euros to:</p>

<ul>
  <li>“Human centric Internet aligned with values and principles commonly shared in Europe” ;</li>
  <li>“A flourishing internet, based on common building blocks created within NGI, that enables better control of our digital life” ;</li>
  <li>“A structured ecosystem of talented contributors driving the creation of new internet commons and the evolution of existing internet commons”.</li>
</ul>

<p>In the name of these challenges, more than 500 projects received NGI funding in the first 5 years, backed by 18 organisations managing these European funding consortia.</p>

<p>NGI contributes to a vast ecosystem, as most of its budget is allocated to fund third parties by the means of open calls, to structure commons that cover the whole Internet scope - from hardware to application, operating systems, digital identities or data traffic supervision. This third-party funding is not renewed in the current program, leaving many projects short on resources for research and innovation in Europe.</p>

<p>Moreover, NGI allows exchanges and collaborations across all the Euro zone countries as well as “widening countries”<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>, currently both a success and an ongoing progress, likewise the Erasmus programme before us. NGI also contributes to opening and supporting longer relationships than strict project funding does. It encourages implementing projects funded as pilots, backing collaboration, identification and reuse of common elements across projects, interoperability in identification systems and beyond, and setting up development models that mix diverse scales and types of European funding schemes.</p>

<p>While the USA, China or Russia deploy huge public and private resources to develop software and infrastructure that massively capture private consumer data, the EU can’t afford this renuFuntoonciation.
Free and open source software, as supported by NGI since 2020, is by design the opposite of potential vectors for foreign interference. It lets us keep our data local and favors a community-wide economy and know-how, while allowing an international collaboration.</p>

<p>This is all the more essential in the current geopolitical context: the challenge of technological sovereignty is central, and free software allows to address it while acting for peace and sovereignty in the digital world as a whole.</p>

<p>In this perspective, we urge you to claim for preserving the NGI programme as part of the 2025 funding programme.</p>

<hr />

<p>Signed, Ruben De Smet, lead developer of Whisperfish, <a href="https://pad.public.cat/lettre-NCP-NGI">among many more</a>.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>As defined by Horizon Europe, widening Member States are Bulgaria, Croatia, Cyprus, the Czech Republic, Estonia, Greece, Hungary, Latvia, Lituania, Malta, Poland, Portugal, Romania, Slovakia and Slovenia. Widening associated countries (under condition of an association agreement) include Albania, Armenia, Bosnia, Faroe Islands, Georgia, Kosovo, Moldavia, Montenegro, Morocco, North Macedonia, Serbia, Tunisia, Turkey and Ukraine. Widening overseas regions are : Guadeloupe, French Guyana, Martinique, Reunion Island, Mayotte, Saint-Martin, The Azores, Madeira, the Canary Islands. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Ruben De Smet</name></author><category term="privacy" /><category term="privacy" /><category term="cryptography" /><summary type="html"><![CDATA[I have been involved in multiple projects with funding granted by NGI through NLnet. Many more FOSS projects benefit from NGI funding.]]></summary></entry><entry><title type="html">Public PhD defense on June 17, 2024</title><link href="https://www.rubdos.be/privacy/2024/06/03/public-phd-defense.html" rel="alternate" type="text/html" title="Public PhD defense on June 17, 2024" /><published>2024-06-03T00:00:00+00:00</published><updated>2024-06-03T00:00:00+00:00</updated><id>https://www.rubdos.be/privacy/2024/06/03/public-phd-defense</id><content type="html" xml:base="https://www.rubdos.be/privacy/2024/06/03/public-phd-defense.html"><![CDATA[<h1 id="announcement-public-phd-defense">Announcement: Public PhD defense</h1>

<p>On June 17th, 2024, <a href="https://www.etrovub.be/people/member/about-bio/rdesmeta/">I</a> will defend my PhD thesis titled “Rapid prototyping and deployment of privacy-enhancing technologies” at the Vrije Universiteit Brussel.
My promotors are <a href="https://www.etrovub.be/people/member/about-bio/ksteenha/">prof. dr. ir. Kris Steenhaut</a> and <a href="https://researchportal.vub.be/en/persons/an-braeken">prof. dr. An Braeken</a>,
and my jury further consists out of
<a href="https://www.beetzsee.de/">prof. dr. Jan Tobias Mühlberg</a>,
<a href="https://www.kuleuven.be/wieiswie/en/person/00058206">dr. ing. Jorn Lapon</a>,
<a href="https://wids.research.vub.be/en/ann-dooms">prof. dr. Ann Dooms</a>,
<a href="https://www.etrovub.be/people/member/about-bio/ftemmerm/">prof. dr. ir. Frederik Temmermans</a>,
<a href="https://www.etrovub.be/people/member/about-bio/bjansen/">prof. dr. Bart Jansen</a>,
and <a href="https://researchportal.vub.be/en/persons/wendy-meulebroeck">prof. dr. ir. Wendy Meulebroeck</a>.</p>

<h2 id="practical-details">Practical details</h2>

<p>The defense will take place at the Vrije Universiteit Brussel, Campus Etterbeek, in the <a href="https://www.vub.be/sites/default/files/2022-09/220908_58439_Bereikbaarheidsfiche_Brussels_Main_Campus_DIGITAAL.pdf">Promotiezaal D.2.01</a> at <strong><a href="https://www.timeanddate.com/worldclock/fixedtime.html?msg=Public+PhD+defense+Ruben+De+Smet&amp;iso=20240617T10&amp;p1=48&amp;ah=2">🗺️ 10:00 CEST</a></strong>.</p>

<p>The defense will be in English, and will be tailored to a general audience.
The defense will be followed by a reception (probably at <em>‘t Complex</em>) around early noon.
If you cannot attend the defense and reception, I expect many people to stay at the Complex after 18:00.
If you would like to physically attend the defense or the reception,
<a href="https://forms.office.com/e/brf4FcD91w">please register online on https://forms.office.com/e/brf4FcD91w</a>.</p>

<p>The event will additionally be live-streamed via Microsoft Teams.
If you would like to receive the link to the live stream,
either <a href="https://forms.office.com/e/brf4FcD91w">register online</a>,
or <a href="/about">let me know via any other channel</a>, e.g. by Signal.</p>

<p><img src="/assets/img/phd-cover.png" alt="PhD cover" /></p>

<h2 id="abstract">Abstract</h2>

<blockquote>
  <p>Since its inception, the internet has quickly become a public service
utility. The combination of its commercial exploitation, and the rather
intimate nature of how humans actively use the internet, gives rise to
some paradoxical situations.</p>

  <p>As a citizen of Belgium, I would probably not expect to give my name and
phone number to a company in the United States to talk to my brother,
50 km up north. However, for over two billion people, this is their
rather paradoxical reality: the company Meta, owning WhatsApp, collects
and stores these data for their users. This cherry-picked scenario
stands example for a wider trend in the industry.</p>

  <p>Cryptographers have worked on several privacy-enhancing technologies (PETs).
These PETs aim to minimize the amount of personal data
to fulfill a service for users. Although these technologies exist on
paper, several practical issues arise. These practicalities are the
subject of this thesis.</p>

  <p>One practical issue is the performance. PETs, especially those that run on end-user
devices, should both be fast and require little bandwidth. We study how
implementation details may lead to significant speedups or bandwidth
savings. Specifically, we devise a zero-knowledge proof (ZKP) tailored to electronic road pricing (ERP).
ERP is a privacy-sensitive topic, and our ERP system achieves
some notable performance improvements over preexisting proposals.</p>

  <p>A second practical issue is the challenging nature of implementing
PETs. We present
“<a href="https://doi.org/10.1109/ACCESS.2022.3153366">Circuitree</a>” and “<a href="https://gitlab.com/whisperfish/whisperfish/">Whisperfish</a>”, to study how to bring PETs to an actual
application. Circuitree is a high-level framework to tailor ZKPs to specific
scenarios, using a bespoke logic programming language. The language is
designed such that the resulting ZKP is highly efficient.</p>

  <p>Whisperfish is effectively a reimplementation of the Signal instant
messaging client, and allows to present in detail how Signal deploys
their PETs to users.
All ideas put forward in this thesis were evaluated by means of their
implementation in the <a href="https://www.rust-lang.org/">Rust programming language</a>.</p>
</blockquote>

<h2 id="bibliography">Bibliography</h2>

<p>These publications have lead to the work in this thesis:</p>

<p><strong>De Smet, R.</strong>, <a href="https://researchportal.vub.be/en/persons/robrecht-blancquaert">Blancquaert, R.</a>, <a href="https://researchportal.vub.be/en/persons/tom-godden">Godden, T.</a>, <a href="https://www.etrovub.be/people/member/about-bio/ksteenha/">Steenhaut, K.</a>, &amp; <a href="https://researchportal.vub.be/en/persons/an-braeken">Braeken, A.</a> (2024).<a href="https://doi.org/10.3390/s24031030">Armed with Faster Crypto: Optimizing Elliptic Curve Cryptography for ARM Processors. Sensors, 24(3), Article 3.</a></p>

<p><strong>De Smet, R.</strong>, <a href="https://www.etrovub.be/people/member/about-bio/ksteenha/">Steenhaut, K.</a>, &amp; <a href="https://researchportal.vub.be/en/persons/an-braeken">Braeken, A.</a> (2023). <a href="https://doi.org/10.1109/TDSC.2023.3314867">Private Electronic Road Pricing using Bulletproofs with Vector Commitments. IEEE Transactions on Dependable and Secure Computing, 1–13.</a></p>

<p><a href="https://researchportal.vub.be/en/persons/tom-godden">Godden, T.</a>, <strong>De Smet, R.</strong>, <a href="https://chrdebru.github.io/">Debruyne, C.</a>, <a href="https://thvdveld.be/">Vandervelden, T.</a>, <a href="https://www.etrovub.be/people/member/about-bio/ksteenha/">Steenhaut, K.</a>, &amp; <a href="https://researchportal.vub.be/en/persons/an-braeken">Braeken, A.</a> (2022). <a href="https://doi.org/10.1109/ACCESS.2022.3153366">Circuitree: A Datalog Reasoner in Zero-Knowledge. IEEE Access, 10, 21384–21396.</a></p>

<p><a href="https://thvdveld.be/">Vandervelden, T.</a>, <strong>De Smet, R.</strong>, <a href="https://www.etrovub.be/people/member/about-bio/ksteenha/">Steenhaut, K.</a>, &amp; <a href="https://researchportal.vub.be/en/persons/an-braeken">Braeken, A.</a> (2022). <a href="https://doi.org/10.1016/j.future.2021.09.042">SHA3 and Keccak variants computation speeds on constrained devices. Future Generation Computer Systems, 128, 28–35.</a></p>

<p>I would like to thank my co-authors for their contributions to these articles.
I would also like to thank Matti, direc85, for his contributions to Whisperfish.</p>]]></content><author><name>Ruben De Smet</name></author><category term="privacy" /><category term="signal" /><category term="privacy" /><category term="circuitree" /><category term="zero-knowledge proofs" /><category term="cryptography" /><summary type="html"><![CDATA[Announcement: Public PhD defense]]></summary></entry><entry><title type="html">My problem with Beeper</title><link href="https://www.rubdos.be/privacy/signal/2023/09/07/my-problem-with-beeper.html" rel="alternate" type="text/html" title="My problem with Beeper" /><published>2023-09-07T00:00:00+00:00</published><updated>2023-09-07T00:00:00+00:00</updated><id>https://www.rubdos.be/privacy/signal/2023/09/07/my-problem-with-beeper</id><content type="html" xml:base="https://www.rubdos.be/privacy/signal/2023/09/07/my-problem-with-beeper.html"><![CDATA[<p><a href="https://www.beeper.com/">Beeper</a> is a tool to get all your chats in one smooth and integrated application.
It’s founded by <a href="https://twitter.com/ericmigi">Eric Migicovsky</a> and <a href="https://twitter.com/bradtgmurray">Brad Murray</a>,
known for having built the awesome <a href="https://en.wikipedia.org/wiki/Pebble_(watch)">Pebble watches</a> in the past<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</p>

<p>I am the first one to admit that keeping a crazy number of chat applications and accounts around is horrible.
I am on Matrix (@rubdos:rubdos.be; I even host my own server),
Signal (I maintain <a href="https://gitlab.com/whisperfish/whisperfish/">Whisperfish</a>, a third-party Signal client),
IRC (Weechat),
e-mail (with multiple different accounts),
and probably a whole lot more that I don’t bother to check.
Other people use iMessage, Instagram, Facebook, and even worse platforms for intimate conversation<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>.
Especially with the tendency nowadays to write every chat application in Electron (Signal Desktop and Element come to mind in my case),
this problem hogs a lot of CPU and RAM that I would rather invest in something else.</p>

<p>This problem is what Beeper wants to solve:
all your chats in one single interface.
They are barely the first to attempt this.
<a href="https://pidgin.im/">Pidgin</a>, for example, is also a unified instant messaging interface.
The <a href="https://telepathy.freedesktop.org/wiki/">Telepathy framework</a> is another one.
These are instant messaging (IM) <em>clients</em> with plugins for every protocol,
and handle the integration locally on the device.</p>

<p>What makes Beeper unique, is the implementation of the unification.
Essentially, Beeper is a “normal” Matrix client, and all other protocols are bridged into the Matrix server.
This means that your Beeper account is accessible from all different kinds of devices,
and all of these devices will have a unified view over your IM accounts.
This is extremely convenient!</p>

<h1 id="beeper-destroys-privacy-for-non-beeper-users">Beeper destroys privacy for non-Beeper users</h1>

<p>Since Beeper implements the unification on the server-side,
the properties of a chat session are reduced to the capabilities of the Matrix protocol,
and the end-to-end encryption is terminated <em>at the bridge side</em>.
This implies that Beeper effectively acts as a man-in-the-middle, breaking end-to-end encryption, putting user data of all their users in the same place.
At least, this implies that your plain text messages exist in memory on the Beeper servers, including metadata and account and session keys.
Additionally, Beeper has the goal of implementing messenger interoperability,
which <a href="https://alecmuffett.com/article/14656">reduces properties of all protocols for all contact to the lowest-common-denominator</a> in cases of mixed-protocol sessions.</p>

<p>Let’s consider the implications from the Signal point-of-view,
since Signal is quite universally considered the state-of-the-art from a privacy perspective.
For example, Signal does not know<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup> the members of groups,
because of their recent-ish <a href="https://signal.org/blog/signal-private-group-system/">private group system</a> (2019).
Beeper, being a Matrix server, will need access to the decrypted group state,
and hence the Beeper server <em>will</em> know the members of any group.
Consider the implications of the above:
<strong>being a passive member of a group with even a single Beeper user destroys group anonymity!</strong></p>

<p>This is also true for existing groups.
If you are part of a group on Signal,
and one of the members decides to try Beeper with their existing Signal account,
the Beeper bridge server will know about your group membership,
without you ever consenting.</p>

<p>Lastly and relatedly, there are some security and practicality concerns, not necessarily relating to privacy.
Services like Signal or WhatsApp might disagree, for <a href="https://gitlab.com/whisperfish/whisperfish/-/issues/398">various reasons</a>, to allow connections from Beeper.
They might change their mind over night, or you might bounce on the <a href="https://signal.org/blog/keeping-spam-off-signal/">spam filter</a>, or hit some <a href="https://gitlab.com/whisperfish/whisperfish/-/issues/417">rate limiter</a>.
There are a plethora of implicit security issues of sharing the same Beeper IP address when connecting to messaging services.</p>

<h1 id="self-hosting-beeper-solves-the-problem">Self-hosting Beeper “solves” the problem</h1>

<p>I discussed this issue with Eric, when I had the privilege of meeting him in Brussels in February.
Largely, the issue boils down to your trust in the host of the Beeper bridges:
if you trust the bridges, then it does not necessarily matter that it knows about group states, the contents of messages, or the contacts you are talking to.</p>

<p>Even when you trust Beeper’s servers, there are potential issues.
You may have trusted their servers yesterday, but today they can get seized by a government, or Beeper might get breached.
Or they might move their servers onto a malicious or curious cloud provider.</p>

<p>So, if you don’t trust the Beeper servers, they offer you the option to <a href="https://github.com/beeper/self-host">self-host</a>.
However, this only solves one half of the issue.
Alice might trust their own server, but Bob is still forced to communicate with a bridge they don’t know about.
Additionally, self-hosting always implies a maintenance burden, which might weaken the security of the communication.
In my experience, self-hosting and federation is not a solution to a privacy problem, nor does it give back your autonomy.
E-mail is a federated protocol and can be self-hosted.
In practice, we are all unwillingly users of Google Mail and Outlook at the same time.
Mastodon is a federated system, but in practice we all rely on mastodon.social.
In extenso, Matrix is a federated system, but in practice we all rely on Matrix.org.
You don’t get autonomy nor privacy if your contacts are on a server you don’t trust.</p>

<h1 id="dont-complain-suggest-whats-better">Don’t complain; suggest what’s better</h1>

<p>Honestly, I don’t know.
Fragmentation of communication is a real issue,
and a difficult, maybe impossible one to solve.
I am actively forcing all my personal communication on Signal,
and my professional communication through email (Thunderbird) and Matrix (<a href="https://github.com/poljar/weechat-matrix">weechat-matrix</a>).
This is not a (long term) solution, because I’m putting trust in Signal LLC, where it might not be appropriate.</p>

<p>The emotional or interpersonal implications of “please kindly register on Signal because I’m not used by Facebook” can be quite drastic,
and I realize it is not a procedure that most people can afford to follow.</p>

<p>Sadly, life is sometimes more complicated than a technological solution might make it seem like.</p>

<h1 id="acknowledgements">Acknowledgements</h1>

<p>I would like to explicitly thank <a href="https://github.com/valldrac">valldrac</a> for his feedback on this post.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>I still wear my Pebble Time every day. Its wrist band broke a few weeks ago next to a moshpit, so now it’s a red Pebble Time with a white wrist band. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>As I explained <a href="https://video.rubdos.be/w/6KrhTEXzbPHoED1ztEomUU">during my talk about Whisperfish in Lausanne</a>, I do not trust any platform except Signal for intimate conversations.  Also, wow, I speak with a really heavy Belgian accent nowadays. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Signal private groups are of course not perfect. Network traffic analysis can uncover group structure, and this is generally a moving target. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Ruben De Smet</name></author><category term="privacy" /><category term="signal" /><category term="digital markets act" /><category term="signal" /><category term="privacy" /><category term="beeper" /><summary type="html"><![CDATA[Beeper is a tool to get all your chats in one smooth and integrated application. It’s founded by Eric Migicovsky and Brad Murray, known for having built the awesome Pebble watches in the past1. I still wear my Pebble Time every day. Its wrist band broke a few weeks ago next to a moshpit, so now it’s a red Pebble Time with a white wrist band. &#8617;]]></summary></entry><entry><title type="html">How to overengineer a vacuum cleaner</title><link href="https://www.rubdos.be/2023/04/22/vacuum.html" rel="alternate" type="text/html" title="How to overengineer a vacuum cleaner" /><published>2023-04-22T20:41:00+00:00</published><updated>2023-04-22T20:41:00+00:00</updated><id>https://www.rubdos.be/2023/04/22/vacuum</id><content type="html" xml:base="https://www.rubdos.be/2023/04/22/vacuum.html"><![CDATA[<p>I own an <a href="https://support.eufy.com/s/product/a085g000000Nm4PAAS/robovac-11s">Eufy Robovac 11s</a>.
This is an IR-controlled vacuum cleaner, and I have been commanding it via Home Assistant and a <a href="https://www.home-assistant.io/integrations/broadlink/">Broadlink</a> IR-remote since as long as I can remember.</p>

<p>The automation was relatively simple:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">alias</span><span class="pi">:</span> <span class="s">When nobody is home, start Dobby</span>
  <span class="na">description</span><span class="pi">:</span> <span class="s1">'</span><span class="s">'</span>
  <span class="na">trigger</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">state</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">group.family</span>
    <span class="na">to</span><span class="pi">:</span> <span class="s">not_home</span>
    <span class="na">for</span><span class="pi">:</span>
      <span class="na">minutes</span><span class="pi">:</span> <span class="m">5</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">time</span>
    <span class="na">at</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s1">'</span><span class="s">8:00:00'</span>
    <span class="pi">-</span> <span class="s1">'</span><span class="s">12:00:00'</span>
    <span class="pi">-</span> <span class="s1">'</span><span class="s">16:00:00'</span>
    <span class="pi">-</span> <span class="s1">'</span><span class="s">20:00:00'</span>
  <span class="na">condition</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">condition</span><span class="pi">:</span> <span class="s">state</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">group.family</span>
    <span class="na">state</span><span class="pi">:</span> <span class="s">not_home</span>
    <span class="na">for</span><span class="pi">:</span>
      <span class="na">minutes</span><span class="pi">:</span> <span class="m">5</span>
  <span class="pi">-</span> <span class="na">condition</span><span class="pi">:</span> <span class="s">time</span>
    <span class="na">after</span><span class="pi">:</span> <span class="s1">'</span><span class="s">7:00'</span>
    <span class="na">before</span><span class="pi">:</span> <span class="s1">'</span><span class="s">20:00'</span>
  <span class="pi">-</span> <span class="na">condition</span><span class="pi">:</span> <span class="s">state</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">switch.dobby</span>
    <span class="na">state</span><span class="pi">:</span> <span class="s">off</span>
    <span class="na">for</span><span class="pi">:</span>
      <span class="na">hours</span><span class="pi">:</span> <span class="m">11</span>
  <span class="na">action</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">service</span><span class="pi">:</span> <span class="s">switch.turn_on</span>
    <span class="na">target</span><span class="pi">:</span>
      <span class="na">entity_id</span><span class="pi">:</span> <span class="s">switch.dobby</span>
  <span class="pi">-</span> <span class="na">service</span><span class="pi">:</span> <span class="s">notify.notify</span>
    <span class="na">data</span><span class="pi">:</span>
      <span class="na">title</span><span class="pi">:</span> <span class="s">Dobby</span>
      <span class="na">message</span><span class="pi">:</span> <span class="s">Stof zuigen zal ik doen!</span>
  <span class="na">mode</span><span class="pi">:</span> <span class="s">single</span>
</code></pre></div></div>

<p>Basically, Dobby cleaned the appartement at most once a day, whenever nobody was there.
This idea has a few drawbacks:</p>
<ul>
  <li>During the weekends, I would often get to the shop for 10 minutes and return immediately.
If I would leave again for a longer period the same day, Dobby would have only cleaned for five or ten minutes.</li>
  <li>Dobby would clean every day, even when on a vacation.</li>
  <li>Maybe I would like Dobby to clean during certain periods when I’m home, too. For example, Dobby could go around while I’m in the shower.</li>
</ul>

<h1 id="simulating-dust-and-batteries">Simulating dust and batteries</h1>

<p>At this point, it is clear that Dobby should become smarter.
Remember, Dobby is an Eufy 11s, which has no connectivity whatsoever.
This implies that Dobby is controlled 100% open-loop:
Home Assistant can send a start command via IR,
and a stop-and-go-home command,
but I have no way of obtaining any information about Dobby’s state.
At a certain point, I will probably slap an ESP32 with <a href="https://esphome.io/">ESPHome</a> on it to have <em>some</em> feedback about battery and cleaning,
but currently, Dobby cannot talk to me.</p>

<p>In order to have an idea about the battery charge status,
I opted to build a simulator for it.
The <code class="language-plaintext highlighter-rouge">dobby_charge_rate</code> is a function of whether Dobby is home or cleaning,
and the <code class="language-plaintext highlighter-rouge">dobby_charge</code> is the integral of that function.
Note in the code below that I added a small random term for the integration to actually trigger.
Suggestions for (ahum) cleaning that up are welcome.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="na">template</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">trigger</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">time_pattern</span>
        <span class="na">minutes</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/2"</span>
    <span class="na">sensor</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Dobby charge rate</span>
        <span class="na">unique_id</span><span class="pi">:</span> <span class="s">dobby_charge_rate</span>
        <span class="na">unit_of_measurement</span><span class="pi">:</span> <span class="s2">"</span><span class="s">%/h"</span>
        <span class="c1"># Home: 25%/h</span>
        <span class="c1"># Running: 75%/h</span>
        <span class="na">state</span><span class="pi">:</span> <span class="pi">&gt;-</span>
          <span class="s">{% set dobby = is_state('switch.dobby', 'on') | int %}</span>
          <span class="s">{% set dobby_not_full = states('sensor.dobby_battery_charge') == "unknown" or (states('sensor.dobby_battery_charge') | int &lt;= 100) %}</span>
          <span class="s">{% set dobby_not_empty = states('sensor.dobby_battery_charge') == "unknown" or (states('sensor.dobby_battery_charge') | int &gt;= 0) %}</span>
          <span class="s">{{ -75 * dobby * (dobby_not_empty | int) + 25 * (1 - dobby) * (dobby_not_full | int) + (range(-9, 10) | random)/100 }}</span>

<span class="na">sensor</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">integration</span>
    <span class="na">source</span><span class="pi">:</span> <span class="s">sensor.dobby_charge_rate</span>
    <span class="na">unit_time</span><span class="pi">:</span> <span class="s">h</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">Dobby battery charge</span>
    <span class="na">unique_id</span><span class="pi">:</span> <span class="s">dobby_charge</span>

</code></pre></div></div>

<p>Additionally, I made a <code class="language-plaintext highlighter-rouge">dust_accumulation_rate</code> and <code class="language-plaintext highlighter-rouge">accumulated_dust</code>, in the same fashion.
This is based on the number of people that are present at home.
The constants are based on the idea that Dobby should clean every four days in vacation mode, but again every day when I’m actually home for any significant time.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="na">template</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">trigger</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">time_pattern</span>
        <span class="na">minutes</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/2"</span>
    <span class="na">sensor</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Dust accumulation rate</span>
        <span class="na">unique_id</span><span class="pi">:</span> <span class="s">dust_accumulation_rate</span>
        <span class="na">unit_of_measurement</span><span class="pi">:</span> <span class="s2">"</span><span class="s">%/h"</span>
        <span class="c1"># .5%/hour base rate = 50% every four days</span>
        <span class="c1"># 10 hours * one person = 90% dust</span>
        <span class="c1"># 1 hour * one dobby = -100% dust</span>
        <span class="na">state</span><span class="pi">:</span> <span class="pi">&gt;-</span>
          <span class="s">{% set dobby = is_state('switch.dobby', 'on') | int %}</span>
          <span class="s">{% set not_max_dust = states('sensor.accumulated_dust') == "unknown" or (states('sensor.accumulated_dust') | int &lt;= 100) %}</span>
          <span class="s">{% set not_min_dust = states('sensor.accumulated_dust') == "unknown" or (states('sensor.accumulated_dust') | int &gt;= 0) %}</span>
          <span class="s">{{ (((states('zone.home') | int) * 9 + 0.5 * (1 - dobby)) * not_max_dust - (100 * dobby) * not_min_dust) + (range(-9, 10) | random)/100 }}</span>

<span class="na">sensor</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">integration</span>
    <span class="na">source</span><span class="pi">:</span> <span class="s">sensor.dust_accumulation_rate</span>
    <span class="na">unit_time</span><span class="pi">:</span> <span class="s">h</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">Accumulated dust</span>
    <span class="na">unique_id</span><span class="pi">:</span> <span class="s">accumulated_dust</span>

</code></pre></div></div>

<p>Based on these two properties, I changed the automation to trigger at 99% battery and 75% dust, still checking the presence status of inhabitants and guests.</p>

<h1 id="taking-it-a-step-further-shower-detection">Taking it a step further: shower detection</h1>

<p>Now onto the most silly part:
I would like Dobby to clean while I’m home alone and showering.
During that time, Dobby would not bother anybody,
and can freely roam about for about 15 minutes.
This is especially useful if I don’t plan to be away for a long time, and I would have guests over the same day.</p>

<p>My first attempt at detecting shower presence was based on the bathroom humidity sensor.
And so was my second and third attempt.
I’m not sure which version this one is, but this is the last I tried:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="na">sensor</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">statistics</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">Bathroom Humidity Stats</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">sensor.xiaomith2_humidity</span>
    <span class="na">state_characteristic</span><span class="pi">:</span> <span class="s">mean</span>
    <span class="na">sampling_size</span><span class="pi">:</span> <span class="m">40</span>
    <span class="na">max_age</span><span class="pi">:</span>
      <span class="na">hours</span><span class="pi">:</span> <span class="m">1</span>

<span class="na">binary_sensor</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">platform</span><span class="pi">:</span> <span class="s">template</span>
    <span class="na">sensors</span><span class="pi">:</span>
      <span class="na">showering</span><span class="pi">:</span>
        <span class="na">value_template</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">states('sensor.xiaomith2_humidity')</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">int</span><span class="nv"> </span><span class="s">&gt;</span><span class="nv"> </span><span class="s">states('sensor.bathroom_humidity_stats')</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">int</span><span class="nv"> </span><span class="s">+</span><span class="nv"> </span><span class="s">5</span><span class="nv"> </span><span class="s">and</span><span class="nv"> </span><span class="s">states('sensor.bathroom_humidity_stats')</span><span class="nv"> </span><span class="s">!=</span><span class="nv"> </span><span class="s">'unknown'</span><span class="nv"> </span><span class="s">}}"</span>
        <span class="na">friendly_name</span><span class="pi">:</span> <span class="s">Showering</span>
        <span class="na">device_class</span><span class="pi">:</span> <span class="s">occupancy</span>

</code></pre></div></div>

<p>Basically: if the humidity is over 5% higher than the hourly mean, I consider the shower to be occupied.</p>

<p>This worked, more or less.
Dobby would start cleaning by the time I got out of the shower, and then probably started and stopped a few times more while I was in the living room.</p>

<p>Finding those exact offsets that work is annoying and unpleasent,
and this process finally got me to touch machine learning.
Over the course of today’s afternoon,
I wrote <a href="https://gitlab.com/rubdos/hasli/">a little KNN inference system</a> that talks to Home Assistant, and bases its features and samples of <a href="https://www.home-assistant.io/integrations/logbook/">Home Assistant’s logbook</a>.
To be more precice: Hasli keeps track of a list of entities, and runs inference when the tracked entities change their state.
Hasli will then update its own entities in Home Assistant, for further use in automations.</p>

<p>Currently, a configuration for Hasli looks like this:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">binary</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">showering"</span>
  <span class="na">input_entities</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bathroom</span><span class="nv"> </span><span class="s">humidity"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor.xiaomith2_humidity"</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bathroom</span><span class="nv"> </span><span class="s">temperature"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor.xiaomith2_temperature"</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bedroom</span><span class="nv"> </span><span class="s">humidity"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor.slaapkamer_smart_air_humidity"</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bedroom</span><span class="nv"> </span><span class="s">temperature"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">sensor.slaapkamer_smart_air_temperature"</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">people</span><span class="nv"> </span><span class="s">counter"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">zone.home"</span>

  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bedside</span><span class="nv"> </span><span class="s">presence</span><span class="nv"> </span><span class="s">3"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">binary_sensor.lidlpresence3_occupancy</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">toilet</span><span class="nv"> </span><span class="s">presence"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">binary_sensor.lidlpresence1_occupancy</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">bedside</span><span class="nv"> </span><span class="s">presence</span><span class="nv"> </span><span class="s">2"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">binary_sensor.lidlpresence2_occupancy</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">living</span><span class="nv"> </span><span class="s">humidity"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">sensor.living_smart_air_humidity</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">living</span><span class="nv"> </span><span class="s">temperature"</span>
    <span class="na">entity_id</span><span class="pi">:</span> <span class="s">sensor.living_smart_air_temperature</span>
</code></pre></div></div>

<h2 id="expanding-hasli">Expanding Hasli</h2>

<p>Currently, I have a local <code class="language-plaintext highlighter-rouge">main.rs</code> that is tailored towards my own “showering” inference.
My hope is that Dobby will clean tomorrow morning while I’m in the shower.
If that works, the goal is to make Hasli a proper daemon, and integrate it with the Home Assistant UI to allow everyone to design inference systems based on their sensors, and annotate the required data through the Home Assistant UI.</p>

<p>Any help to get data annotation integrated in Home Assistant would be very welcome.
I envision a UI element where you can annotate a timeline of your own sensor data, not unlike the <a href="https://github.com/alexarch21/history-explorer-card">History Explorer Card</a> by <a href="https://github.com/alexarch21/">alexarch21</a>.</p>

<p>Hasli should also expose a service to Home Assistent, such that data annotation can be automated!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I own an Eufy Robovac 11s. This is an IR-controlled vacuum cleaner, and I have been commanding it via Home Assistant and a Broadlink IR-remote since as long as I can remember.]]></summary></entry><entry><title type="html">End-to-end encryption is not the end</title><link href="https://www.rubdos.be/2022/04/15/about-secure-messengers.html" rel="alternate" type="text/html" title="End-to-end encryption is not the end" /><published>2022-04-15T00:00:00+00:00</published><updated>2022-04-15T00:00:00+00:00</updated><id>https://www.rubdos.be/2022/04/15/about-secure-messengers</id><content type="html" xml:base="https://www.rubdos.be/2022/04/15/about-secure-messengers.html"><![CDATA[<p><em>This article first appeared in Dutch,
simultaneously in <a href="https://ministryofprivacy.eu/2022/02/16/leesvoer-hier-is-de-derde-uitgave-van-ministrytalks-ons-privacymagazine/">Ministry Talks</a>
and via the <a href="https://cybersecurity-research.be/x/2967">Cybersecurity Research Flanders project</a>.
This is an English language translation of the original publication.</em></p>

<p>The year is 2015.
Mae’s message to Annie that she sent via Facebook Messenger is intercepted.</p>

<p>“I’m sick of this place,” reads Mark, her boss at Facebook.
Mae and Annie were no longer allowed to communicate.
Above all, Mark now knows that Mae doesn’t appreciate her job or Facebook’s values and standards very much.</p>

<p>In a parallel universe, we find ourselves in the year 2022.
Facebook is now called Meta.
In 2016, Meta added end-to-end encryption to Messenger in view of their <a href="https://messengernews.fb.com/2021/04/30/messenger-policy-workshop-future-of-private-messaging/">Commitment to Privacy</a>.
With end-to-end encryption, the content of a message is only readable by the sender and the recipient, not anymore by the messaging service.
However, the message that Mae just sent to Annie via Messenger is intercepted again.
Mark knows that Mae and Annie are communicating; Mae is in trouble again.</p>

<p>Since Edward Snowden’s revelations in 2013, the use of end-to-end encryption has been gaining momentum, because it safeguards our privacy.
Despite this, Mae is in trouble in both universes.
End-to-end encryption is a good start, but unfortunately, it seems insufficient.</p>

<p>In fact, end-to-end encryption only protects against reading messages during their transit.
End-to-end encryption is therefore a <em>minimum requirement</em> for a private messaging service, just like a letter in the mail is also in a sealed envelope, or just just like a message that has to remain within the four walls of your home also doesn’t get projected onto your outside walls.</p>

<p>Few messaging apps turn on that end-to-end encryption by default.
Messenger has been planning to turn that option on by default for a while,
but for now, the user has to do that manually, after a search in the options.
Even with Telegram you have to manually create a “Secret Chat”, which additionally means you lose a lot of functionality.
The best students in the class here are Signal and Threema, where end-to-end encryption is a requirement.</p>

<p>To understand why Mae is in trouble, despite end-to-end encryption, we need to look at metadata.
Since 2016, Meta, then Facebook, has been making a statement:
they are not (or no longer) interested in the content of conversations, because conversations are now optionally end-to-end encrypted.
For them, the value of a messaging service lies is in knowing the dynamics of the social network:
Who talks to whom?
When?
Where are the individuals when they send those messages?
How frequently do they talk?
Like no other, Meta knows the value of metadata;
they changed their name for a reason.
Meta knows all too well how to exploit and valorize this data,
and <a href="https://www.facebook.com/policy.php">mention this in their privacy policy</a>:</p>

<blockquote>
  <p>[W]e combine this information across different devices you use.
For example, we use information collected about your use of our Products on your phone to better personalize the content (including ads) or features you see when you use our Products on another device,
such as your laptop or tablet, or to measure whether you took an action in response to an ad we showed you on your phone on a different device.</p>
</blockquote>

<h1 id="sealed-sending-signal-and-zero-knowledge">Sealed sending, Signal and zero-knowledge</h1>

<p>Their polar opposite is called Signal.
Signal rules the Metadata-free Empire.
Had Mae used Signal, Mark would not have known that Mae and Annie were still talking.
In fact, since 2018, Signal has been using “<a href="https://signal.org/blog/sealed-sender/">sealed sending</a>”,
where the sender of a message does not identify themselves when sending a message.
“Sealed sending” is the technological equivalent of not listing the sender on the envelope.
This sounds simple in theory, but in practice is quite complicated.
If you allow anyone to reach a digital mailbox, then you’re also allowing them to receive unwanted messages and you potentially create an avalanche of spam.</p>

<p>Signal uses a zero-knowledge proof against this.
Zero-knowledge proofs have recently become become very popular to solve privacy problems in crypto currencies such as Monero and ZCash.
They allow you to convince someone of certain propositions, without disclosing any information in the process.
In the case of crypto currencies, a zero-knowledge proof is used to ensure that an encrypted transaction is sound:
the payer proves that their wallet does not go below zero because of that transaction,
without disclosing how big the transaction or the contents of their wallet is.
In Signal, you prove to the servers that the receiver allows messages to be received from you, without disclosing who you are.</p>

<p>The practical implications of zero-knowledge proofs reach a lot further than private transactions or sending sealed messages.
For example, it is possible to design an alternative to the EU Digital COVID certificate (in Belgium, COVID-Safe Ticket, CST),
which dynamically generates a QR-code depending on the local rules.
This QR-code, unlike the original on the CST,
does not contain any information about your vaccination or test status.
It only contains a “proof” that indicates you comply with the rules.
Besides, creating such a zero-knowledge CST is possible without any cooperation of the involved governments.
This highlights the contrast between the CST and the Bluetooth based contact tracing.
The contact tracing application was developed with the explicit intention of collecting and processing the least amount of information possible,
but this effort has clearly not taken place during the development of the digital COVID certificate.</p>

<h2 id="private-group-messaging">Private group messaging</h2>

<p>At the end of 2019, Signal introduced <a href="https://signal.org/blog/signal-private-group-system/">another technological advancement</a>,
also made possible in part because of zero-knowledge proofs.
For sending messages in groups,
most messaging services make use of
“server fan-out”:
the sender sends the message once to the server,
and the server takes care to distribute the message to the individual group members.
For the server to execute that process correctly,
it needs to know the structure of the group.
This is not the case for Signal,
nor for most other “client fan-out” systems.
In these systems, the sender is responsible for sending the message to every group member individually.
The disadvantage of this technique is the necessary bandwidth when sending a message.</p>

<p>Signal always used client fan-out
because of its privacy advantage.
The most important argument for server fan-out,
apart from the higher bandwidth requirement,
is keeping the group <em>structure</em> consistent.
In a naive client fan-out system,
the group structure is dictated by the last observed update,
independent of who supplied that update.
You could consider this total anarchy,
but only until December 2019.</p>

<p>In order to keep the group structure consistent,
Signal will now store the group structure on their server,
in encrypted form.
Note that Signal still does not see who are the members of the group,
but it will act as an authority on the correct member list.
A group administrator can now change the list, by adding or removing members.
This poses a problem, however: the server needs to be sure that the list is modified by someone with permission,
but the users of the group do not want to identify themselves when carrying out such a mutation.
The privacy of the users is guaranteed through a zero-knowledge proof.
The user proves that they are in the list of administrators,
without disclosing their identity.</p>

<p>The net effect is an anonymous authentication system:
users can prove their permission level, without disclosing who they really are,
all while the servers are ensured that only privileged users can access sensitive data.</p>

<h1 id="other-modern-cryptographic-techniques">Other modern cryptographic techniques</h1>

<p>Zero-knowledge proofs are only one of the many modern cryptographic advancements that are currently being studied.
They are deployed more and more, because they achieve a concrete result,
without overly compromising performance of the application.
Other techniques are still young,
and might have an unacceptable impact on performance.
As an example, homomorphic encryption allows to make computations on encrypted data,
allowing to later decrypt the computed result.
A dream application is to apply artificial intelligence in large data centres,
without them ever needing the actual privacy sensitive data.
This is possible on paper,
but still prohibitively expensive in terms of computational cost.
For simpler computations, homomorphic encryption is already very practical,
and is for instance used in the new Signal group system.</p>

<p>Another promising technique is “secure multy-party computation” (SMPC or simply MPC).
MPC allows two or more parties to keep some values secret,
while being able to compute a common result from those secret values.
The classic example is the rich man game of computing who is the richest among a group of people, without disclosing each others net value.
Practically, MPC has been used to make statistics and studies on databases that could not be joined because of their privacy sensitive contents.</p>

<p>With modern cryptography,
many modern digital privacy issues can be tackled.
Not only on messaging services, but also far outside that realm.
Often, those problems are not visible at the surface.</p>

<p>While the focus of this article was on the privacy enhancing techniques used in Signal,
Signal is of course not holy or unique in improving technology.
Newcomers such as <a href="https://getsession.org/">Session</a>
also innovate in techniques to hide metadata.
For an outsider, it is sadly difficult to judge these alternatives.
Signal is critiqued, rightfully so, on requiring a phone number during registration.
This critique often shadows the more fundamental, less visible positive aspects of Signal’s engineering.
It is however clear that Signal leads many innovations in terms of privacy-enhancing technology.
End-to-end encryption is clearly only the start of innovation in privacy-enhancing technology,
and the innovations mentioned in this article are most definitely not the end.</p>

<h1 id="acknowledgement">Acknowledgement</h1>

<p>The writing of this article was supported by Cybersecurity
Vlaanderen, under the Cybersecurity: Outreach &amp; Training programme.
This article goes together with the article “Cryptographic techniques for data minimisation”
(Nl. “<a href="https://cybersecurity-research.be/x/2810">Cryptografische technieken
voor dataminimalisatie</a>”, currently untranslated),
which dives deeper into the technical details of the cryptographic primitives mentioned in this article.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[This article first appeared in Dutch, simultaneously in Ministry Talks and via the Cybersecurity Research Flanders project. This is an English language translation of the original publication.]]></summary></entry></feed>