upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/btfaddr.h
blob: 55a3ebd95313ec78e77b8928cec9e5a85f766af1 (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright (c) 2026 Bitflash developers
// Distributed under the MIT/X11 software license.
//
// Bitflash hidden services -- self-certifying `.btf` addresses (a Tor `.onion`
// analogue, ported from the Itzal design). An address IS the service's public
// key: base32(pubkey[32] || checksum[2]).btf, derived from the owner's
// secp256k1 x-only key, so it cannot be forged (no CA, no DNS). Resolving it
// means proving a descriptor is signed by exactly this key.
//
// This is the ADDRESS + DESCRIPTOR layer. Reachability (rendezvous over the
// embedded Nostr relays so the origin IP is never exposed) builds on top.

#ifndef BITFLASH_BTFADDR_H
#define BITFLASH_BTFADDR_H

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

namespace btf
{

// Pseudo-TLD, resolved inside the Bitflash client, never by real DNS.
extern const char* TLD; // ".btf"

// RFC 4648 base32, lowercase, no padding (case-insensitive hostname label).
std::string Base32Encode(const unsigned char* data, size_t n);
bool        Base32Decode(const std::string& s, std::vector<unsigned char>& out);

// Derive the `.btf` address for a 32-byte x-only public key.
std::string Address(const unsigned char pubkey[32]);

// True if a hostname is a `.btf` address (case-insensitive, optional trailing dot).
bool IsBtf(const std::string& host);

// Parse a `.btf` address back to its 32-byte public key, verifying the checksum.
// Returns false if the label isn't valid base32, is too short, or checksum fails.
bool ParseAddress(const std::string& addr, unsigned char pubkeyOut[32]);


// ---- Service descriptor (published later on Nostr) -------------------------
//
// A descriptor tells a client how to REACH a service after resolving its
// address: "service <pubkey> is reachable via <meeting_node>, encrypt end-to-end
// to my x25519 key <enc>". It is signed by the service key and self-certifying:
// the client requires the signature to verify under the exact pubkey the
// address decodes to, so nobody can publish a descriptor for an address they
// don't own (no hijacking, even via a malicious relay).

struct Descriptor
{
    unsigned char pubkey[32];
    std::string   enc;          // service x25519 public key (hex) for the E2E channel
    std::string   meeting_node; // rendezvous node the service is registered at
    std::string   onion;        // optional direct Tor hidden-service endpoint (host.onion:port)
    uint64_t      created;
};

// Normalize and validate a direct Tor hidden-service endpoint. Only v3 onion
// names are accepted: 56 base32 chars plus ".onion", followed by ":PORT".
bool NormalizeOnionEndpoint(const std::string& in, std::string& out);

// Sign a descriptor. `ctx` is a secp256k1_context* (passed as void* to keep this
// header free of secp headers); `seckey` is the 32-byte service secret key.
// Returns the descriptor JSON as a string, or "" on failure.
std::string SignDescriptor(void* ctx, const unsigned char seckey[32],
                           const std::string& enc, const std::string& meeting_node,
                           uint64_t created,
                           const std::string& onion = std::string());

// Verify a descriptor is validly signed by `expect_pubkey` (the key the resolved
// `.btf` address encodes). Returns true and fills `out` on success.
bool VerifyDescriptor(void* ctx, const std::string& jsonStr,
                      const unsigned char expect_pubkey[32], Descriptor& out);

} // namespace btf

#endif