From c0aacb3287422b03ea73982edcef9bd9e99cafe3 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 27 Oct 2026 04:23:22 +0100 Subject: [PATCH] Define one bounded channel description encoding for signing and verification --- src/chat/chat_channel.c | 43 ++++++++++++++++++--------------------- src/chat/chat_core_priv.h | 6 ++++++ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/chat/chat_channel.c b/src/chat/chat_channel.c index 7752935c..4aece5b3 100644 --- a/src/chat/chat_channel.c +++ b/src/chat/chat_channel.c @@ -32,30 +32,27 @@ #include #include #include +#include +#include -/* ─── Ed25519 подпись join-сообщения ─── */ - -static int channel_sign_join(const uint8_t* ch_x25519, const uint8_t* ch_ed25519, - uint64_t node_id, const uint8_t* node_pubkey, - uint64_t join_ts, const uint8_t* ed25519_privkey, - uint8_t sig_out[64]) -{ - uint8_t msg[128]; - int mlen = member_sync_build_join_msg(ch_x25519, ch_ed25519, node_id, node_pubkey, join_ts, - msg, (int)sizeof(msg)); - if (mlen < 0) { memset(sig_out, 0, 64); return -1; } - - EVP_PKEY* pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, - ed25519_privkey, 32); - if (!pkey) { memset(sig_out, 0, 64); return -1; } - EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); - if (!mdctx) { EVP_PKEY_free(pkey); memset(sig_out, 0, 64); return -1; } - int ok = EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey) == 1 - && EVP_DigestSign(mdctx, sig_out, &(size_t){64}, msg, (size_t)mlen) == 1; - EVP_MD_CTX_free(mdctx); - EVP_PKEY_free(pkey); - if (!ok) memset(sig_out, 0, 64); - return ok ? 0 : -1; +/* Один формат описания для создания и проверки подписи входящего JOIN/invite. */ +int chat_channel_description_data(const char* channel, const char* name, uint64_t owner, + const uint8_t x25519[32], const uint8_t ed25519[32], uint8_t* out, size_t capacity) { + if (!channel || !name || !x25519 || !ed25519 || !out) { + DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "channel description: missing argument"); return -1; + } + size_t channel_len = strnlen(channel, 20), name_len = strnlen(name, 256); + if (!channel_len || channel_len == 20 || channel[0] == '0' || strspn(channel, "0123456789") != channel_len || + strtoull(channel, NULL, 10) > INT64_MAX || name_len == 256 || capacity < channel_len + name_len + 74) { + DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "channel description: invalid channel/name lengths=%zu/%zu capacity=%zu", + channel_len, name_len, capacity); return -1; + } + size_t offset = channel_len + 1; memcpy(out, channel, offset); + memcpy(out + offset, name, name_len + 1); offset += name_len + 1; + memcpy(out + offset, &owner, 8); offset += 8; + memcpy(out + offset, x25519, 32); offset += 32; + memcpy(out + offset, ed25519, 32); offset += 32; + return (int)offset; } /* ─── подготовка инфраструктуры канала (db_sync instance) ─── */ diff --git a/src/chat/chat_core_priv.h b/src/chat/chat_core_priv.h index 186fc0be..b5ebb6af 100644 --- a/src/chat/chat_core_priv.h +++ b/src/chat/chat_core_priv.h @@ -20,6 +20,7 @@ #define CC_ID "chat_core" #define CHAT_MEDIA_BACKFILL_CHANNELS 16 +#define CHAT_CHANNEL_DESCRIPTION_MAX (20 + 256 + 8 + 32 + 32) /* ── Base64 encode/decode (URL-safe, used for msg "d" field prefix) ── */ @@ -119,6 +120,11 @@ void sanitize_ch_id(const char* ch_id, char* out, size_t out_sz); void msg_table_name(const char* ch_id, char* buf, size_t sz); void peers_table_name(const char* ch_id, char* buf, size_t sz); +/* Байты подписи описания:канонический ID+NUL,имя<=255байт+NUL,owner native-u64,X25519/Ed25519 public[32]. + * Возвращает длину/-1;аргументы обязательны,при отказе out не меняется. Общий формат create/JOIN/invite. */ +int chat_channel_description_data(const char* channel, const char* name, uint64_t owner, + const uint8_t x25519[32], const uint8_t ed25519[32], uint8_t* out, size_t capacity); + /* ── db_sync registry (chat_core.c) ── */ struct DB_SYNC_INSTANCE* si_find(struct UTUN_INSTANCE* inst, const char* ch_id);