• chevron_right

    Dino 0.3 Release / Dino · Saturday, 12 February - 21:22 · 3 minutes

Dino is a secure and privacy-friendly messaging application. It uses the XMPP (Jabber) protocol for decentralized communication. We aim to provide an intuitive, clean and modern user interface.


The 0.3 release is all about calls. Dino now supports calls between two or more people!

Calls are end-to-end encrypted and use a direct connection between the peers whenever possible, but fallbacks are also in place.

As always, we put lots of love into the user interface and hope that you will enjoy using it. To call a friend, just open a conversation with them and select whether you want to start an audio-only or a video call.


You also can start a call in a private group or invite additional contacts to an existing call. Using a peer-to-peer approach for groupcalls means that no additional server support is required, besides conference rooms.

Peer-to-peer calls require more bandwidth than calls routed through a server and are thus not suited for a large number of participants. In the future, we plan to also develop calls via a forwarding server to solve resource issues on the client side and to allow for calls with more participants.



Calls are end-to-end encrypted with the best encryption supported by both you and your contact. The encryption keys for a call are exchanged using DTLS and the call is then encrypted with SRTP. You can see the DTLS keys used for the current call in the UI and compare them with the ones your contact sees.

Additionally, the DTLS keys are authenticated using OMEMO. If you verified the OMEMO key beforehand, you can be sure that you have an end-to-end encrypted call with a device that you trust.

Interoperabilility & Open Protocols

Calls are established and conducted using openly standardized protocols. Call intents are sent ( XEP-0353 ) and connection methods exchanged via XMPP ( RFC 6120 ) in a standardized way ( XEP-0167 ), the data is encrypted ( RFC 5763 ) and transferred ( RFC 3550 ) all via standardized and documented means.

You can establish calls between Dino and every other application that follows these standards. Encrypted video calls can be made between Dino and for example Conversations or Movim. With clients like Gajim that don’t support encryption, making unencrypted calls is also possible. If a client doesn’t support video, audio-only calls can still be made.



Peat bogs are unique ecosystems that mitigate the effects of climate change if they’re in a natural state, but worsen climate change when they are drained. We named this Dino release “Theikenmeer” after a bog nature reserve in Germany to help spread the word about these important yet endangered ecosystems.

Peat bogs are wetlands that accumulate peat, a deposit of dead moss and other plant material. Due to low oxygen levels, moss below the water surface does not decay and thus accumulates bit by bit. By accumulating plant material, bogs store carbon. Although they only make up 3% of the world’s land surface, bogs store twice as much carbon as all forests together! [ 1 ]


Besides capturing carbon, a bog also provides other benefits to its surroundings. A bog acts like a sponge: It absorbs water when it’s abundant and releases it back into the surrounding when it’s dry. Thus, it reduces the severity of floods and droughts. Bogs also lower the temperatures in the surroundings, filter the groundwater and are home to endangered and specialized plants and animals.

During the last centuries, peat bogs have been increasingly drained in order to make use of the land or to extract the peat. When a bog is dry, the accumulated plant material starts to decay, releasing the stored carbon into the atmosphere.

Theikenmeer is a nature reserve in the north-west of Germany containing a peat bog and a lake. The peat bog has been drained to extract peat and due to nearby farming until the peat bog and the lake were completely dried out by 1977. It has been calculated that the Theikenmeer peat bog would release 2250 tons of CO₂ into the atmosphere every year while it’s dry [ 2 ]. Fortunately, volunteers started closing the drainage channels in the early 1980s. Today, the bog is wet again and bog plants and wildlife started returning into the area, allowing the bog to capture CO₂ instead of releasing it.

Theikenmeer’s peat bog belongs to a small percentage of natural peat bogs in Germany. However, over 90% of all peat bogs in Germany are still drained, causing almost 7% of Germany’s yearly greenhouse gas emissions [ 3 ]. Drained peat bogs only make up 0.3% of the world’s land surface, yet they emmit 5% of all anthropogenic greenhouse gases [ 1 ].

  • wifi_tethering open_in_new

    This post is public /blog/2022/02/dino-0.3-release/

  • chevron_right

    Dino 0.2 Release / Dino · Thursday, 12 November, 2020 - 18:00 · 3 minutes

Dino is a secure and open-source messaging application. It uses the XMPP (Jabber) protocol for decentralized communication. We aim to provide an intuitive, clean and modern user interface.

The 0.2 release adds message correction, improves the file upload functionality and provides more information about message encryption. Besides other smaller changes it also fixes a number of bugs.

Message correction


It is now possible to correct the last message you sent. You can access the function by hovering the message that you want to correct and then click the edit button that appears. If you’re a fan of shortcuts, you can also press the UP key. Last message correction has been the most frequently requested feature addition so far. We are happy about how it turned out and hope you are, too!

File sharing


You can now send files via drag and drop! Furthermore, you can now send Images by pasting them from your clipboard. As before, there is also still the option to press the “Send a File”-button.

Especially with those new ways of sending a file it is important to know that you are sending the right file to the right person. That’s why Dino now presents a confirmation dialog with a file preview and some file details.



It has already been possible to accept, verify or reject OMEMO keys. Now you can see the relevant information alongside each message: A small lock or seal symbol above a message indicates whether the message was encrypted by an accepted or a verified device, respectively. A red, open lock warns you in case your contact sends unencrypted messages in an encrypted conversation.

Unread, pending and more…


Dino now displays the number of unread messages in the conversation list. The color of the circle tells you whether the new messages triggered a notification (e.g. direct messages, mentions in channels).

Furthermore, Dino lets you know in case your message has not been sent yet by displaying “pending…” alongside the message.

In moderated channels, Dino will inform you if you don’t have the permission to write messages and offer the possibility to request that permission from a moderator.

Coral Reefs

Coral reefs are diverse and important ecosystems. Climate change and local human influences endanger coral reefs around the world. We named this Dino release “Mexican Caribbean Coral Reefs” to help spread the word about what needs to be done to preserve these unique ecosystems.

While coral reefs only occupy 0.1% of the ocean area, they are home to 25% of all marine species. Those reefs are made up of the calcium carbonate skeletons of corals. Corals grow very slowly and thus reefs require thousands of years to form. Many tropical corals live in symbiosis with tiny algae, which provide the corals with nutrients in exchange for shelter.

Climate change harms corals in two ways: First, it raises the ocean temperatures. Corals lose their algae in high water temperatures, which is called “bleaching”. Without the algae the corals starve. Secondly, the ocean absorbs parts of the increasing carbon dioxide amounts from the atmosphere. In water, CO₂ reacts to carbonic acid, which dissolves coral skeletons.

Many coral reefs are located in the shallow water near coasts and are thus highly affected by local human activities: Sediments and nutrients are washed into the ocean and deprive the corals of light; Overfishing can negatively affect the whole ecosystem; Destructive fishing using poisons or explosives harms the corals.

For example, the coral cover in the Mexican Caribbean Coral Reefs decreased by 60% between 1980 and 2016. This was caused by mass bleaching events due to increased water temperature, hurricane impacts, and an increased amount of sediment due to deforestation [ 1 ].

Various programs aim to protect individual coral reefs from local dangers. However, the ecosystem coral reef can only be preserved by also eliminating the global threat: Climate change. According to multiple studies, coral reefs only have a chance of survival if the global temperature increase is limited to 1.5°C [ 2 , 3 ]. Your actions have an impact.

  • wifi_tethering open_in_new

    This post is public /blog/2020/11/dino-0.2-release/

  • chevron_right

    Setting out for calls and conferences / Dino · Tuesday, 11 August, 2020 - 13:00

Video calls have become a widely used means of communication in personal and in business settings. Especially during the last months, people increasingly used video calls to keep in touch. Unfortunately, many turn to US-based, centralized and closed-source solutions that come with privacy and security issues.

Screen showing dinosaurs in a video conference

We are now starting to implement decentralized calls and conferences in Dino. As with the rest of the UI, we aim for a nice and simple user experience. The call features are planed to be implemented and published step-by-step over the next 12 months. Support for encrypted two-party calls that are compatible with Conversations should be ready by the end of this year or early next year. For conference calls, we are also looking into compatibility with the popular video-conferencing solution Jitsi Meet, that is also based on the XMPP protocol.

This work is made possible through contributions from the NGI0 PET Fund. The fund is managed by NLnet and dedicated to Privacy and Trust Enhancing technologies. It was established with financial support from the European Commission’s Next Generation Internet programme.

Logos of NGI0 PET, NLnet and European Commission
  • wifi_tethering open_in_new

    This post is public /blog/2020/08/setting-out-for-calls-and-conferences/

  • chevron_right

    Dino 0.1 Release / Dino · Wednesday, 29 January, 2020 - 17:00 · 3 minutes

We are thrilled to announce the first release of Dino: Version 0.1. This marks an important milestone of the development process that started three years ago and already combined work of 30 contributors, including 4 summer of code students and multiple development sprints.

Dino is a secure and open-source application for decentralized messaging. It uses the XMPP (“Jabber”) protocol and is interoperable with other XMPP clients and servers. We aim to provide an intuitive, clean and modern user interface.

Dino's Main Window

Motivation: Why Dino?

Chat applications like WhatsApp and Facebook Messenger are easy to use and thus were adopted by billions of people. However, they are closed-source and the companies behind them are frequently criticized for misuse of private data. Multiple messaging apps grew around the idea of providing a privacy-friendly alternative, for example Signal and Wire. While they provide encryption and release source-code, their users still have to rely on a centralized service and trust a single company.

XMPP is an open protocol for federated communication. There are lots of public servers that communicate with each other and anyone can host their own server. This makes it a great basis to write a privacy-friendly and decentralized messenger on. A number of clients already exist for the XMPP protocol, however Dino sets a different focus. Existing clients target tech-savvy power users. The XMPP ecosystem lacks a client that is enjoyable to use while providing the features people expect from a modern chat application. Dino fills that gap by aiming to be secure and privacy-friendly while at the same time providing a great user experience.


At first glance, Dino’s user interface is similar to what you might be used to from other popular messengers. On the left side your opened conversations are listed, ordered such that the latest messages are always on top. You can open new conversations or join channels with the ‘+’ menu.

Conversation with inline images and a file in Dino

Messaging and more

You can send messages to individuals as well as to private group chats and public channels. Dino can be used together with other clients simultaneously, allowing you continue the same conversation on your mobile phone as well as on your desktop. Messages you sent and received while Dino was offline are synchronized on start up.

Dino's message search with highlighted results

Message search

Dino supports sharing images and other files. It can transfer files via your server or directly to your contact, peer-to-peer and without size limitations.

An advanced message search allows you to search and filter your message history - globally or within one conversation. After looking through the results, you can jump to a message to read more of the context.

You can use multiple accounts in the same interface, allowing you for example to conveniently separate your work and private identities.

Security and Privacy

Dino's OMEMO Key Management Dialog

Security has been a focus for Dino development since the beginning. That’s why we support two end-to-end-encryption methods out of the box: The well-known encryption standard OpenPGP allows you to extend your Web-of-Trust from e-Mail to XMPP. The OMEMO double-ratchet encryption provides you with a modern encryption scheme with individual device trust that is widely used in the XMPP network.

We take your privacy seriously in every detail. For example you can keep Dino from informing the sender when you read a message, so they won’t see a double-tick on their messages. Dino allows you to configure all of its privacy features per contact: You can keep your best friends up-to-date while not sharing anything with strangers.

Fast and well integrated

Dino does not include a full browser stack with its large resource usage and potential of security issues. Instead it is a native desktop application meaning it is small and has a light footprint. Dino integrates nicely with the rest of your desktop applications and services.

Get Started

Once you created an XMPP account, you can contact people across the globally connected XMPP network. XMPP addresses are of the form . You can sign in with an existing account or create a new one!

  • wifi_tethering open_in_new

    This post is public /blog/2020/01/dino-0.1-release/

  • chevron_right

    End of the Google Summer of Code / Dino · Monday, 26 August, 2019 - 00:00 · 2 minutes

This Google Summer of Code was about adding peer-to-peer file transfers to Dino. Dino is an XMPP client, XMPP is decentralized instant messaging standard.

The work was mostly done in two larger pull requests. The first one, dino#577 , added a Jingle framework ( XEP-0166 ), the in-band-bytestream transport ( XEP-0047 , XEP-0261 ) and the Jingle file transfer protocol ( XEP-0234 ).

Jingle is a protocol for (mostly out-of-band) peer-to-peer connections between XMPP clients. It is designed to support multiple transport types, e.g. in-band bytestreams, connections via SOCKS5 proxies or direct IP connections. It provides support to send different kinds of data between clients, the two major users are file transfers (described below) and audio/video calls. All this is reflected in the code, the Jingle interface was designed to be extensible for more transport methods and different data types.

In-band bytestreams are a simple method of exchanging binary data between XMPP clients by sending base64 -encoded data in the XMPP stream via the server. It is a good fallback method in case no other transport works, but adds 33% overhead to the data sent.

Apart from the HTTP file upload specification, the Jingle file transfer protocol is another standard way of exchanging files between XMPP clients. For Dino (and also in Conversations ), this method is used transparently (using the same UI) for files larger than the upload limit of the HTTP upload server. This allows the user to benefit from both methods.

The work on this pull request was concluded by some interoperability testing with Conversations and Gajim, two other major XMPP clients.

The second pull request, dino#592 (not merged yet, currently on commit 6028fd1 ) added the SOCKS5 transport method for Jingle ( XEP-0065 , XEP-0260 ).

The SOCKS5 transport method allows XMPP clients to exchange data via a direct connection or via a XMPP-server provided SOCKS5 proxy. The direct transfer only works if one client can see the other client’s IP address and is not firewalled, which is mostly the case if both the clients are on the same private network. It is currently not implemented and is waiting for some libnice support for enumerating the local interfaces (see below). Instead, the data can be exchanged via a proxy reachable by both clients, determined by some candidate exchange.

Interoperability testing for the second pull request uncovered some old and new bugs in both existing clients and my implementation. Thanks to the Conversations developer for taking my bug reports seriously and responding very fast.

There were also a couple of other smaller pull requests which I’ll mention here:

  • dino#569 . Tiny fix for logging to a file.
  • dino#570 . Tiny typo fix, sorry for even mentioning. :o
  • dino#579 . Improvement around the error generation in response to certain XMPP messages.

In the course of the interoperability testing, I also opened a couple of issues on other XMPP clients: Conversations#3478 , Conversations#3500 , Conversations#3514, Conversations#3515 , Gajim#9784 .

As the next steps , after Google Summer of Code, I’ll implement the WebRTC transport method to get interoperability with XMPP browser clients that cannot open direct TCP connections to SOCKS5 servers. Additionally, one could implement audio/video calls on top of the current Jingle code.

At this point I’d like to thank my two mentors fiaxh and mar-v-in without whom this wouldn’t have been possible. They were quick to answer any questions that arose, about architectural design of the code, the XMPP standards or even just questions about Vala , the language Dino is written in.

Thanks to my mentoring organization, the XSF (XMPP standards foundation), as well, for the weekly meetings and generally the advice given therein.

  • wifi_tethering open_in_new

    This post is public /blog/2019/08/end-of-the-google-summer-of-code/

  • chevron_right

    Ninth and tenth week: Interoperability fun / Dino · Tuesday, 6 August, 2019 - 00:00 · 3 minutes

After finishing the SOCKS5 bytestreams transport for Jingle (S5B, XEP-0065 , XEP-0260 ), I was asked whether I had already done interoperability testing with other clients for the fallback to in-band bytestreams.

flow: […] which other transports do you support? How far has interoperability testing between different implementations be done?

hrxi: only socks5 and ibb, conversations and gajim both work fine

flow: […] did you also test the socks5 to ibb fallback?

hrxi: no, that doesn’t work yet

flow: uh, maybe you find the time to implement that in the remaining two weeks, or are there other plans?

I guess I should’ve seen it coming at this point. Here’s how the fallback should work, according to the Jingle SOCKS5 XEP ( XEP-0260#Fallback ), excluding acks and simplified (dropping a lot of elements that need to be present):

1. <jingle action="session-initiate"> <transport xmlns="j-s5b" /> </jingle>

2. <jingle action="session-accept"> <transport xmlns="j-s5b" /> </jingle>

3. <jingle action="transport-info"> <transport xmlns="j-s5b"> <candidate-error /> </transport> </jingle>

4. <jingle action="transport-replace"> <transport xmlns="j-ibb" /> </jingle>

5. <jingle action="transport-accept"> <transport xmlns="j-ibb" /> </jingle>

6. <open xmlns="ibb" />

First, the normal Jingle session initiation happens, the client offering a file sends a session-initiate including SOCKS5 proxy information and waits. Then, when the receiving user accepts the file, or if the receiving client automatically accepts the file based on some conditions, it sends a session-accept including its SOCKS5 proxy information.

In point 3, we start to deviate from the normal “happy path”; in order to test the fallback, I made Dino send no local candidates and skipped checking all of the remote candidates, leading to both clients sending a transport-info with a candidate-error , meaning that none of the candidates offered by the peer work.

Now (4), according to the XEP, the initiator (left side) should send a transport-replace to change the transport method to in-band bytestreams.

In 5, the responder accepts this change.

After getting this response, the initiator is supposed to open the in-band bytestream ( XEP-0261#Protocol flow ) to complete the negotiation.

It took a few tries until I had Dino-Dino fallback working. The other clients were also fun:

Dino → Conversations The best case. Fails in step 2, but only because of some minor problems, the block size negotiation doesn’t take into account what Dino sent. Dino asks for a block size of 4096 bytes, Conversation is only allowed to lower this value but sets the consensus to 8192 bytes. I ignored this and the fact that Conversations did not send a sid and got a working fallback. Conversations#3515 .

Conversations → Dino Fails in step 4, for some reason Conversations doesn’t send a transport-replace after the SOCKS5 transport failed. Conversations#3514 . EDIT Seems to be my mistake, couldn’t reproduce it when trying to test it with the Conversations developer.

Dino → Gajim Fails in a funny way, in step 5. Gajim responds to transport-replace with a session-accept . session-accept is only valid in response to session-initiate , so I don’t know how that happens. Some Conversations user already reported that issue. Gajim#9692 .

Gajim → Dino Gets stuck in step 6, Gajim doesn’t open the in-band bytestream even though it is the initiator. Gajim#9784 .

Of course I’m not sure that I diagnosed all of these issues correctly, these might be mistakes on my part and in my code, too. Let’s see how these issue threads develop.

EDIT And of course there was at least one mistake by me, Conversations → Dino seems to work.

  • wifi_tethering open_in_new

    This post is public /blog/2019/08/ninth-and-tenth-week-interoperability-fun/

  • chevron_right

    Eighth week: Standards / Dino · Thursday, 25 July, 2019 - 00:00 · 2 minutes

Sometimes, XEPs are really imprecise or even lack information about some interactions. Most of the time, it’s about error handling where it’s not really specified what to do in error cases, as the XEP mostly deals with the “happy path” when everything is working.

This week, I tried to get SOCKS5 bytestreams (S5B, XEP-0065 , XEP-0260 ) working for file transfers. Most of the stuff simply worked after implementing the S5B transport, since the Jingle module was offering a transport-agnostic bytestream to the outside world, or in this case Jingle file transfers XEP-0234 . However, file transfers with Conversations got stuck at 100%. After some debugging, I found out that Conversations doesn’t close the SOCKS5 connection after sending the file. Since I relied on the the peer closing the connection after sending the complete file, this led to Conversations waiting for me to acknowledge the file transfer and me waiting for Conversations to close the connection. I opened Conversations#3500 about this inconsistency.

Reading into XEP-0234 , I tried to find out how to detect the end of the file transfer. The two relevant sections I found were

Once a file has been successfully received, the recipient MAY send a Jingle session-info message indicating receipt of the complete file, which consists of a <received/> element qualified by the 'urn:xmpp:jingle:apps:file-transfer:5' namespace. The <received/> element SHOULD contain 'creator' and 'name' attributes sufficient to identify the content that was received.

(8.1 Received)


Once all file content in the session has been transfered, either party MAY acknowledge receipt of the received files (see Received) or, if there are no other active file transfers, terminate the Jingle session with a Jingle session of <success/> . Preferably, sending the session-terminate is done by the last entity to finish receiving a file to ensure that all offered or requested files by either party have been completely received (up to the advertised sizes).

(6.2 Ending the Session) (link might die in the future, has a weird anchor).

I wasn’t able to find the relevant information, so I looked at Conversation’s source code to find out how it determines when the file transfer is complete. Turns out it’s simply checking whether it has already read as many bytes as the integer in the <size> field in the initial file offer. Adding that as a “filetransfer complete” condition, I can now receive files from Conversations. This however, is not a general solution, as the <size> field only SHOULD be present when offering a file, so we can’t rely on it being available when receiving files over Jingle.

If anyone knows what the correct way to detect a completed file transfer is, please tell me.

  • wifi_tethering open_in_new

    This post is public /blog/2019/07/eighth-week-standards/

  • chevron_right

    Seventh week: Socks 5 file transfer / Dino · Monday, 22 July, 2019 - 00:00 · 1 minute

The blog posts have slipped somewhat, last blog post covering two weeks. Let’s try to fix that.

The next step for file transfers was to implement more Jingle transport methods. Currently, only in-band bytestreams are implemented as transport methods. The inefficiencies have been discussed already, it mostly boils down to the fact that in-band bytestreams exchange base64-encoded data over the XMPP stream.

The next transport method to be implemented are SOCKS5 bytestreams (S5B, XEP-0065 , XEP-0260 ). They can work in direct (peer-to-peer) or mediated (via a proxy server) mode, depending on whether the clients are visible to each other or whether they want to share their IP address.

SOCKS5 is a relatively simple protocol, it can basically be implemented after reading its Wikipedia page : After establishing a TCP connection to the proxy server, the client sends its available authentication methods, the server chooses one, the authentication happens. After successful authentication, the client specifies where it wants to connect to and the server acks that. Thereafter, one can use the TCP connection as if it was connected to the previously specified IP address, sending and receiving data as if one were connected directly.

SOCKS5 bytestreams use this protocol in a somewhat peculiar way. Instead of specifying IP addresses to connect to, the SOCKS5 proxy more or less acts like a rendez-vous point. Both sides that want to use the proxy as mediator connect to it, and specify a common but somewhat random fictional domain name to connect to. After one of the clients “activates” the connection via XMPP, data can flow between these clients.

In theory, this is just another Jingle transport method, so one wouldn’t have to modify the Jingle code to add it. However, since we only have one transport method yet, the abstractions are probably not quite right yet: For example, S5B needs support for <jingle action="transport-info"> , which IBB didn’t.

Let’s see how this works out.

  • wifi_tethering open_in_new

    This post is public /blog/2019/07/seventh-week-socks-5-file-transfer/