Return error if trying to sign activity which is already signed
This commit is contained in:
parent
b700a8ac6d
commit
3dbb922f3c
3 changed files with 26 additions and 5 deletions
|
@ -13,6 +13,7 @@ use crate::http_signatures::create::{
|
||||||
HttpSignatureError,
|
HttpSignatureError,
|
||||||
};
|
};
|
||||||
use crate::json_signatures::create::{
|
use crate::json_signatures::create::{
|
||||||
|
is_object_signed,
|
||||||
sign_object,
|
sign_object,
|
||||||
JsonSignatureError,
|
JsonSignatureError,
|
||||||
};
|
};
|
||||||
|
@ -122,7 +123,14 @@ async fn deliver_activity_worker(
|
||||||
),
|
),
|
||||||
ACTOR_KEY_SUFFIX,
|
ACTOR_KEY_SUFFIX,
|
||||||
);
|
);
|
||||||
let activity_signed = sign_object(&activity, &actor_key, &actor_key_id)?;
|
let activity_value = serde_json::to_value(&activity)?;
|
||||||
|
let activity_signed = if is_object_signed(&activity_value) {
|
||||||
|
log::warn!("activity is already signed");
|
||||||
|
activity_value
|
||||||
|
} else {
|
||||||
|
sign_object(&activity_value, &actor_key, &actor_key_id)?
|
||||||
|
};
|
||||||
|
|
||||||
let activity_json = serde_json::to_string(&activity_signed)?;
|
let activity_json = serde_json::to_string(&activity_signed)?;
|
||||||
if recipients.is_empty() {
|
if recipients.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -19,6 +19,8 @@ pub struct Proof {
|
||||||
pub proof_value: String,
|
pub proof_value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const PROOF_KEY: &str = "proof";
|
||||||
|
|
||||||
// Similar to https://identity.foundation/JcsEd25519Signature2020/
|
// Similar to https://identity.foundation/JcsEd25519Signature2020/
|
||||||
// - Canonicalization algorithm: JCS
|
// - Canonicalization algorithm: JCS
|
||||||
// - Digest algorithm: SHA-256
|
// - Digest algorithm: SHA-256
|
||||||
|
@ -40,10 +42,13 @@ pub enum JsonSignatureError {
|
||||||
|
|
||||||
#[error("invalid object")]
|
#[error("invalid object")]
|
||||||
InvalidObject,
|
InvalidObject,
|
||||||
|
|
||||||
|
#[error("already signed")]
|
||||||
|
AlreadySigned,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign_object(
|
pub fn sign_object(
|
||||||
object: &impl Serialize,
|
object: &Value,
|
||||||
signer_key: &RsaPrivateKey,
|
signer_key: &RsaPrivateKey,
|
||||||
signer_key_id: &str,
|
signer_key_id: &str,
|
||||||
) -> Result<Value, JsonSignatureError> {
|
) -> Result<Value, JsonSignatureError> {
|
||||||
|
@ -63,10 +68,17 @@ pub fn sign_object(
|
||||||
let mut object_value = serde_json::to_value(object)?;
|
let mut object_value = serde_json::to_value(object)?;
|
||||||
let object_map = object_value.as_object_mut()
|
let object_map = object_value.as_object_mut()
|
||||||
.ok_or(JsonSignatureError::InvalidObject)?;
|
.ok_or(JsonSignatureError::InvalidObject)?;
|
||||||
object_map.insert("proof".to_string(), proof_value);
|
if object_map.contains_key(PROOF_KEY) {
|
||||||
|
return Err(JsonSignatureError::AlreadySigned);
|
||||||
|
};
|
||||||
|
object_map.insert(PROOF_KEY.to_string(), proof_value);
|
||||||
Ok(object_value)
|
Ok(object_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_object_signed(object: &Value) -> bool {
|
||||||
|
object.get(PROOF_KEY).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
@ -92,6 +104,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
let result = sign_object(&object, &signer_key, signer_key_id).unwrap();
|
let result = sign_object(&object, &signer_key, signer_key_id).unwrap();
|
||||||
|
|
||||||
|
assert!(is_object_signed(&result));
|
||||||
assert_eq!(result["actor"], object["actor"]);
|
assert_eq!(result["actor"], object["actor"]);
|
||||||
assert_eq!(result["object"], object["object"]);
|
assert_eq!(result["object"], object["object"]);
|
||||||
let signature_date = result["proof"]["created"].as_str().unwrap();
|
let signature_date = result["proof"]["created"].as_str().unwrap();
|
||||||
|
|
|
@ -3,7 +3,7 @@ use serde_json::Value;
|
||||||
|
|
||||||
use crate::utils::crypto::verify_signature;
|
use crate::utils::crypto::verify_signature;
|
||||||
use super::canonicalization::{canonicalize_object, CanonicalizationError};
|
use super::canonicalization::{canonicalize_object, CanonicalizationError};
|
||||||
use super::create::{Proof, PROOF_TYPE, PROOF_PURPOSE};
|
use super::create::{Proof, PROOF_KEY, PROOF_TYPE, PROOF_PURPOSE};
|
||||||
|
|
||||||
pub struct SignatureData {
|
pub struct SignatureData {
|
||||||
pub key_id: String,
|
pub key_id: String,
|
||||||
|
@ -40,7 +40,7 @@ pub fn get_json_signature(
|
||||||
let mut object = object.clone();
|
let mut object = object.clone();
|
||||||
let object_map = object.as_object_mut()
|
let object_map = object.as_object_mut()
|
||||||
.ok_or(VerificationError::InvalidObject)?;
|
.ok_or(VerificationError::InvalidObject)?;
|
||||||
let proof_value = object_map.remove("proof")
|
let proof_value = object_map.remove(PROOF_KEY)
|
||||||
.ok_or(VerificationError::NoProof)?;
|
.ok_or(VerificationError::NoProof)?;
|
||||||
let proof: Proof = serde_json::from_value(proof_value)
|
let proof: Proof = serde_json::from_value(proof_value)
|
||||||
.map_err(|_| VerificationError::InvalidProof("invalid proof"))?;
|
.map_err(|_| VerificationError::InvalidProof("invalid proof"))?;
|
||||||
|
|
Loading…
Reference in a new issue