Write warning to log when signature creation date is not known

This commit is contained in:
silverpill 2022-09-12 21:02:33 +00:00
parent 458ca3fc3d
commit d0f97a33b3
2 changed files with 19 additions and 1 deletions

View file

@ -4,6 +4,8 @@ use rsa::RsaPrivateKey;
use crate::utils::crypto::{sign_message, get_message_digest}; use crate::utils::crypto::{sign_message, get_message_digest};
pub const SIGNATURE_ALGORITHM: &str = "rsa-sha256";
pub struct SignatureHeaders { pub struct SignatureHeaders {
pub host: String, pub host: String,
pub date: String, pub date: String,
@ -63,8 +65,9 @@ pub fn create_http_signature(
.collect::<Vec<String>>().join(" "); .collect::<Vec<String>>().join(" ");
let signature_parameter = sign_message(actor_key, &message)?; let signature_parameter = sign_message(actor_key, &message)?;
let signature_header = format!( let signature_header = format!(
r#"keyId="{}",algorithm="rsa-sha256",headers="{}",signature="{}""#, r#"keyId="{}",algorithm="{}",headers="{}",signature="{}""#,
actor_key_id, actor_key_id,
SIGNATURE_ALGORITHM,
headers_parameter, headers_parameter,
signature_parameter, signature_parameter,
); );

View file

@ -4,6 +4,7 @@ use actix_web::{
HttpRequest, HttpRequest,
http::{Method, Uri, header::HeaderMap}, http::{Method, Uri, header::HeaderMap},
}; };
use chrono::{DateTime, TimeZone, Utc};
use regex::Regex; use regex::Regex;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
@ -48,6 +49,7 @@ struct SignatureData {
pub key_id: String, pub key_id: String,
pub message: String, // reconstructed message pub message: String, // reconstructed message
pub signature: String, // base64-encoded signature pub signature: String, // base64-encoded signature
pub created_at: Option<DateTime<Utc>>,
} }
const SIGNATURE_PARAMETER_RE: &str = r#"^(?P<key>[a-zA-Z]+)="(?P<value>.+)"$"#; const SIGNATURE_PARAMETER_RE: &str = r#"^(?P<key>[a-zA-Z]+)="(?P<value>.+)"$"#;
@ -81,6 +83,14 @@ fn parse_http_signature(
let signature = signature_parameters.get("signature") let signature = signature_parameters.get("signature")
.ok_or(VerificationError::ParseError("signature is missing"))? .ok_or(VerificationError::ParseError("signature is missing"))?
.to_owned(); .to_owned();
let maybe_created_at = if let Some(created_at) = signature_parameters.get("created") {
created_at.parse().ok().map(|ts| Utc.timestamp(ts, 0))
} else {
request_headers.get("date")
.and_then(|header| header.to_str().ok())
.and_then(|date| DateTime::parse_from_rfc2822(date).ok())
.map(|datetime| datetime.with_timezone(&Utc))
};
let mut message_parts = vec![]; let mut message_parts = vec![];
for header in headers_parameter.split(' ') { for header in headers_parameter.split(' ') {
@ -113,6 +123,7 @@ fn parse_http_signature(
key_id, key_id,
message, message,
signature, signature,
created_at: maybe_created_at,
}; };
Ok(signature_data) Ok(signature_data)
} }
@ -138,6 +149,9 @@ pub async fn verify_http_signature(
request.uri(), request.uri(),
request.headers(), request.headers(),
)?; )?;
if signature_data.created_at.is_none() {
log::warn!("signature creation time is missing");
};
let actor_id = key_id_to_actor_id(&signature_data.key_id)?; let actor_id = key_id_to_actor_id(&signature_data.key_id)?;
let actor_profile = if no_fetch { let actor_profile = if no_fetch {
@ -210,6 +224,7 @@ mod tests {
"(request-target): post /user/123/inbox\nhost: example.com", "(request-target): post /user/123/inbox\nhost: example.com",
); );
assert_eq!(signature_data.signature, "test"); assert_eq!(signature_data.signature, "test");
assert_eq!(signature_data.created_at.is_some(), false);
} }
#[test] #[test]