You can send the GiftWrap to all relays if you want. Same as Nip04.
So it means now I have to send two DMs, one with 04 and one with 17 😭😭😭
Maybe.. but just for now. Or just do one with NIP 17. People can use 0xchat to see it on iOS and Android, Snort/Coracle/Coop in the desktop, and Amethyst on Android. There are options available.
Can’t ask normal users to jump through the hoops, if they are on Damus or any other client that yet to support it, I’ll have a long list of people complaining about broken OTP 😭
This is why ie6 lasted so long, too scared to rip the bandaid Nip04 is just bad it's better to fix it now while we're small and go through some short term pain imo
can it be blocked at the relay level? relays could just stop accepting them, that' would orce the hand of devs to remove it.
Good point, I will remove it from my relays
We still use it for otp, so i doubt we would just remove it unless someones wants to rewrite our otp code. It’s easy for people who don’t have existing code around to say just remove it.
Yes it's definitely easier to say than fix, but don't you agree it's bad for DMs?
Always has been the case, people just make a blank statement “<thing> is bad” and have 0 regard for all that came before or relies on it. Plus “bad” is only based on use case, and nothing more than that.
Looking at nip17, I still have no idea how I can use nostr-tools and create a correct DM. One part of being secure is having less ways to shoot yourself into a foot, and I see a lot of landmines that will reap my legs off when I read it. I asked for a good example using nostr-tools and failed to find even one yet. 😭😭😭😭
https://github.com/vitorpamplona/lazereyes/blob/main/js/nip17.js
Just call createNIp17wraps with the message and keys.
async function createNip17Wraps(message, senderPubkey, receiverPubkey) Where do I stick my SK into? And what do I do with the returned values that are in non-event format?
Humm.. you might need to tweak the code. This uses the browser's expression to sign via window.nostr... The returned values are two wraps for the sender and the receiver. All you need to do is to broadcast them to the relays each one uses.
Ok, I’ll take a look again and see if I can implement it. I assume that I do not need to send the “sender” part since it is OTP and nobody needs to check it as a sender
Yep, I guess it would be even better since the sender doesn't need a copy of the code.
I implemented it for the nostr.build just now but not sure if it even works. I still send 04 and now 17 as well. I have no way to verify it 😅
I will check tomorrow, but I only got the nip04. Also, you should ask for the nprofile in the login page. In that way, you will have the relay info to get the DM relays and send the DMs. :)
Is the code open somewhere?
😅 the code that does the sending is a complete mess and has a non-public info in it. I’ll try to clean it up and open the source for it. Need to parameterize some of the non-public (but not a high value secret or anything) info.
t-y Fishcake
This took me way longer than I would have liked, but here is the working Typescript code that makes those god damn GW DMs. // Create DM event export async function creatNIP17DMEvent( fromSk: string, toNpub: string, dm: string[], ): Promise<Array<Event>> { const skBuff = hexToBytes(fromSk) const events: Array<Event> = [] while (dm.length > 0) { const msg = dm.shift() if (msg) events.push(createNip17Wraps(msg, toNpub, skBuff)) } return events } function getNow(): number { return Math.floor(Date.now() / 1000) } function getRandomNow(): number { return getNow() - Math.floor(Math.random() * 172800) } function nip44Encrypt(rumor: Rumor, privateKey: Uint8Array, publicKey: string): string { const key = nip44.v2.utils.getConversationKey(privateKey, publicKey) return nip44.v2.encrypt(JSON.stringify(rumor), key) } function createWrap(event: Event, recipientPublicKey: string): Event { // Get random secret key to wrap the event const randomSK = generateSecretKey() return finalizeEvent({ kind: 1059, // Gift wrapped event content: nip44Encrypt(event, randomSK, recipientPublicKey), created_at: getRandomNow(), tags: [["p", recipientPublicKey]] }, randomSK) as Event } function createSeal(event: Rumor, privateKey: Uint8Array, recipientPublicKey: string): Event { return finalizeEvent({ kind: 13, // Seal content: nip44Encrypt(event, privateKey, recipientPublicKey), created_at: getRandomNow(), tags: [] }, privateKey) } function createRumor(message: string, senderPubkey: string, receiverPubkey: string): Rumor { const rumor = { kind: 14, // As per specs, should be Kind 14 event content: message, pubkey: senderPubkey, created_at: getNow(), tags: [["p", receiverPubkey]], } as Rumor rumor.id = getEventHash(rumor) return rumor } function createNip17Wraps(message: string, recipientPublicKey: string, senderSk: Uint8Array): Event { const senderPubkey = getPublicKey(senderSk) return createWrap( createSeal( createRumor(message, senderPubkey, recipientPublicKey), senderSk, recipientPublicKey), recipientPublicKey) }
One fix for types: function nip44Encrypt(rumor: Rumor | VerifiedEvent, privateKey: Uint8Array, publicKey: string): string { const key = nip44.v2.utils.getConversationKey(privateKey, publicKey) return nip44.v2.encrypt(JSON.stringify(rumor), key) } It does not have any impact, just cosmetics
It works! :)
Yeah! I do suggest to make a clear documentation about how it should be done, I will contribute if needed. It is super confusing now and no single NIP to look at 🫂😭
Maybe send a PR with some of this code to nostr-tools?
Good idea! 🫂
I should add nip40 expiration to the wrap too I think, if the event is OTP
Great idea
Done!
I had some other issues, and didn’t have the messages actually sent anywhere, now they are but none of the clients see them only 04. Hence my point, if it is complex and close to impossible to implement even with examples, it will not be used or will be misused or misimplemented 😭😭😭
Very good boy You can tag me in one and send to relay.utxo.one/chat I'll help you test 🐶🐾 Relay will give you an error right away if it didn't work https://i.nostr.build/lyNDHtFTkFQU6r0L.jpg
I am blasting the DMs, and they go out but none of them are seen by the client. My conclusion is that nip17 sucks ass, and only focuses on solving c2c but not s2c problem. I cannot have DMs sent to a specific relay, I don’t know who is using what and when, I need for DMs to reach the recipient and for me to do not need to know about their nprofile or anything else besides their npub, I cannot rely on any relay to have any info about any npub, I need to send it fast and with no WS fuss that is client oriented shit. So many complaints 😭😭😭😅
Thanks! This will help ! 🫂🙏🏻🫡