7.8 KiB
KryptEY
KryptEY was created by mellitopia and amnesica.
We implemented a stand alone android keyboard, KryptEY, which enables E2EE encryption of single messages on any Android messenger. It is based on the Simple Keyboard. The Android version of the Signal Protocol is used for the E2EE functionality.
The keyboard provides the functionality to encrypt and decrypt messages, is independent of a messenger app and does not require a server for the key exchange. The keyboard includes a separate text field for entering the message that is to be encrypted. After selecting the receiver, the message is sent to the text field of the used messenger and then sent to the chat partner as usual. The chat partner copies the message to the clipboard, the application recognises the KryptEY message as well as the sender and offers the option to decrypt the ciphertext message. The decrypted message is displayed in the KryptEY text field and saved in the message history. Further, chat partners can be created and deleted through the application and their security number can be verified by comparing it on both end devices. Encrypted and decrypted messages are stored in a message history for later viewing and there is a Q&A section that helps with questions about the keyboard and its functionalities.
The elliptic curve X25519 with SHA-512 is used in the X3DH Key Agreement Protocol from the applied Signal library. The hash function SHA-256 is used for the various chains and AES-256 with CBC ( Pkcs#7) is used for the encryption of the messages. SHA-512 is also used to generate the fingerprint, the representation of the public key used for encryption.
Initialization
After installing the app, the Signal Protocol is initialised on the device. For this purpose,
a SignalProtocolAddress
consisting of a randomised UUID and an arbitrary device id is created.
Further, an identity key, two one-time prekeys and a signed prekey are created. From this
information, various stores are created to man- age the protocol: the IdentityKeyStore
, PreKeyMetadataStore
, PreKeyStore
, SenderKeyStore
, SessionStore
, SignalProtcolStore
, and
the SignedPreKeyStore
. All protocol information is stored serialised in the application’s
SharedPreferences. The Jackson library is used for this purpose. All the information together forms
an account on the device, with the SignalProtocolAddress
identifying the user.
In addition, there are four different message types in KryptEY for exchanging keys and ciphertext messages between chat partners.
PreKeyResponse
: to send thePreKeyBundle
(Invite message)PreKeySignalMessage
: to send a ciphertext andPreKeyBundle
after establishing the session on one’s side.SignalMessage
: to send a ciphertextPreKeyResponse
+SignalMessage
: to send a ciphertext with newPreKeyBundle
information to update the session
Session Establishment and Key Management
To exchange messages, a session must first be initialised on both end devices. If Bob wants to
communicate with Alice, Bob needs Alice’s PreKeyBundle
to establish the session on his side. Alice
sends this via an invite message, which contains her PreKeyBundle
data (PreKeyResponse
). This
allows Bob to add Alice as a contact within the keyboard and establish a session on his side. Bob
can now send an initial encrypted message to Alice. Since Alice has not yet initialised a session
with Bob, this message is a PreKeySignalMessage
and contains additional information besides the
actual ciphertext message so that Alice can establish a session with Bob. After Alice has also added
Bob as a contact and created a session, she can now decrypt the message Bob sent. At this point,
both parties have established a session and can send messages to each other. These messages
are SignalMessages
.
The one-time prekeys used to establish the sessions are renewed after each use, while the identity
key is never renewed. After 30 days the signed prekeys are rotated. The old signed prekey is deleted
after 2 days. After such rotation, an updated PreKeyBundle
is sent together with an encrypted
message with which the receiver, e.g. Bob, can update his session with Alice (PreKeyResponse
+SignalMessage
). This combination of messages eliminates the need for a separate reading of the
renewed KeyBundle information. For the user, the message appears like a normal SignalMessage
. The
session management with the manually created PreKeyResponse
is necessary, because no server is
used for the exchange of the PreKeyBundles
.
In addition to the PreKeySignalMessage
and SignalMessage
, which are also used by the Signal app,
KryptEY uses the PreKeyResponse
and PreKeyResponse
+SignalMessage
. As previously mentioned,
these are necessary to guarantee the Signal Protocol without the use of a server. Further, in the
Signal app 100 one-time prekeys are created, while in KryptEY only 2 one-time prekeys are created.
These one-time prekeys are replaced after each use, which eliminates the need for time-consuming key
management of 100 one-time prekeys. Also, unlike Signal, KryptEY does not use telephone numbers to
identify users. Instead, randomised UUIDs are used. This could contribute to an increase of the
privacy of the users, since no telephone numbers are used to identify the users.tween chat partners.
MessageEnvelope and Message Encoding
To send a message, all information is collected in a MessageEnvelope
and then sent as plain JSON
or hidden in a decoy message. Depending on the message type, this envelope contains
the PreKeyResponse
, the CipherTextMessage
(PreKeySignalMessage
or SignalMessage
) as a byte
array, the type of the CipherTextMessage
(PreKeySignalMessage
or SignalMessage
), a timestamp
and the SignalProtocolAddress
.
There are two different encoding modes in KryptEY, raw mode and fairytale mode. Messages can be sent as a JSON array (raw mode) or hidden in a decoy message (fairytale mode) to make the conversation look inconspicuous. In the latter, the encrypted message is hidden in invisible, non-printable Unicode characters. To keep the message size as small as possible, the JSON is minified, i.e. all spaces and paragraphs are removed and the key values of the JSON are replaced by abbreviated key values, e.g. ”preKeyResponse” becomes ”pR”. After that, the string is compressed with GZIP and converted into a binary string. When converting to invisible Unicode characters, 4 bits are always mapped to an invisible Unicode character like U+200C (ZERO WIDTH NON-JOINER). There are 16 invisible Unicode characters to choose from, covering all combinations from 0000-1111. The invisible Unicode string is then placed after an arbitrary sentence from one of the two available fairytales Cinderella and Rapunzel and can be sent to the application. After receiving, the invisible Unicode characters are extracted from the message, converted to a binary string, decompressed, and deminified. Then the message can be read by the app. The invisible characters are included in the transmitted messages, which can cause problems in some messengers, unfortunately (see Limitations in the README).
Additional Information
The keyboard only needs the ”VIBRATE” permission to enable vibration after key press. Unlike the Android Open Source Project keyboard , the application does not require any sensitive permissions such as access to external storage or contacts. Internet access is also not needed. At least Android 8.0 (API 26) is required and the application has been licensed with GPL-3.0.