ssb: Support publishing private messages from the command-line. #89
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 26m28s

This commit is contained in:
2025-01-08 20:16:17 -05:00
parent 3352098284
commit 872201c886
4 changed files with 223 additions and 93 deletions

View File

@ -4389,3 +4389,67 @@ tf_ssb_ebt_t* tf_ssb_connection_get_ebt(tf_ssb_connection_t* connection)
{
return connection ? connection->ebt : NULL;
}
char* tf_ssb_private_message_encrypt(uint8_t* private_key, const char** recipients, int recipients_count, const char* message, size_t message_size)
{
uint8_t public_key[crypto_box_PUBLICKEYBYTES] = { 0 };
uint8_t secret_key[crypto_box_SECRETKEYBYTES] = { 0 };
uint8_t nonce[crypto_box_NONCEBYTES] = { 0 };
uint8_t body_key[crypto_box_SECRETKEYBYTES] = { 0 };
crypto_box_keypair(public_key, secret_key);
randombytes_buf(nonce, sizeof(nonce));
randombytes_buf(body_key, sizeof(body_key));
uint8_t length_and_key[1 + sizeof(body_key)];
length_and_key[0] = (uint8_t)recipients_count;
memcpy(length_and_key + 1, body_key, sizeof(body_key));
size_t payload_size = sizeof(nonce) + sizeof(public_key) + (crypto_secretbox_MACBYTES + sizeof(length_and_key)) * recipients_count + crypto_secretbox_MACBYTES + message_size;
uint8_t* payload = tf_malloc(payload_size);
uint8_t* p = payload;
memcpy(p, nonce, sizeof(nonce));
p += sizeof(nonce);
memcpy(p, public_key, sizeof(public_key));
p += sizeof(public_key);
for (int i = 0; i < recipients_count; i++)
{
uint8_t recipient[crypto_scalarmult_curve25519_SCALARBYTES] = { 0 };
uint8_t key[crypto_box_PUBLICKEYBYTES] = { 0 };
tf_ssb_id_str_to_bin(key, recipients[i]);
if (crypto_sign_ed25519_pk_to_curve25519(recipient, key) != 0)
{
return NULL;
}
uint8_t shared_secret[crypto_secretbox_KEYBYTES] = { 0 };
if (crypto_scalarmult(shared_secret, secret_key, recipient) != 0)
{
return NULL;
}
if (crypto_secretbox_easy(p, length_and_key, sizeof(length_and_key), nonce, shared_secret) != 0)
{
return NULL;
}
p += crypto_secretbox_MACBYTES + sizeof(length_and_key);
}
if (crypto_secretbox_easy(p, (const uint8_t*)message, message_size, nonce, body_key) != 0)
{
return NULL;
}
p += crypto_secretbox_MACBYTES + message_size;
assert((size_t)(p - payload) == payload_size);
char* encoded = tf_malloc(payload_size * 2 + 5);
size_t encoded_length = tf_base64_encode(payload, payload_size, encoded, payload_size * 2 + 5);
memcpy(encoded + encoded_length, ".box", 5);
tf_free(payload);
return encoded;
}