refactor(types): move UserIdentityDesc verification into types crate

This commit is contained in:
oxalica 2024-09-19 02:34:21 -04:00
parent fac380fe55
commit 82ab7f7d2c
2 changed files with 67 additions and 52 deletions

View file

@ -1,12 +1,10 @@
use std::num::NonZero;
use std::time::{Duration, Instant};
use anyhow::{anyhow, ensure, Context};
use anyhow::{anyhow, ensure};
use axum::http::{HeaderMap, HeaderName, StatusCode};
use blah_types::identity::{IdUrl, UserIdentityDesc};
use blah_types::{
get_timestamp, PubKey, Signed, UserRegisterPayload, X_BLAH_DIFFICULTY, X_BLAH_NONCE,
};
use blah_types::{get_timestamp, Signed, UserRegisterPayload, X_BLAH_DIFFICULTY, X_BLAH_NONCE};
use http_body_util::BodyExt;
use parking_lot::Mutex;
use rand::rngs::OsRng;
@ -246,7 +244,11 @@ pub async fn user_register(
}
};
if let Err(err) = validate_id_desc(&reg.id_url, &reg.id_key, &id_desc, fetch_time) {
if let Err(err) = (|| {
ensure!(reg.id_key == id_desc.id_key, "id_key mismatch");
id_desc.verify(Some(&reg.id_url), fetch_time)?;
Ok(())
})() {
return Err(error_response!(
StatusCode::UNAUTHORIZED,
"invalid_id_description",
@ -314,53 +316,6 @@ pub async fn user_register(
Ok(StatusCode::NO_CONTENT)
}
fn validate_id_desc(
id_url: &IdUrl,
id_key: &PubKey,
id_desc: &UserIdentityDesc,
now: u64,
) -> anyhow::Result<()> {
ensure!(*id_key == id_desc.id_key, "id_key mismatch");
ensure!(
*id_key == id_desc.profile.signee.user.id_key,
"profile id_key mismatch",
);
let profile_signing_key = &id_desc.profile.signee.user.act_key;
let mut profile_signed = false;
for (i, signed_kdesc) in id_desc.act_keys.iter().enumerate() {
let kdesc = &signed_kdesc.signee.payload;
(|| {
// act_key itself is signed by id_key, so both are id_key here.
ensure!(
signed_kdesc.signee.user.id_key == *id_key
&& signed_kdesc.signee.user.act_key == *id_key,
"not signed by id_key",
);
signed_kdesc
.verify()
.context("signature verification failed")?;
if now < kdesc.expire_time && *profile_signing_key == kdesc.act_key {
profile_signed = true;
}
Ok(())
})()
.map_err(|err| anyhow!("invalid act_key[{}] {}: {}", i, kdesc.act_key, err))?;
}
ensure!(profile_signed, "profile is not signed by valid act_keys");
id_desc
.profile
.verify()
.context("profile signature verification failed")?;
ensure!(
id_desc.profile.signee.payload.id_urls == std::slice::from_ref(id_url),
"id_url list must consists of a single matching id_url",
);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;