How does one create a fake zap event?

Reply to this note

Please Login to reply.

Discussion

Ready for some low-level nostr? Because I will not hold back.

First, let's reference the required information: https://github.com/nostr-protocol/nips/blob/master/57.md

NIP-57 consists of a few events; their flow is well explained right away. From that flow, we only need part of step 1 (their public key, npub), 3 (the fake event we will generate), ignore 4, 5, 6, and 7, we will absolutely fake 8, and quietly ignore 9 with a smirk.

I will be using fiatjaf's nak tool for this; it is the easiest way to make this and I will use my own npub for a demonstration, on your post, to show you how this works.

First, I need your npub. Easy, your profile, right there - and store it.

I also need the ID of your post. That one is quite easy to grab. Unfortunately, Primal's cache servers isn't entirely nostr compliant; trying to grab events from it returns weird replies... O.o Oh well, I'll just assume that one of "the big ones" have your event too.

However, I have to convert the keys first.

root@superdiskboi ~# setenv TARGET_NPUB "npub1plrayr9zxu7qw365xrrmckx9ygql9rfj583khlcksen7eapj0lkqvv499t"

root@superdiskboi ~ [1]# setenv MY_NPUB "npub1tcekjparmkju6k83r5tzmzjvjwy0nnajlrwyk35us9g7x7wx80ys9hjmky"

root@superdiskboi ~ [1]# setenv TARGET_NPUB_HEX (nak decode $TARGET_NPUB | jq -r ".pubkey")

root@superdiskboi ~ [1]# setenv MY_NPUB_HEX (nak decode $MY_NPUB | jq -r ".pubkey")

root@superdiskboi ~ [1]# echo $TARGET_NPUB_HEX

0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec

root@superdiskboi ~# echo $MY_NPUB_HEX

5e336907a3dda5cd58f11d162d8a4c9388f9cfb2f8dc4b469c8151e379c63bc9

Cool. I can use that for requests now - so, lets fetch your reply right up there:

# nak req -a $TARGET_NPUB_HEX -p $MY_NPUB_HEX --limit 5 wss://nos.lol

connecting to wss://nos.lol... ok.

{"kind":1,"id":"8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d","pubkey":"0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec","created_at":1740326940,"tags":[["e","ce2fa5cf30573050d4f79f601beae49a66d265f15673abf5cb40e5b81d63a06a","","root"],["e","7b6d5c795a1b129619cbfdc2197b5c0fd13606d60ec71f2cecad120f314c841f"],["e","29051fdea21103f94926792a420a0db3aff40f6df39fde46a868a52f22387285","","reply"],["p","e2ccf7cf20403f3f2a4a55b328f0de3be38558a7d5f33632fdaaefc726c1c8eb"],["p","0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec"],["p","5e336907a3dda5cd58f11d162d8a4c9388f9cfb2f8dc4b469c8151e379c63bc9"]],"content":"How does one create a fake zap event? ","sig":"a103258815d3279a77ebc704abbb8ddd1f3dd947757e6c002bffb0031552b102def36ca51f9558fd0ce5efc9c7ea8a77ac989af577ad0469fdae00c95dd4a1be"}

Sick. The ID is what I need to make a reference to this note. So, I saved that together with the JSON blob.

As per the NIP, I _should_ normally contact your LNURL and check if you are Nostr enabled and blah blah - but let's just pretend that yours does accept Nostr and I could fetch an invoice and send the payment and your server happily returns me with a result; to quote, "Once the invoice is paid, the recipient's lnurl server MUST generate a zap receipt as described in Appendix E, and publish it to the relays specified in the zap request."

Each Nostr-enabled LN-Server/-Service has it's own npub/nsec. Let's make one for the pretend real quick.

root@superdiskboi ~ [1]# setenv FAKEPAYER_NSEC_HEX (nak key generate)

root@superdiskboi ~ [1]# setenv FAKEPAYER_NPUB_HEX (nak key public $FAKEPAYER_NSEC_HEX)

root@superdiskboi ~ [1]# echo $FAKEPAYER_NPUB_HEX

0658eebe021d9d3a0ec2bf4dfe066dda7e0b6c498a9d7483cfd1e512977deb83

Good! Our fake LN-Server has an identity now. Lit.

Now, we need to generate the fake "zap receipt", an event of kind 9735, a p-tag with the receipient (your) npub, e tag for the event (for which I grabbed the ID above), a fake "Bolt11 Zap Receipt", and an encoded Zap Request - which in itself is just a nostr event of kind 9734 with basically the same settings (target post in e, target npub in p and an amount tag - I will set this to something humane).

Let's start bottom-up:

(I) paid (you) 1k sats on your reply (id):

# nak event --sec $MY_NSEC_HEX -k 9734 -e $YOUR_REPLY_ID -p $TARGET_NPUB_HEX -t amount=1000 -t "lnurl=damneddespot724@minibits.cash"

{"kind":9734,"id":"047b4897cfc34a59bcaa05df0341d19b5419165bc5a187fb25b76a41f4a78d5f","pubkey":"43554621089946f0d76870db76f08451048d924a899ae01ffe374a29bb8e3cf3","created_at":1740328851,"tags":[["amount","1000"],["lnurl","damneddespot724@minibits.cash"],["e","8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d"],["p","0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec"]],"content":"","sig":"6a21986a90633b119097f8e62493d502b2d6df69e01af9b1ad0ca3eccf88bf57e51d78981a6359f97154a0ec6a9999fc4a53a2981d22d4a54432cf67e934c848"}

That's the "zap request" we sent off to the non-existent server.

Next, we need a fake bolt11 "containing the description hash bolt11 invoice". Nope, don't think so. In fact, I'll throw some completely arbitrary information in there - because no relay in Nostr-land actually verifies those anyway - not even the clients. :D

# setenv BOLT11_DESCRIPTOR "idontthinkthiswillreallymateranywaysoallowmetowritesomethingstupidinherelol"

Next, "The zap receipt MUST contain a description tag which is the JSON-encoded zap request". Bruh. literally stringifying a stringified JSON? aight...

# echo '{"kind":9734,"id":"047b4897cfc34a59bcaa05df0341d19b5419165bc5a187fb25b76a41f4a78d5f","pubkey":"43554621089946f0d76870db76f08451048d924a899ae01ffe374a29bb8e3cf3","created_at":1740328851,"tags":[["amount","1000"],["lnurl","damneddespot724@minibi

ts.cash"],["e","8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d"],["p","0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec"]],"content":"","sig":"6a21986a90633b119097f8e62493d502b2d6df69e01af9b1ad0ca3eccf88bf57e51d78981a6359f97154a0ec6a999

9fc4a53a2981d22d4a54432cf67e934c848"}' | podman run -i php -r 'echo json_encode(file_get_contents("php://stdin"));'

"{\"kind\":9734,\"id\":\"047b4897cfc34a59bcaa05df0341d19b5419165bc5a187fb25b76a41f4a78d5f\",\"pubkey\":\"43554621089946f0d76870db76f08451048d924a899ae01ffe374a29bb8e3cf3\",\"created_at\":1740328851,\"tags\":[[\"amount\",\"1000\"],[\"lnurl\",\"damneddespot724@minibits.cash\"],[\"e\",\"8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d\"],[\"p\",\"0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec\"]],\"content\":\"\",\"sig\":\"6a21986a90633b119097f8e62493d502b2d6df69e01af9b1ad0ca3eccf88bf57e51d78981a6359f97154a0ec6a9999fc4a53a2981d22d4a54432cf67e934c848\"}\n"

Yep, old reliable. Didn't have node on my system, and I had just pulled PHP down so... here we are. Strip the \n at the end, and we have ourself a stringified json string. woop. x.x

Alright - now let's fill out all the blanks and construct the actual zap event, 9735:

# nak event --sec $FAKEPAYER_NSEC_HEX -k 9735 -e $YOUR_REPLY_ID -p $TARGET_NPUB_HEX -d "bolt11=$BOLT11_DESCRIPTOR" -d "description=$FAKE_PAY_REQUEST"

{"kind":9735,"id":"328670ccb23504127f476449f968c0a6fc5dddf6e3bb1107a4e1f7c65cce935a","pubkey":"0658eebe021d9d3a0ec2bf4dfe066dda7e0b6c498a9d7483cfd1e512977deb83","created_at":1740329750,"tags":[["e","8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d"],["p","0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec"],["d","bolt11=idontthinkthiswillreallymateranywaysoallowmetowritesomethingstupidinherelol"],["d","description={\"kind\":9734,\"id\":\"047b4897cfc34a59bcaa05df0341d19b5419165bc5a187fb25b76a41f4a78d5f\",\"pubkey\":\"43554621089946f0d76870db76f08451048d924a899ae01ffe374a29bb8e3cf3\",\"created_at\":1740328851,\"tags\":[[\"amount\",\"1000\"],[\"lnurl\",\"damneddespot724@minibits.cash\"],[\"e\",\"8a36028fb98d27a3529736432a122b1721f4ae144e8271be3b84dd9e0293fd5d\"],[\"p\",\"0fc7d20ca2373c07475430c7bc58c52201f28d32a1e36bff168667ecf4327fec\"]],\"content\":\"\",\"sig\":\"6a21986a90633b119097f8e62493d502b2d6df69e01af9b1ad0ca3eccf88bf57e51d78981a6359f97154a0ec6a9999fc4a53a2981d22d4a54432cf67e934c848\"}"]],"content":"","sig":"1a508d6444a3f1dd36d946a05e0af4a6626e7ed593b584f2133c7d42f15ef0296c87ef901d5c7767636ffa836ef5cf0a00ce30c3cd781e004de6dee36be5efdd"}

And there we have it: A zap event with a bogus zap request that never received a real bolt11 invoice but fullfills the entire schema - and, how to get there.

You can put that into a simple, single shell file and rumor has it people have done this before to fake interaction on Nostr. Some people really are that lonely, but considering how easy it is to fake them, I guess you can see how why it works. x)

By the way, this IS a valid set of events. Those ARE verifiable. Do not put them on a relay, please? Not that it would do anything, but - out of respect, yknow. o.o

Holy shit... I have some understanding to do

OK I just read through it again, I roughly understand what's going on (I do some JSON modifications of IDs etc in my day job just like this (not good at it or understand the nostr protocol very well yet but...) Why would I not put it onto a relay then (because it's your npub and that'd make you look bad)? Aren't we trying to blow up bots together?

Does this spike cpu on the bot or something and it just continuously attempts to fulfill the invoice, how does it attempt to process this?

You wouldnt put this into a relay because it's literally a fake event, a lie. Like, uh, how do I put this... "It's not honorable to lie"? does...that make sense? ^^;

Nicely explained, and extra lol points! But wound't this make that not work assuming the client was checking?

nevent1qvzqqqqqqypzqvhpsfmr23gwhv795lgjc8uw0v44z3pe4sg2vlh08k0an3wx3cj9qqsvty8w0mrxdg9hh8k34pzef3a3sghdv6jr7ykts42ef6xmn4yd3asyzaqek

Yep, correct.

Now, how many clients _do_ that? :D

To quote the quoted jb55: "if they implement the spec properly" - and no client that I know/am aware of (primal, snort, astral, nostrudel, nostor) do. Especially no relays. o.o

THAT SAID... I am heavily basing this off of what I have seen or interacted with. o.o