Direct Message
Direct Message introduces a secure way for two users to publish encrypted messages to each other within the Texudus ecosystem. Direct messages (DMs) leverage public/private key cryptography to ensure that only the intended recipient can read the message. This feature also enables metadata to specify a user's public key and file where the direct messages are stored. It have compatibility with encryption protocol (Curve25519).
Quickstart
1. Create Public and Private Key
openssl genpkey -algorithm X25519 -out private_key.pem
openssl pkey -pubout -in private_key.pem -out public_key.pem
2. Public Key Declaration
A new metadata field named public_key must be present in the user's texudus feed. This field should contain the user's Public Key in Base64 format.
Example:
base64 -w 0 < public_key.pem > public_key.b64
The output, for example, will be MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=.
Set the public_key to the Texudus feed metadata:
# nick = example
# url = https://example.com/texudus.txt
# public_key = MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=
3. Encryption of DMs
Direct messages must be encrypted using the recipient's public key to ensure confidentiality. Any modern cryptographic library supporting EC (libsocium, nacl, Go's box/secretbox, etc.) public/private key encryption can be used for this purpose.
curl https://recipient.com/texudus.txt | grep public_key | cut -d' ' -f4 | base64 -d > recipient_public_key.pem
openssl pkeyutl -derive -inkey sender_private_key.pem -peerkey recipient_public_key.pem -out shared_key.bin
echo -n "My direct message" | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -out message.enc -pass file:shared_key.bin
base64 -w 0 < message.enc > message.enc.b64
cat message.enc.b64
The output, for example, will be 1234567890abcdef=.
4. DM Syntax
Direct messages must explicitly target the recipient using the format: datetime + \t + receiver url + encrypted_message.
Example:
2025-01-18T18:20:00+01:00 https://example.com/texudus.txt 1234567890abcdef=
You must save it in a new file, for example, dm.txt. The direct messages are isolated from the rest of the feed, and the client should be able to parse them separately.
Add the meta dm_feed with the URL of the feed where the direct message is stored.
# nick = example
# url = https://example.com/texudus.txt
# public_key = MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=
# dm_feed = https://example.com/dm.txt
Detailed Explanation
Public Key Metadata
The mandatory public_key metadata field allows feed authors to publish their public key. Clients can use this key to encrypt messages for the feed author. The key must be a string. This ensures that only the author can decrypt the message using their private key.
# public_key = MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=
DM Feed Metadata
The mandatory dm_feed metadata field specifies the URL of the feed where direct messages are stored. This allows clients to fetch and parse direct messages separately from the main feed.
# dm_feed = https://example.com/dm.txt
Encryption Process
When sending a direct message:
1. Retrieve the recipient's public key from their public_key metadata.
2. Encrypt the plaintext message using the public key.
3. Encode the ciphertext (Base64).
4. Add the new line to the texudus feed with the recipient's nick and url followed by the encrypted message.
Example Workflow
Let's assume two users, alice and bob, want to communicate privately. Alice wants to send a direct (she likes to encrypt the message) and Bob wants to read it (decrypt the message).
1. Key Generation
Alice and Bob each generate a public/private key pair using Curve25519 algorithm with openssl:
openssl genpkey -algorithm X25519 -out alice_private_key.pem
openssl pkey -pubout -in alice_private_key.pem -out alice_public_key.pem
openssl genpkey -algorithm X25519 -out bob_private_key.pem
openssl pkey -pubout -in bob_private_key.pem -out bob_public_key.pem
2. Setup
Alice declares her public key in her texudus.txt metadata:
Open alice_public_key.pem and copy the key.
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=
-----END PUBLIC KEY-----
The public key is the string between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----: MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=.
And paste it in the public_key field.
# nick = alice
# url = https://alice.example.com/texudus.txt
# public_key = MCowBQYDK2VuAyEAvBvdsHgzmIiRL9Mjb4fVrbSQGn4Q/m9p7XZCUDj5liI=
# dm_feed = https://alice.example.com/dm.txt
Bob does the same in his feed:
# nick = bob
# url = https://bob.example.com/texudus.txt
# public_key = MCowBQYDK2VuAyEALBmCrrkDzfUbo3CBBvHB8R9CCD3U88xzQcohBZRGMzE=
# dm_feed = https://bob.example.com/dm.txt
3. Encrypting the Message
Bob wants to send a private message to Alice. Using Alice's public_key, Bob encrypts his message using Openssl:
1. First, Bob retrieves Alice's public key
curl https://alice.example.com/texudus.txt | grep public_key | cut -d' ' -f4 > alice_public_key.pem
2. Calculate the share key
Bob use his private key and Alice's public key to calculate the shared key:
openssl pkeyutl -derive -inkey bob_private_key.pem -peerkey alice_public_key.pem -out shared_key.bin
Then, Bob encrypts the message using the shared key. The message is storage in message.enc:
echo -n "Hi Alice, let's meet tomorrow at 5 PM!" | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -out message.enc -pass file:shared_key.bin
3. Bob encodes the encrypted message in Base64
base64 -w 0 < message.enc > message.enc.b64
Check message.enc.b64 for the encrypted message: U2FsdGVkX1+mVLsw62BUyjcjnAVtU/EP04gS9GuTsD8xW66BH3V+kb828lMswrDntCtKgauLDZEDRCmpAo3lcQ==
This will be the string of the direct message.
3. Sending the Message
Bob appends the encrypted message to his dm_feed:
2025-01-18T18:20:00+02:00 http://alice.example.com/texudus.txt U2FsdGVkX1+mVLsw62BUyjcjnAVtU/EP04gS9GuTsD8xW66BH3V+kb828lMswrDntCtKgauLDZEDRCmpAo3lcQ==
4. Reading the Message
Alice's client fetches the message from Bob's dm_feed and review if the message is for her. She would see yours direct message filtering by her url.
Using her private key, Alice decrypts the message:
1. First, Alice retrieves Bob's public key
curl https://bob.example.com/texudus.txt | grep public_key | cut -d' ' -f4 > bob_public_key.pem
2. Calculate the share key
Alice use her private key and Bob's public key to calculate the shared key:
openssl pkeyutl -derive -inkey alice_private_key.pem -peerkey bob_public_key.pem -out shared_key.bin
3. Alice decodes the encrypted message from Base64
echo 'U2FsdGVkX1+mVLsw62BUyjcjnAVtU/EP04gS9GuTsD8xW66BH3V+kb828lMswrDntCtKgauLDZEDRCmpAo3lcQ==' | base64 -d > message_from_bob.enc
4. Alice decrypts the message using the shared key.
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -in message_from_bob.enc -out message_from_bob.txt -pass file:shared_key.bin
Check message_from_bob.txt for the decrypted message.
cat message_from_bob.txt
Resulting in the plaintext message: Hi Alice, let's meet tomorrow at 5 PM!
Security Considerations
-
Key Verification: Users should ensure public keys are genuine and match the feed owner to mitigate man-in-the-middle attacks.
-
Encrypted Payload Visibility: While the payload is encrypted, all users viewing the feed will see the recipient
nickandurl. This preserves openness but prevents eavesdroppers from reading the message. -
Private Key Security: Users must securely store their private keys and avoid exposing them. A compromised private key can lead to the decryption of all previously sent messages.
-
Replay Attacks: Clients should implement measures to detect and ignore duplicate messages to prevent replay attacks.