Verify events (verify id and signature), configurable

This commit is contained in:
Mike Dilger 2024-02-15 13:56:54 +13:00
parent 01a519be63
commit 68a8cc6ad4
5 changed files with 48 additions and 2 deletions

View File

@ -10,5 +10,6 @@ FriendlyConfig(
public_key_hex: None,
user_hex_keys: [
"ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49"
]
],
verify_events: true,
)

View File

@ -14,6 +14,7 @@ pub struct FriendlyConfig {
pub description: Option<String>,
pub public_key_hex: Option<String>,
pub user_hex_keys: Vec<String>,
pub verify_events: bool,
}
impl Default for FriendlyConfig {
@ -29,6 +30,7 @@ impl Default for FriendlyConfig {
description: None,
public_key_hex: None,
user_hex_keys: vec![],
verify_events: true,
}
}
}
@ -46,6 +48,7 @@ impl FriendlyConfig {
description,
public_key_hex,
user_hex_keys,
verify_events,
} = self;
let mut public_key: Option<Pubkey> = None;
@ -70,6 +73,7 @@ impl FriendlyConfig {
public_key,
user_keys,
user_hex_keys,
verify_events,
})
}
}
@ -87,4 +91,5 @@ pub struct Config {
pub public_key: Option<Pubkey>,
pub user_keys: Vec<Pubkey>,
pub user_hex_keys: Vec<String>,
pub verify_events: bool,
}

View File

@ -3,6 +3,10 @@ use thiserror::Error;
/// Errors that can occur in the chorus crate
#[derive(Error, Debug)]
pub enum Error {
// Bad event id
#[error("Bad event id, does not match hash")]
BadEventId,
// Bad hex input
#[error("Bad hex input")]
BadHexInput,
@ -23,6 +27,10 @@ pub enum Error {
#[error("Config: {0}")]
Config(#[from] ron::error::SpannedError),
// Crypto
#[error("Crypto: {0}")]
Crypto(#[from] secp256k1::Error),
// Duplicate event
#[error("Duplicate")]
Duplicate,

View File

@ -186,7 +186,10 @@ impl WebSocketService {
}
async fn validate_event(event: &Event<'_>) -> Result<bool, Error> {
// FIXME: check signature
// Verify event is valid
if GLOBALS.config.read().await.verify_events {
event.verify()?;
}
// Accept relay lists from anybody
if event.kind() == Kind(10002) {

View File

@ -125,6 +125,35 @@ impl<'a> Event<'a> {
output.extend(br#""}"#);
Ok(output)
}
pub fn verify(&self) -> Result<(), Error> {
use secp256k1::hashes::{sha256, Hash};
use secp256k1::schnorr::Signature;
use secp256k1::{Message, XOnlyPublicKey};
let signable = format!(
r#"[0,"{}",{},{},{},"{}"]"#,
self.pubkey(),
self.created_at(),
self.kind(),
self.tags()?,
unsafe { std::str::from_utf8_unchecked(self.content()) },
);
let hash = sha256::Hash::hash(signable.as_bytes());
let hashref = <sha256::Hash as AsRef<[u8]>>::as_ref(&hash);
if hashref != self.id().as_slice() {
return Err(Error::BadEventId);
}
let pubkey = XOnlyPublicKey::from_slice(self.pubkey().as_slice())?;
let sig = Signature::from_slice(self.sig().as_slice())?;
let message = Message::from_digest_slice(hashref)?;
sig.verify(&message, &pubkey)?;
Ok(())
}
}
impl fmt::Display for Event<'_> {