diff options
Diffstat (limited to 'src/btfaddr.cpp')
| -rw-r--r-- | src/btfaddr.cpp | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/src/btfaddr.cpp b/src/btfaddr.cpp index 5f983bc..55bb6c5 100644 --- a/src/btfaddr.cpp +++ b/src/btfaddr.cpp | |||
| @@ -214,35 +214,47 @@ bool VerifyDescriptor(void* ctxv, const std::string& jsonStr, | |||
| 214 | const unsigned char expect_pubkey[32], Descriptor& out) | 214 | const unsigned char expect_pubkey[32], Descriptor& out) |
| 215 | { | 215 | { |
| 216 | secp256k1_context* ctx = (secp256k1_context*)ctxv; | 216 | secp256k1_context* ctx = (secp256k1_context*)ctxv; |
| 217 | json v; | 217 | // Descriptors arrive from untrusted peers (via Nostr relays). Guard the whole |
| 218 | try { v = json::parse(jsonStr); } catch (...) { return false; } | 218 | // parse: a malformed or wrong-typed field must be rejected, never throw. |
| 219 | if (!v.is_object()) return false; | 219 | try |
| 220 | if (!v.contains("pubkey") || !v.contains("enc") || !v.contains("meeting_node") | 220 | { |
| 221 | || !v.contains("created") || !v.contains("sig")) return false; | 221 | json v = json::parse(jsonStr); |
| 222 | 222 | if (!v.is_object()) return false; | |
| 223 | unsigned char pubkey[32]; | 223 | if (!v.contains("pubkey") || !v.contains("enc") || !v.contains("meeting_node") |
| 224 | if (!HexDecode(v["pubkey"].get<std::string>(), pubkey, 32)) return false; | 224 | || !v.contains("created") || !v.contains("sig")) return false; |
| 225 | if (memcmp(pubkey, expect_pubkey, 32) != 0) return false; // descriptor is for a different key | 225 | // Reject wrong field types before extracting (json::get would otherwise throw). |
| 226 | 226 | if (!v["pubkey"].is_string() || !v["enc"].is_string() || | |
| 227 | std::string enc = v["enc"].get<std::string>(); | 227 | !v["meeting_node"].is_string() || !v["sig"].is_string() || |
| 228 | std::string meeting_node = v["meeting_node"].get<std::string>(); | 228 | !v["created"].is_number_unsigned()) return false; |
| 229 | uint64_t created = v["created"].get<uint64_t>(); | 229 | |
| 230 | 230 | unsigned char pubkey[32]; | |
| 231 | unsigned char sig[64]; | 231 | if (!HexDecode(v["pubkey"].get<std::string>(), pubkey, 32)) return false; |
| 232 | if (!HexDecode(v["sig"].get<std::string>(), sig, 64)) return false; | 232 | if (memcmp(pubkey, expect_pubkey, 32) != 0) return false; // descriptor is for a different key |
| 233 | 233 | ||
| 234 | unsigned char digest[32]; | 234 | std::string enc = v["enc"].get<std::string>(); |
| 235 | DescriptorDigest(expect_pubkey, enc, meeting_node, created, digest); | 235 | std::string meeting_node = v["meeting_node"].get<std::string>(); |
| 236 | 236 | uint64_t created = v["created"].get<uint64_t>(); | |
| 237 | secp256k1_xonly_pubkey xpub; | 237 | |
| 238 | if (!secp256k1_xonly_pubkey_parse(ctx, &xpub, expect_pubkey)) return false; | 238 | unsigned char sig[64]; |
| 239 | if (!secp256k1_schnorrsig_verify(ctx, sig, digest, 32, &xpub)) return false; | 239 | if (!HexDecode(v["sig"].get<std::string>(), sig, 64)) return false; |
| 240 | 240 | ||
| 241 | memcpy(out.pubkey, expect_pubkey, 32); | 241 | unsigned char digest[32]; |
| 242 | out.enc = enc; | 242 | DescriptorDigest(expect_pubkey, enc, meeting_node, created, digest); |
| 243 | out.meeting_node = meeting_node; | 243 | |
| 244 | out.created = created; | 244 | secp256k1_xonly_pubkey xpub; |
| 245 | return true; | 245 | if (!secp256k1_xonly_pubkey_parse(ctx, &xpub, expect_pubkey)) return false; |
| 246 | if (!secp256k1_schnorrsig_verify(ctx, sig, digest, 32, &xpub)) return false; | ||
| 247 | |||
| 248 | memcpy(out.pubkey, expect_pubkey, 32); | ||
| 249 | out.enc = enc; | ||
| 250 | out.meeting_node = meeting_node; | ||
| 251 | out.created = created; | ||
| 252 | return true; | ||
| 253 | } | ||
| 254 | catch (...) | ||
| 255 | { | ||
| 256 | return false; // malformed / wrong-typed descriptor -> reject, don't crash | ||
| 257 | } | ||
| 246 | } | 258 | } |
| 247 | 259 | ||
| 248 | } // namespace btf | 260 | } // namespace btf |