-
Notifications
You must be signed in to change notification settings - Fork 56
_GSoC 2019 E2EE final evaluation
*libQMatrixClient was renamed to libQuotient
Name: Alexey Andreyev
E-mail: yetanotherandreyev@gmail.com
Matrix: @aa13q:matrix.org
Idea: Adding end-to-end encryption to more clients
GSoC project page: link
Mentors: Alexey Rusakov, Hubert Chathi
Contribution: libQuotient GSoC E2EE PRs list
The project aimed at adding end-to-end encryption to libQuotient for future support in Qt/libQuotient-based client like Quaternion and Spectal, or even Telepathy IM.
Regarding my initial proposal, I’ve completed tasks enough for message receiving, and not finished tasks related to message sending.
Focused on libQuotient, I've also added changes to Quaternion client to support the proposed API and test the results. I've reused libQtOlm, which is a Qt wrapper to the matrix olm library and contributed to provide better compatibility during its building and deployment. This also required to dive into the olm library itself and provide minor patch for the olm CMake files too.
So, the basic structure of the project changed a bit, libQtOlm was added as a dependency to support libolm:
+--------------------------------------------+
| Quaternion/Spectral/Telepathy|Tank/etc |
+------------------+ +--------------------------------------------+
| CS API | <----> | libQuotient |
+------------------+ +-------------------------------+------------+
|Synapse homeserver| | Qt | libQtOlm |
+------------------+ +--------------------------------------------+
| libolm |
+------------+
During the coding period, I've resorted to the specification, the guide and the last year GSoC python implementation actively. And added minor fix for the documentation about names constants at the documentation examples.
After sorting it out with the additional dependencies, I've focused on receiving m.room.encryption
event properly to detect additional megolm properties such as rotation criteria: rotation_period_msgs
and rotation_period_ms
. After the contribution, I've got full EncryptionEvent
support.
The next thing that was introduced is the EncryptionManager
class, which provides methods to work with the olm account. EncryptionManager
gives access to QtOlm::Account
field from the QtOlm wrapper of the olm library. EncryptionManager
was also implemented to handle all the device-specific initialization, such as handling targetKeysNumber
and methods like uploading device and one-time keys, olm session decryption. To support saving olm account after application restarts, additional option AccountSettings::encryptionAccountPickle
was introduced.
Next task was uploading device keys and one-time keys using EncryptionManager
, which required attention to the request structure and fields. After that, it was possible to upload identity and one-time keys during successfull connection to the server.
The result of the iteration was provided as pull request for a review. Quotient and Spectral clients successfully uploaded device keys, while one-time keys required additional fixes during actual decryption later.
The note at This Week In Matrix were also provided.
Next step was to implement EncryptedEvent
support. After the additional changes to the libQtOlm and olm to support in-tree building, I've dived into the documentation to support encrypted messages, found minor issue at the example and fixed it at the docs and the library.
@kitsune provided recommendations on how to organize messages decryption on-the-go without storing them decrypted to avoid security and architecture problems. The EncryptedEvent
event type is used when sending encrypted events. It can be used either within a room (in which case it will have all of the Room Event fields), or as a to-device event. The encrypted payload can contain any message event. However, for most of the cases, the message event is the room message event. And even for the to-device events, the context is for the room. So, to simplify integration to the timeline, EncryptedEvent
is a RoomEvent
inheritor. Strictly speaking though, it's not always a RoomEvent
, but an Event
in general. It's possible because RoomEvent
interface is similar to Event
's one and doesn't add new restrictions, just provides additional features. This was also referenced at the code implementation.
The iteration with draft EncryptedEvents
implementation was provided as a PR. @kitsune introduced new logging categories and fixed memory leaks and dangling pointers after that.
Looking at python implementation as a reference and implementing similar logic, I've started to realize better how the things work, how olm session is used to share the keys and initialize the megolm session at the room. And realized what parts are missing to implement receiving of the encrypted messages.
During the debugging, I've fixed EncryptionManager
initialization place, implemented RoomKeyEvent
to support olm session initialization, added handling of the to-device messages and fixed megolm inbound session decryption logic. As a result, I've provided actual working code for receiving messages that could be reused at the project. I've also provided missing Arch Linux packages for the community to test it with my native environment too.
The result were introduced as final PR.
Additional contribution were provided to test results with Quaternion: aa13q-e2ee branch
Talking about future work, I'm going to sync it with the libQuotient project board. Next steps are:
- Managing devices list for users in the room
- Sending encrypted messages
While olm account management architecture and device_one_time_keys_count
sync data handling is here, such tasks as session management after a restart and device verification still requires additional efforts. After that encrypted attachments support and key backups could also be added.
To take part in the Google Summer of Code project was my dream. I'm very happy I've managed to took part this year, since it was the last year of my study, while I'm probably not very satisfied with my personal results.
From the beginning of the project, I've realized I'm very lucky since I've got all the chances to provide perfect results. @Kaffeine helped me a lot with my TelepathyIM contribution. He helped me to evolve my CMake, git and Qt/C++ skills and that's how I've started contributing to the libQuotient before GSoC. After that, it turns out that I've accepted and received even two mentors. @uhoreg from the Matrix team, who helped me with End-to-End Encryption logic and olm/megolm understanding. And @kitsune from the Quotient project, who helped me a lot with the code review, with the architecture decisions and the library logic, and even with the time management (he was the one who watched carefully about my results). The last year GSoC python implementation and guide from @Zil0 were also here, and it turns out that Spectral developer @BHat provided QtOlm wrapper right before GSoC stated. However, time management was my weak point, where I've made key mistakes, such as poor combination with my regular part-time job. I definitely should have reserved a small vacation at least for the final period of the project to handle tasks better. In the end, I've managed to debug the mistakes and provided encrypted messages receiving that could already be used at the clients. Also, I evolved my skills and dived into the megolm E2EE subject. I'm willing to continue my contribution to develop libQuotient as full-featured Qt-based Matrix library.
In general, I am not disappointed. I'm wishing luck to all the future students who are reading this. I'm happy to receive support and contribute to an international open project not only for myself, but also for the other developers and users.