Fix NIP-04 decryption for outgoing messages in chat

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 <noreply@anthropic.com>
This commit is contained in:
padreug 2026-01-09 16:22:16 +01:00
parent 465dcf988e
commit 651e8c035c

View file

@ -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<void> { private async processIncomingMessage(event: any): Promise<void> {
try { try {
@ -715,10 +716,29 @@ export class ChatService extends BaseService {
console.warn('Cannot process message: user not authenticated') console.warn('Cannot process message: user not authenticated')
return return
} }
// Get sender pubkey from event
const senderPubkey = event.pubkey // Determine if this is an outgoing message (sent by us)
// Decrypt the message content const isOutgoing = event.pubkey === userPubkey
const decryptedContent = await nip04.decrypt(userPrivkey, senderPubkey, event.content)
// 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 // Check if this is a market-related message
let isMarketMessage = false let isMarketMessage = false
try { try {
@ -764,13 +784,13 @@ export class ChatService extends BaseService {
id: event.id, id: event.id,
content: displayContent, content: displayContent,
created_at: event.created_at, created_at: event.created_at,
sent: false, sent: isOutgoing,
pubkey: senderPubkey pubkey: event.pubkey
} }
// Ensure we have a peer record for the sender // Ensure we have a peer record for the other party (the peer we're chatting with)
this.addPeer(senderPubkey) this.addPeer(otherPartyPubkey)
// Add the message // Add the message to the peer's conversation
this.addMessage(senderPubkey, message) this.addMessage(otherPartyPubkey, message)
} }
} catch (error) { } catch (error) {
console.error('Failed to process incoming message:', error) console.error('Failed to process incoming message:', error)