upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/test_btfaddr.cpp
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-08-26 22:43:41 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-08-26 22:43:41 +0000
commit3fe9280fc11bc4ceaff3bb21533224b7b3e88da7 (patch)
tree8179a95dbede51a2b3910b3c0bacae48c8c3b2d0 /src/test_btfaddr.cpp
parentbbe04dc8c96b4c4766d2771d3438233bf82687c0 (diff)
btfaddr: reject descriptors whose onion endpoint is not signed
Upstream 1.2.19 signs the onion endpoint only under the optional sig3, and VerifyDescriptor treated sig3 failure as 'drop the onion, accept the rest'. Any relay could therefore strip an onion endpoint down to a rendezvous-only descriptor (or, under /oniononly, cut the peer off) by deleting one field. Now an onion field must arrive with a valid sig3 over the V3 digest or the whole descriptor is rejected. Honest 1.2.19 writers always emit both fields, so interop is preserved. The full two-field strip still verifies -- it is indistinguishable from a peer that never had an onion -- and needs the onion bound into the primary sig, which only upstream can do without breaking every 1.2.18/1.2.19 verifier; reported as an upstream protocol defect. test_btfaddr flips the two upstream checks that enshrined the soft drop and adds unsigned-onion and full-strip cases.
Diffstat (limited to 'src/test_btfaddr.cpp')
-rw-r--r--src/test_btfaddr.cpp19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/test_btfaddr.cpp b/src/test_btfaddr.cpp
index 8de426e..9d33d63 100644
--- a/src/test_btfaddr.cpp
+++ b/src/test_btfaddr.cpp
@@ -133,12 +133,23 @@ int main()
133 std::string d3 = btf::SignDescriptor(ctx, sk, ENC_HEX, "node-1", 5, ONION); 133 std::string d3 = btf::SignDescriptor(ctx, sk, ENC_HEX, "node-1", 5, ONION);
134 json j3 = json::parse(d3); 134 json j3 = json::parse(d3);
135 j3["onion"] = "bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde.onion:8433"; 135 j3["onion"] = "bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde.onion:8433";
136 CHECK(btf::VerifyDescriptor(ctx, j3.dump(), pk, o) && o.onion.empty(), 136 CHECK(!btf::VerifyDescriptor(ctx, j3.dump(), pk, o),
137 "tampered onion ignored rather than trusted"); 137 "tampered onion rejects the descriptor");
138 json j4 = json::parse(d3); 138 json j4 = json::parse(d3);
139 j4["sig3"] = std::string(128, '0'); 139 j4["sig3"] = std::string(128, '0');
140 CHECK(btf::VerifyDescriptor(ctx, j4.dump(), pk, o) && o.onion.empty(), 140 CHECK(!btf::VerifyDescriptor(ctx, j4.dump(), pk, o),
141 "bad onion signature ignored rather than trusted"); 141 "bad onion signature rejects the descriptor");
142 json j5 = json::parse(d3);
143 j5.erase("sig3");
144 CHECK(!btf::VerifyDescriptor(ctx, j5.dump(), pk, o),
145 "unsigned onion rejects the descriptor");
146 // Removing both fields still verifies: the result is indistinguishable
147 // from a peer that never had an onion endpoint. That residual strip
148 // needs the onion bound into the primary sig, an upstream change.
149 json j6 = json::parse(d3);
150 j6.erase("onion"); j6.erase("sig3");
151 CHECK(btf::VerifyDescriptor(ctx, j6.dump(), pk, o) && o.onion.empty(),
152 "full strip indistinguishable from no-onion (documented residual)");
142 } 153 }
143 154
144 printf("full_resolve_chain_from_address\n"); 155 printf("full_resolve_chain_from_address\n");