• chevron_right

      Setting out for calls and conferences

      pubsub.movim.eu / 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

      dino.im /blog/2020/08/setting-out-for-calls-and-conferences/

    • chevron_right

      Dino 0.1 Release

      pubsub.movim.eu / 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.

    Features

    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 user@example.com . You can sign in with an existing account or create a new one!

    • wifi_tethering open_in_new

      This post is public

      dino.im /blog/2020/01/dino-0.1-release/

    • chevron_right

      End of the Google Summer of Code

      pubsub.movim.eu / 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

      dino.im /blog/2019/08/end-of-the-google-summer-of-code/

    • chevron_right

      Ninth and tenth week: Interoperability fun

      pubsub.movim.eu / 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

      dino.im /blog/2019/08/ninth-and-tenth-week-interoperability-fun/

    • chevron_right

      Eighth week: Standards

      pubsub.movim.eu / 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)

    and

    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

      dino.im /blog/2019/07/eighth-week-standards/

    • chevron_right

      Seventh week: Socks 5 file transfer

      pubsub.movim.eu / 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

      dino.im /blog/2019/07/seventh-week-socks-5-file-transfer/

    • chevron_right

      Fifth and sixth week: File receiving

      pubsub.movim.eu / Dino · Tuesday, 9 July, 2019 - 00:00

    In the last two weeks, file receiving over Jingle has been implemented. This means that basic Jingle file transfers are available in Dino now (at least once the pull request #577 has been merged).

    As predicted by the Jingle implementation gist , this was actually a bit more than I would have guessed – you basically have to implement the Jingle and file transfer protocol again, but this time from the other side. Doing so involved some refactoring of the original code in order to fit better with Dino’s internals. I moved the code from signal-style callbacks to async IOStream s .

    • wifi_tethering open_in_new

      This post is public

      dino.im /blog/2019/07/fifth-and-sixth-week-file-receiving/

    • chevron_right

      Fourth week: Some UI integration

      pubsub.movim.eu / Dino · Thursday, 27 June, 2019 - 00:00

    File sending over Jingle (with in-band-bytestream transport) has now been integrated into the UI. This has fortunately been quite easy as Dino already had support for file sending, via HTTP uploads. Thus I only needed to hook into the existing UI to also offer Jingle file transfers. This means that now you can click on the “attach” paper clip to send a file. Since prioritization of different transport methods and file receiving haven’t been implemented so far, these changes aren’t in the master branch yet.

    Prioritization is important so that HTTP file uploads are preferred where possible (file small enough, server supports it): Jingle file transfers only work to a single target and only when it is online at the same time as the sender.

    Since the ability to receive files via Jingle can also be reasonably expected if the client supports sending them, we basically have two blockers for merging.

    Screenshot of Dino showing the paper clip button and a lot of file transfers

    Screenshot of Dino showing the paper clip button and a lot of file transfers

    Above you can see the chat window after some testing. ;)

    • wifi_tethering open_in_new

      This post is public

      dino.im /blog/2019/06/fourth-week-some-ui-integration/

    • chevron_right

      Third week: Interoperability testing

      pubsub.movim.eu / Dino · Tuesday, 18 June, 2019 - 00:00 · 1 minute

    I managed to get the basic in-band bytestream file transfers working. It still doesn’t have any user interface, that’s depending on a project by my mentor. For now, it’s simply triggered by a hardcoded target JID that gets a file transfer when it sends a presence.

    After finishing the proof of concept, I added some error handling and did some code cleanup. With that done, I did some interoperability testing. With Gajim , the file transfers now worked well, so I moved on to test with Conversations . Here, something funny happened, my Dino code sent (abbreviated for brevity):

    <iq type='set'>
      <jingle action='session-initiate'>
        <content>
          <description xmlns='urn:xmpp:jingle:apps:file-transfer:5'>
          </description>
          <transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='4096' />
        </content>
      </jingle>
    </iq>
    

    And Conversations responded:

    <iq type='set'>
      <jingle action='session-accept'>
        <content>
          <description xmlns='urn:xmpp:jingle:apps:file-transfer:5'>
          </description>
          <transport xmlns='urn:xmpp:jingle:transports:s5b:1'>
            <candidate host='146.255.57.229' type='proxy' jid='proxy.jabber.ccc.de' port='5224' />
          </transport>
        </content>
      </jingle>
    </iq>
    

    In essence, my Dino code asked to open a Jingle session for a file transfer, using in-band-bytestreams as the transport. Then, Conversations responded that it accepts my offer of Socks 5-based Jingle transport for the file transfer, accepting an offer I didn’t make. I think this is a violation of the Jingle XEP ( XEP-0166 ): If the other party wants to negotiate a different transport, it should probably use the transport-replace Jingle action. I created an issue ( Conversations#3478 ) which was quickly resolved. I have yet to test the fix, I don’t have a development setup for Conversations yet.

    The in-band bytestream file transfers I tested were quite slow (<2KB/s), probably some rate-limiting of the servers, I didn’t investigate furtherly.

    • wifi_tethering open_in_new

      This post is public

      dino.im /blog/2019/06/third-week-interoperability-testing/