upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/btfaddr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/btfaddr.cpp')
-rw-r--r--src/btfaddr.cpp40
1 files changed, 26 insertions, 14 deletions
diff --git a/src/btfaddr.cpp b/src/btfaddr.cpp
index ce2ac86..502220e 100644
--- a/src/btfaddr.cpp
+++ b/src/btfaddr.cpp
@@ -319,20 +319,32 @@ bool VerifyDescriptor(void* ctxv, const std::string& jsonStr,
319 std::string onion; 319 std::string onion;
320 if (v.contains("onion")) 320 if (v.contains("onion"))
321 { 321 {
322 if (v["onion"].is_string() && v.contains("sig3") && v["sig3"].is_string()) 322 // A descriptor that carries an onion endpoint must prove it. The
323 { 323 // endpoint is covered by sig3 and only sig3, so any failure here --
324 std::string onionNorm; 324 // missing sig3, bad hex, unnormalised endpoint, bad signature --
325 std::string onionRaw = v["onion"].get<std::string>(); 325 // means the descriptor was tampered with, and a tampered
326 if (NormalizeOnionEndpoint(onionRaw, onionNorm) && onionNorm == onionRaw) 326 // descriptor is rejected outright. Upstream dropped just the onion
327 { 327 // and accepted the rest, which let any relay convert an onion
328 unsigned char sig3[64]; 328 // descriptor into a rendezvous-only one by deleting a field.
329 unsigned char digest3[32]; 329 //
330 DescriptorDigestV3(expect_pubkey, enc, meeting_node, onionNorm, created, digest3); 330 // Residual, by design: removing BOTH "onion" and "sig3" still
331 if (HexDecode(v["sig3"].get<std::string>(), sig3, 64) && 331 // verifies, because the result is indistinguishable from a peer
332 secp256k1_schnorrsig_verify(ctx, sig3, digest3, 32, &xpub)) 332 // that never had an onion endpoint. Closing that requires binding
333 onion = onionNorm; 333 // the onion into the primary sig (the V2 digest), which every
334 } 334 // upstream 1.2.18/1.2.19 verifier would reject -- an upstream
335 } 335 // protocol change, not something this fork can do unilaterally.
336 if (!v["onion"].is_string()) return false;
337 if (!v.contains("sig3") || !v["sig3"].is_string()) return false;
338 std::string onionNorm;
339 std::string onionRaw = v["onion"].get<std::string>();
340 if (!NormalizeOnionEndpoint(onionRaw, onionNorm) || onionNorm != onionRaw)
341 return false;
342 unsigned char sig3[64];
343 unsigned char digest3[32];
344 DescriptorDigestV3(expect_pubkey, enc, meeting_node, onionNorm, created, digest3);
345 if (!HexDecode(v["sig3"].get<std::string>(), sig3, 64)) return false;
346 if (!secp256k1_schnorrsig_verify(ctx, sig3, digest3, 32, &xpub)) return false;
347 onion = onionNorm;
336 } 348 }
337 349
338 memcpy(out.pubkey, expect_pubkey, 32); 350 memcpy(out.pubkey, expect_pubkey, 32);