/* * dm_crypto.h — криптография прямого чата (DM) * * conv_id выводится из ID двух узлов, content_key — из своего X25519-ключа и * публичного ключа пира. Переговоров нет; nonce сообщения зависит от conv_id/author/seq. * CCM и файловые примитивы предоставляет общий media_crypto.h. */ #ifndef DM_CRYPTO_H #define DM_CRYPTO_H #include #include #include "../media_async/media_crypto.h" #ifdef __cplusplus extern "C" { #endif #define DM_CONTENT_KEY_SIZE 32 #define DM_NONCE_SIZE 13 /* AES-CCM требует ровно 13 байт */ #define DM_TAG_SIZE 16 #define DM_CCM_PLAIN_MAX 65535u #define DM_MEDIA_PLAIN_SIZE 32768u /* conv_id: SHA256("utun_dm_v" || min(a,b) || max(a,b)), префикс — 9 ASCII-байт без NUL. * ID узлов хешируются в порядке байтов хоста; первые 8 байт SHA256 читаются как uint64_t того же порядка. * Снимается старший бит (маска 0x7FFFFFFFFFFFFFFF), нулевой результат заменяется на 1. * Положительное 63-битное число, одинаковое для обоих направлений пары узлов. */ uint64_t dm_derive_conv_id(uint64_t a, uint64_t b); /* content_key = SHA256(X25519(my_priv, peer_pub) || "utun_dm_content"). * Возвращает 0 при успехе, <0 при ошибке. */ int dm_derive_content_key(const uint8_t my_priv[32], const uint8_t peer_pub[32], uint8_t out[DM_CONTENT_KEY_SIZE]); /* Детерминированный nonce, уникальный на каждое сообщение: * SHA256(conv_id || author || seq)[..13]. Одинаков на обеих сторонах, * не пересекается между направлениями (author различается). */ void dm_build_nonce(uint64_t conv_id, uint64_t author, uint64_t seq, uint8_t nonce[DM_NONCE_SIZE]); #ifdef __cplusplus } #endif #endif /* DM_CRYPTO_H */