sign: ensure the NIP-46 result matches the template
This commit is contained in:
parent
007565b513
commit
c8a5da086e
18
src/sign.ts
18
src/sign.ts
|
@ -5,14 +5,14 @@ import { type Event, type EventTemplate, finishEvent, HTTPException } from '@/de
|
|||
import { connectResponseSchema } from '@/schemas/nostr.ts';
|
||||
import { jsonSchema } from '@/schema.ts';
|
||||
import { Sub } from '@/subs.ts';
|
||||
import { Time } from '@/utils.ts';
|
||||
import { eventMatchesTemplate, Time } from '@/utils.ts';
|
||||
import { createAdminEvent } from '@/utils/web.ts';
|
||||
|
||||
/**
|
||||
* Sign Nostr event using the app context.
|
||||
*
|
||||
* - If a secret key is provided, it will be used to sign the event.
|
||||
* - If `X-Nostr-Sign` is passed, it will use a NIP-46 to sign the event.
|
||||
* - If `X-Nostr-Sign` is passed, it will use NIP-46 to sign the event.
|
||||
*/
|
||||
async function signEvent<K extends number = number>(event: EventTemplate<K>, c: AppContext): Promise<Event<K>> {
|
||||
const seckey = c.get('seckey');
|
||||
|
@ -54,13 +54,14 @@ async function signNostrConnect<K extends number = number>(event: EventTemplate<
|
|||
tags: [['p', pubkey]],
|
||||
}, c);
|
||||
|
||||
return awaitSignedEvent<K>(pubkey, messageId, c);
|
||||
return awaitSignedEvent<K>(pubkey, messageId, event, c);
|
||||
}
|
||||
|
||||
/** Wait for signed event to be sent through Nostr relay. */
|
||||
async function awaitSignedEvent<K extends number = number>(
|
||||
pubkey: string,
|
||||
messageId: string,
|
||||
template: EventTemplate<K>,
|
||||
c: AppContext,
|
||||
): Promise<Event<K>> {
|
||||
const sub = Sub.sub(messageId, '1', [{ kinds: [24133], authors: [pubkey], '#p': [Conf.pubkey] }]);
|
||||
|
@ -79,12 +80,17 @@ async function awaitSignedEvent<K extends number = number>(
|
|||
for await (const event of sub) {
|
||||
if (event.kind === 24133) {
|
||||
const decrypted = await decryptAdmin(event.pubkey, event.content);
|
||||
const msg = jsonSchema.pipe(connectResponseSchema).parse(decrypted);
|
||||
|
||||
if (msg.id === messageId) {
|
||||
const result = jsonSchema
|
||||
.pipe(connectResponseSchema)
|
||||
.refine((msg) => msg.id === messageId)
|
||||
.refine((msg) => eventMatchesTemplate(msg.result, template))
|
||||
.safeParse(decrypted);
|
||||
|
||||
if (result.success) {
|
||||
close();
|
||||
clearTimeout(timeout);
|
||||
return msg.result as Event<K>;
|
||||
return result.data.result as Event<K>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { type Event, nip19, z } from '@/deps.ts';
|
||||
import { type Event, type EventTemplate, getEventHash, nip19, z } from '@/deps.ts';
|
||||
import { getAuthor } from '@/queries.ts';
|
||||
import { lookupNip05Cached } from '@/utils/nip05.ts';
|
||||
|
||||
|
@ -106,11 +106,17 @@ function dedupeEvents<K extends number>(events: Event<K>[]): Event<K>[] {
|
|||
return [...new Map(events.map((event) => [event.id, event])).values()];
|
||||
}
|
||||
|
||||
/** Ensure the template and event match on their shared keys. */
|
||||
function eventMatchesTemplate(event: Event, template: EventTemplate): boolean {
|
||||
return getEventHash(event) === getEventHash({ pubkey: event.pubkey, ...template });
|
||||
}
|
||||
|
||||
export {
|
||||
bech32ToPubkey,
|
||||
dedupeEvents,
|
||||
eventAge,
|
||||
eventDateComparator,
|
||||
eventMatchesTemplate,
|
||||
findTag,
|
||||
isFollowing,
|
||||
isRelay,
|
||||
|
|
Loading…
Reference in New Issue