- Chat application with non blocking threads
- Rivest-Shamir-Adleman encryption (RSA) and key handshake
- OAEP
- Nazar Mykhailischuk - Miller–Rabin primality test, RSA
- Nikita Lenyk - chat structure, OAEP, RSA
The project is build within five layers
-
Transport Layer - communication layers between sockets
-
Security Layer - RSA encryption with OAEP padding
-
Application Layer - Client and server side implementations
-
Protocol Layer - Message Integrity test and serialization
-
Message Transport Layer - Handles the reliable messages over TCP sockets
The FrameLayer class is responsible for adding a Header, which allows to set a dynamic buffer size when receiving messages.
-
Header format: 4 byte unsigned int MSB
-
Pack method adds length prefix of the message payload
! The frame Layer exactly after RSA + OAEP encryption
Uses RSA - asymmetric encryption with several features
-
Prime Number Generation: Uses Milller-Rabin primality test to generate secure primes
-
Prime Numbers Separation: Ensures
$p$ and$q$ differ by at least 256 bits -
Standart public exponent is set to
$e = 65537$
As the plain RSA is deterministic. Sercurity Layer uses OAEP (Optimal Asymmetric Encryption Padding). It adds random data to the original message before encryption, making each encrypted message unique. This prevents attacks based on the analysis of ciphertexts and other vulnerabilities.
OAEP - transforms a message
-
Input data block
-
Message
$m$ of length$\text{mLen}$ -
Maximum message length is
$k - 2\times\text{hLen} - 2$ , where:$k$ is the RSA modulus byte length:$k = \lceil\log_256(n)\rceil$ $\text{hLen}$ is the hash function output length (32 bytes for SHA-256)
-
-
General Data Block
-
Compute
$\text{lHash} = \text{Hash}(L)$ where$L$ is an optional label (usually empty) -
Create padding string
$\text{PS}$ of zeros:$\text{PS} = 0^{k-\text{mLen}-2\times\text{hLen}-2}$ -
Construct
$\text{DB} = \text{lHash} \mathbin\Vert \text{PS} \mathbin\Vert 0x01 \mathbin\Vert m$
! This will be first separator block
-
-
Random seed generation
$r$ - Generate random seed
$r$ of length$\text{hLen}$ bytes
- Generate random seed
-
Mask generation MGF1
-
Compute
$\text{dbMask} = \text{MGF1}(r, k-\text{hLen}-1)$ -
Create
$\text{maskedDB} = \text{DB} \oplus \text{dbMask}$
-
-
Masking seed
-
Compute
$\text{seedMask} = \text{MGF1}(\text{maskedDB}, \text{hLen})$ -
Create
$\text{maskedSeed} = r \oplus \text{seedMask}$
-
-
Final Encoding:
$\text{EM} = 0x00 \mathbin\Vert \text{maskedSeed} \mathbin\Vert \text{maskedDB}$
-
RSA Encryption:
- Convert
$\text{EM}$ to integer$m$ Compute$c = m^e \mod n$
- Convert
-
Creates the message hash with fixed-size(32 bytes) by SHA256 of the message payload.
-
When sending the message: Includes:
-
4-byte Header containing the digest length
-
The digest (SHA256 hash)
-
The actual message data
-
-
Output [digest_length (4-bytest)][digest (32 bytes)][payload]
-
Integrity test
-
Get the length from the Header
-
Extract the original digest
-
Extract the payload
-
Recalculate the hash with SHA256 of received payload
-
Compare the received hash with the new one from step 4
-
If the match the message integrity is passed
! The hash comparison uses HMAC module
compare_digestto avoid timing atacks -
User types message in CLI
Text is converted to bytes and wrapped in SecureMessage with SHA-256 digest
Message is serialized (digest length + digest + payload)
Serialized message is encrypted using server's public key with RSA-OAEP
Encrypted data is framed (length header + content)
Frame is transmitted over TCP socket
Server receives encrypted data with Header
Header is parsed to extract encrypted payload
Payload is decrypted using server's private key
Decrypted data is deserialized to SecureMessage
Integrity is verified by checking SHA-256 digest
Server processes message and prepares broadcast
Server creates new SecureMessage with formatted text
For each client connection:
Message is serialized
Serialized data is encrypted with client's specific public key
Encrypted data is framed and sent to that client
Client receives encrypted data with Header
Header is parsed to extract encrypted payload
Payload is decrypted using client's private key
Decrypted data is deserialized to SecureMessage
Integrity is verified by checking SHA-256 digest
Message is displayed to user
OAEP
-
https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding
-
https://medium.com/asecuritysite-when-bob-met-alice/so-how-does-padding-work-in-rsa-6b34a123ca1f
-
https://www.freecodecamp.org/news/the-cryptography-handbook-rsa-algorithm/?utm_source=chatgpt.com
MGF1 (mask generation)
Miller–Rabin primality test
-
https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
-
https://www.youtube.com/watch?v=8i0UnX7Snkc&ab_channel=NesoAcademy
Padding Methods
RSA
PKCS