From 29db7d726624a86e39f6412e11d41e65ae7de3e2 Mon Sep 17 00:00:00 2001 From: padreug Date: Fri, 9 Jan 2026 16:22:16 +0100 Subject: [PATCH] Fix NIP-04 decryption for outgoing messages in chat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The processIncomingMessage function was also being called for outgoing messages from loadRecentMessagesForPeer, but was using the wrong pubkey for decryption. NIP-04 requires YOUR private key + the OTHER party's public key. For outgoing messages, event.pubkey is the user's own pubkey, but it should use the recipient's pubkey from the p-tag for decryption. This fix: - Detects if message is outgoing (event.pubkey === userPubkey) - For outgoing: gets recipient pubkey from p-tag - For incoming: uses event.pubkey (sender) - Sets sent flag correctly based on direction - Associates message with the correct peer Fixes "aes/pcks5: wrong padding" console errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/modules/chat/services/chat-service.ts | 42 +++++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/modules/chat/services/chat-service.ts b/src/modules/chat/services/chat-service.ts index 37cb14c..767636b 100644 --- a/src/modules/chat/services/chat-service.ts +++ b/src/modules/chat/services/chat-service.ts @@ -702,7 +702,8 @@ export class ChatService extends BaseService { } } /** - * Process an incoming message event + * Process a message event (incoming or outgoing) + * Note: This is called for both directions from loadRecentMessagesForPeer */ private async processIncomingMessage(event: any): Promise { try { @@ -715,10 +716,29 @@ export class ChatService extends BaseService { console.warn('Cannot process message: user not authenticated') return } - // Get sender pubkey from event - const senderPubkey = event.pubkey - // Decrypt the message content - const decryptedContent = await nip04.decrypt(userPrivkey, senderPubkey, event.content) + + // Determine if this is an outgoing message (sent by us) + const isOutgoing = event.pubkey === userPubkey + + // For NIP-04 decryption, we need the OTHER party's pubkey + // - For incoming messages: sender is the other party (event.pubkey) + // - For outgoing messages: recipient is the other party (from p-tag) + let otherPartyPubkey: string + if (isOutgoing) { + // Outgoing: get recipient from p-tag + const pTag = event.tags.find((tag: string[]) => tag[0] === 'p') + if (!pTag || !pTag[1]) { + console.warn('Cannot process outgoing message: no recipient p-tag') + return + } + otherPartyPubkey = pTag[1] + } else { + // Incoming: sender is the other party + otherPartyPubkey = event.pubkey + } + + // Decrypt the message content using the other party's pubkey + const decryptedContent = await nip04.decrypt(userPrivkey, otherPartyPubkey, event.content) // Check if this is a market-related message let isMarketMessage = false try { @@ -764,13 +784,13 @@ export class ChatService extends BaseService { id: event.id, content: displayContent, created_at: event.created_at, - sent: false, - pubkey: senderPubkey + sent: isOutgoing, + pubkey: event.pubkey } - // Ensure we have a peer record for the sender - this.addPeer(senderPubkey) - // Add the message - this.addMessage(senderPubkey, message) + // Ensure we have a peer record for the other party (the peer we're chatting with) + this.addPeer(otherPartyPubkey) + // Add the message to the peer's conversation + this.addMessage(otherPartyPubkey, message) } } catch (error) { console.error('Failed to process incoming message:', error)