upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/btfchan.h
blob: 7963f9d0b1723354e85861571ebe3a946edc3a64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Copyright (c) 2026 Bitflash developers
// Distributed under the MIT/X11 software license.
//
// End-to-end encrypted channel for Bitflash (ported from the Itzal echan.rs).
// Wraps a raw pipe in an authenticated stream so relays/rendezvous nodes see
// only ciphertext and cannot MITM: only the endpoint holding the static secret
// can derive the key.
//
// Handshake: the client makes an ephemeral X25519 key and sends its public half
// to the endpoint. Both sides compute the same box (X25519 ECDH -> shared key
// for XChaCha20-Poly1305, i.e. libsodium crypto_box). Wire frame:
//   [len:4 BE][nonce:24][ciphertext || 16-byte tag]
// with a fresh random 24-byte nonce per frame (safe to pick at random).

#ifndef BITFLASH_BTFCHAN_H
#define BITFLASH_BTFCHAN_H

#include <vector>
#include <stdint.h>
#include <stddef.h>

namespace btf
{

static const int CHAN_KEYBYTES   = 32; // X25519 public/secret and shared key
static const int CHAN_NONCEBYTES = 24; // XChaCha20-Poly1305 nonce
static const int CHAN_MACBYTES   = 16; // Poly1305 tag

// Must be called once before any channel use (initializes libsodium). Idempotent.
bool ChanInit();

// Generate a static X25519 keypair (e.g. the endpoint's long-term key).
void ChanKeypair(unsigned char pk[32], unsigned char sk[32]);

// Derive the X25519 public key from a stored secret key (X25519 base mult).
void ChanPublicFromSecret(unsigned char pk[32], const unsigned char sk[32]);

// Client side: given the endpoint's static public key, produce an ephemeral
// public key (to hand the endpoint) and the shared key. Returns false on error.
bool ChanClientHandshake(const unsigned char endpoint_static_pub[32],
                         unsigned char eph_pub_out[32], unsigned char shared_out[32]);

// Endpoint side: rebuild the same shared key from the client's ephemeral public
// key and my static secret. Only the static-secret holder can do this.
bool ChanEndpointHandshake(const unsigned char client_eph_pub[32],
                           const unsigned char my_static_sk[32], unsigned char shared_out[32]);

// Encrypt a plaintext chunk into a full wire frame ([len][nonce][ct||tag]).
std::vector<unsigned char> ChanEncryptFrame(const unsigned char shared[32],
                                            const unsigned char* pt, size_t n);

// Decrypt a frame BODY (nonce||ciphertext||tag, i.e. without the 4-byte length
// prefix). Returns true and fills `out` on success; false on auth failure.
bool ChanDecryptBody(const unsigned char shared[32],
                     const unsigned char* body, size_t n, std::vector<unsigned char>& out);

} // namespace btf

#endif