mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Fix DM decryptor to try recipient keys for outgoing messages
This commit is contained in:
1 parent
a534e20c10
commit
fa2846afec
2 files changed
+98
-28
No files matched your search
+55
-28
@@ -419,6 +419,8 @@ async function decryptLegacyDm(event, decryptors, actorPubkey) {
|
||||
const ciphertext = typeof event?.content === "string" ? event.content : "";
|
||||
const senderPubkey = normalizeHex(event?.pubkey);
|
||||
const hints = parseEncryptionHints(event?.tags);
|
||||
const recipients = collectRecipients(event?.tags);
|
||||
const normalizedActor = normalizeHex(actorPubkey);
|
||||
|
||||
if (!ciphertext || !senderPubkey) {
|
||||
return buildDecryptResult({
|
||||
@@ -437,38 +439,63 @@ async function decryptLegacyDm(event, decryptors, actorPubkey) {
|
||||
const ordered = orderDecryptors(decryptors, hints);
|
||||
const errors = [];
|
||||
|
||||
const remoteCandidates = [];
|
||||
const seenRemotes = new Set();
|
||||
const registerRemote = (candidate) => {
|
||||
const normalized = normalizeHex(candidate);
|
||||
if (!normalized || seenRemotes.has(normalized)) {
|
||||
return;
|
||||
}
|
||||
seenRemotes.add(normalized);
|
||||
remoteCandidates.push(normalized);
|
||||
};
|
||||
|
||||
if (normalizedActor && normalizedActor === senderPubkey) {
|
||||
for (const recipient of recipients) {
|
||||
registerRemote(recipient?.pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
registerRemote(senderPubkey);
|
||||
|
||||
for (const recipient of recipients) {
|
||||
registerRemote(recipient?.pubkey);
|
||||
}
|
||||
|
||||
for (const decryptor of ordered) {
|
||||
try {
|
||||
const plaintext = await decryptor.decrypt(senderPubkey, ciphertext, {
|
||||
event,
|
||||
stage: "content",
|
||||
});
|
||||
|
||||
if (typeof plaintext === "string") {
|
||||
const recipients = collectRecipients(event?.tags);
|
||||
|
||||
return buildDecryptResult({
|
||||
ok: true,
|
||||
for (const remotePubkey of remoteCandidates) {
|
||||
try {
|
||||
const plaintext = await decryptor.decrypt(remotePubkey, ciphertext, {
|
||||
event,
|
||||
message: {
|
||||
...cloneEvent(event),
|
||||
content: plaintext,
|
||||
},
|
||||
plaintext,
|
||||
recipients,
|
||||
senderPubkey,
|
||||
actorPubkey,
|
||||
decryptor,
|
||||
scheme: decryptor.scheme || hints.algorithms?.[0] || "",
|
||||
stage: "content",
|
||||
remotePubkey,
|
||||
});
|
||||
|
||||
if (typeof plaintext === "string") {
|
||||
return buildDecryptResult({
|
||||
ok: true,
|
||||
event,
|
||||
message: {
|
||||
...cloneEvent(event),
|
||||
content: plaintext,
|
||||
},
|
||||
plaintext,
|
||||
recipients,
|
||||
senderPubkey,
|
||||
actorPubkey,
|
||||
decryptor,
|
||||
scheme: decryptor.scheme || hints.algorithms?.[0] || "",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
scheme: decryptor.scheme || "",
|
||||
source: decryptor.source || "",
|
||||
stage: "content",
|
||||
remotePubkey,
|
||||
error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
scheme: decryptor.scheme || "",
|
||||
source: decryptor.source || "",
|
||||
stage: "content",
|
||||
error,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,49 @@ test("decryptDM handles kind 4 events with nip04 ciphertext", async () => {
|
||||
assert.equal(result.direction, "incoming", "direction should be incoming for recipient");
|
||||
});
|
||||
|
||||
test("decryptDM prefers recipient pubkeys when actor is the sender", async () => {
|
||||
const nostrTools = await import("nostr-tools");
|
||||
const { generateSecretKey, getPublicKey, nip04 } = nostrTools;
|
||||
|
||||
const senderSecret = generateSecretKey();
|
||||
const recipientSecret = generateSecretKey();
|
||||
|
||||
const senderPubkey = getPublicKey(senderSecret);
|
||||
const recipientPubkey = getPublicKey(recipientSecret);
|
||||
|
||||
const message = "Hello from the author";
|
||||
const ciphertext = await nip04.encrypt(senderSecret, recipientPubkey, message);
|
||||
|
||||
const event = {
|
||||
id: "outgoing-kind4",
|
||||
kind: 4,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
pubkey: senderPubkey,
|
||||
tags: [["p", recipientPubkey]],
|
||||
content: ciphertext,
|
||||
};
|
||||
|
||||
const context = {
|
||||
actorPubkey: senderPubkey,
|
||||
decryptors: [
|
||||
{
|
||||
scheme: "nip04",
|
||||
priority: 0,
|
||||
decrypt: (remotePubkey, cipher) =>
|
||||
nip04.decrypt(senderSecret, remotePubkey, cipher),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = await decryptDM(event, context);
|
||||
|
||||
assert.equal(result.ok, true, "decryptDM should succeed for outgoing event");
|
||||
assert.equal(result.plaintext, message, "plaintext should match outgoing message");
|
||||
assert.equal(result.recipients.length, 1, "recipient metadata should remain intact");
|
||||
assert.equal(result.recipients[0].pubkey, recipientPubkey);
|
||||
assert.equal(result.direction, "outgoing", "direction should be outgoing for the author");
|
||||
});
|
||||
|
||||
test("decryptDM unwraps kind 1059 gift wraps with nip44", async () => {
|
||||
const nostrTools = await import("nostr-tools");
|
||||
const { generateSecretKey, getPublicKey, nip44, nip59 } = nostrTools;
|
||||
|
||||
Reference in new issue
Block a user