AES-256 encryption. Diffie-Hellman 2048-bit handshake. Zero bytes in the clear between your phone and our servers. Here is how.
The japap protocol is designed to prevent third parties from accessing the plaintext messages exchanged between client and server. Even if a device's security is compromised, an intruder cannot exploit that breach to decrypt messages.
A mobile messaging protocol must keep three promises at once: encrypt every byte, hold up on an intermittent connection, and come online instantly on a phone just out of airplane mode. Here is how japap keeps all three.
The algorithms used during session establishment are RSA 2048 and AES-256. Once the session is established, every message is encrypted with AES-256-CBC under a derived key, unique for each message.
japap relies exclusively on standard, published cryptographic algorithms, battle-tested by twenty years of public scrutiny. No homebrew crypto.
Lets two devices that have never spoken derive a shared secret without ever transmitting it. The key stays on your devices.
Protects the key exchange phase from any interception. Diffie-Hellman parameters travel only inside an RSA envelope.
Encrypts every message with a uniquely derived key. Two identical messages produce two completely different ciphertexts.
Authenticates every message sent. A single altered byte is enough to have the frame rejected. Impossible to forge without the key.
Six terms recur throughout this document. Here are their precise definitions.
Uniquely identifies each message within a session. Prevents replay attacks.
The last 128 bits of the SHA-1 of the message to encrypt (external header excluded). Used to derive the AES key set.
A key shared between client and server, created during session establishment. It is never transmitted over the network.
32 bytes of key and 16 bytes of initialization vector, used for AES-256-CBC. Derived per message.
Prepended to the encrypted message. Contains the session key identifier (8 bytes) and the message key (16 bytes).
The last 64 bits of the SHA-1 of the session key. Lets the server locate the key used to encrypt a message.
A session is created the first time the app is opened or after the user logs out. The algorithms used are RSA 2048 and AES-256. Before the session is established, some messages travel in the clear — but an intruder cannot do anything with them.
The client sends the server a randomly generated 128-bit nonce. This nonce identifies the client for the duration of the exchange. After this step, it is known to both parties.
The server returns: the client's nonce, its own 128-bit nonce, an integer pq (product of two odd primes) and a fingerprint of its RSA public key. The (client nonce, server nonce) pair identifies the couple for the whole exchange — an intruder cannot spin up a parallel session with the same parameters, since a fresh server nonce is generated for every attempt.
The client decomposes pq into its prime factors p and q. At this point, the Diffie-Hellman exchange can begin.
The client generates a new random 256-bit nonce, builds a message m containing pq, p, q, the nonce pair and this new nonce, then encrypts it with the server's RSA public key as shown below. After this step, the new nonce is known only to the client and the server.
rand pads $m_{1}$ to 255 bytes.
An intruder can intercept this request and replace it with their own, but they would have to regenerate their own new nonce without ever being able to decrypt m₁. Since every subsequent message contains the hash of that new nonce, the values will diverge on the client side and be rejected at verification. The interception simply causes the session to fail on the client — nothing exploitable.
The server replies with the nonce pair and an AES-256 encrypted message containing the last 128 bits of the SHA-1 of the new nonce, the nonce pair, an integer g, a 2048-bit prime p, and g_a. The client knows for certain the reply comes from the server, since it is encrypted with a key derived from the new nonce.
where $a$ is a 2048-bit integer known only to the server.
The client picks b, a random 2048-bit integer, and sends the server the nonce pair along with an AES-256-CBC message containing g_b.
The session key is computed independently on both sides. The two results are mathematically identical.
This 2048-bit key is never transmitted over the network.
The last 64 bits of the SHA-1 of the session key serve as a public identifier, letting the server locate the correct key for each incoming message.
End of the process. All messages may now be exchanged securely, following the structure described below.
Every message exchanged after session establishment is made of three blocks. Here is what an observer on the wire sees — and what they cannot.
The session key (2048 bits) and the message key (128 bits) are used to compute the AES key set applied to a message. The AES key and initialization vector never travel over the network; each endpoint recomputes them from the same algorithm.
The 48-byte result splits into 32 bytes of AES key and 16 bytes of initialization vector. When the data length is not a multiple of 16 bytes, random padding is appended before encryption.
Beyond the primitives and their composition, japap guarantees you three fundamental properties, mathematically verifiable.
Only the holder of the session key can decrypt the content. Without that key, AES-256 in CBC mode is considered beyond the reach of any reasonably accessible computing power.
Any modification of the ciphertext — even a single byte — produces a corrupted message whose message key no longer matches. The frame is rejected before it reaches business logic.
The message key can only be produced by a device holding the session key. The server therefore knows each message comes from an authenticated client, with no possible ambiguity.
Our security team answers every question. Researcher, integrator, curious user: write to us, we reply.