verifyNostrEvent helper

This commit is contained in:
randogoth 2026-07-05 16:49:10 +03:00
parent f69fcb661f
commit 0e70aba755
4 changed files with 80 additions and 17 deletions

View file

@ -9,23 +9,8 @@ import 'nostr_event.dart';
/// Recomputes a signed event's id from its fields and checks the BIP-340
/// signature against its pubkey. Throws if either is inconsistent.
void _verifySignedEvent(Map<String, dynamic> event) {
final id = nostrEventId(
publicKey: event['pubkey'] as String,
createdAt: event['created_at'] as int,
kind: event['kind'] as int,
tags:
(event['tags'] as List).map((t) => (t as List).cast<String>()).toList(),
content: event['content'] as String,
);
if (id != event['id']) {
throw ArgumentError('Event id does not match its contents');
}
if (!bip340.verify(
event['pubkey'] as String,
id,
event['sig'] as String,
)) {
throw ArgumentError('Event signature is invalid');
if (!verifyNostrEvent(event)) {
throw ArgumentError('Event id or signature is invalid');
}
}

View file

@ -4,6 +4,30 @@ import 'dart:math';
import 'package:bip340/bip340.dart' as bip340;
import 'package:crypto/crypto.dart';
/// Verifies a decoded Nostr event: recomputes its id from the canonical
/// serialization and checks the BIP-340 signature against its pubkey. Returns
/// false (rather than throwing) for a malformed map, a mismatched id, or a bad
/// signature, so callers can drop untrusted events fetched from a relay.
bool verifyNostrEvent(Map<String, dynamic> event) {
try {
final publicKey = event['pubkey'] as String;
final sig = event['sig'] as String;
final id = nostrEventId(
publicKey: publicKey,
createdAt: event['created_at'] as int,
kind: event['kind'] as int,
tags: (event['tags'] as List)
.map((t) => (t as List).cast<String>())
.toList(),
content: event['content'] as String,
);
if (id != event['id']) return false;
return bip340.verify(publicKey, id, sig);
} catch (_) {
return false;
}
}
/// Computes the Nostr event id: the lowercase hex SHA-256 of the canonical
/// serialization `[0, pubkey, created_at, kind, tags, content]`. Shared by
/// [signNostrEvent] and by unsigned events such as NIP-59 rumors, which carry

View file

@ -3,6 +3,7 @@ export 'src/relay_connection.dart';
export 'src/nostr_publish_actor.dart';
export 'src/nostr_fetch_actor.dart';
export 'src/nostr_signer_actor.dart';
export 'src/nostr_event.dart' show verifyNostrEvent;
export 'src/geo_actor.dart';
export 'src/file_upload_actor.dart';
export 'src/file_download_actor.dart';