diff --git a/src/activitypub/authentication.rs b/src/activitypub/authentication.rs index 64a5443..d616bb2 100644 --- a/src/activitypub/authentication.rs +++ b/src/activitypub/authentication.rs @@ -13,6 +13,7 @@ use crate::identity::did::Did; use crate::json_signatures::verify::{ get_json_signature, verify_eip191_json_signature, + verify_minisign_json_signature, verify_rsa_json_signature, JsonSignatureVerificationError as JsonSignatureError, JsonSigner, @@ -137,8 +138,7 @@ pub async fn verify_signed_activity( verify_rsa_json_signature(&signature_data, &public_key)?; actor_profile }, - JsonSigner::DidPkh(did_pkh) => { - let did = Did::Pkh(did_pkh.clone()); + JsonSigner::Did(did) => { let mut profiles: Vec<_> = search_profiles_by_did_only(db_client, &did) .await?.into_iter() // Exclude local profiles @@ -151,11 +151,22 @@ pub async fn verify_signed_activity( ); }; if let Some(profile) = profiles.pop() { - verify_eip191_json_signature( - &did_pkh, - &signature_data.message, - &signature_data.signature, - )?; + match did { + Did::Key(did_key) => { + verify_minisign_json_signature( + &did_key, + &signature_data.message, + &signature_data.signature, + )?; + }, + Did::Pkh(did_pkh) => { + verify_eip191_json_signature( + &did_pkh, + &signature_data.message, + &signature_data.signature, + )?; + }, + }; profile } else { return Err(AuthenticationError::ActorError("unknown signer".to_string())); diff --git a/src/identity/signatures.rs b/src/identity/signatures.rs index 1b2bce1..80facbe 100644 --- a/src/identity/signatures.rs +++ b/src/identity/signatures.rs @@ -14,3 +14,6 @@ pub const PROOF_TYPE_JCS_RSA: &str = "JcsRsaSignature2022"; // Similar to EthereumPersonalSignature2021 but with JCS pub const PROOF_TYPE_JCS_EIP191: &str ="JcsEip191Signature2022"; + +// Version 2022A +pub const PROOF_TYPE_JCS_MINISIGN: &str = "MitraJcsMinisignSignature2022A"; diff --git a/src/json_signatures/create.rs b/src/json_signatures/create.rs index e49b374..c475c6f 100644 --- a/src/json_signatures/create.rs +++ b/src/json_signatures/create.rs @@ -4,8 +4,13 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::identity::{ + did_key::DidKey, did_pkh::DidPkh, - signatures::{PROOF_TYPE_JCS_EIP191, PROOF_TYPE_JCS_RSA}, + signatures::{ + PROOF_TYPE_JCS_EIP191, + PROOF_TYPE_JCS_MINISIGN, + PROOF_TYPE_JCS_RSA, + }, }; use crate::utils::canonicalization::{ canonicalize_object, @@ -55,6 +60,19 @@ impl IntegrityProof { proof_value: signature.to_string(), } } + + pub fn jcs_minisign( + signer: &DidKey, + signature: &str, + ) -> Self { + Self { + proof_type: PROOF_TYPE_JCS_MINISIGN.to_string(), + proof_purpose: PROOF_PURPOSE.to_string(), + verification_method: signer.to_string(), + created: Utc::now(), + proof_value: signature.to_string(), + } + } } #[derive(thiserror::Error, Debug)] diff --git a/src/json_signatures/verify.rs b/src/json_signatures/verify.rs index c3e8ae7..0411990 100644 --- a/src/json_signatures/verify.rs +++ b/src/json_signatures/verify.rs @@ -3,8 +3,15 @@ use serde_json::Value; use crate::ethereum::identity::verify_eip191_signature; use crate::identity::{ + did::Did, + did_key::DidKey, did_pkh::DidPkh, - signatures::{PROOF_TYPE_JCS_EIP191, PROOF_TYPE_JCS_RSA}, + minisign::verify_minisign_signature, + signatures::{ + PROOF_TYPE_JCS_EIP191, + PROOF_TYPE_JCS_MINISIGN, + PROOF_TYPE_JCS_RSA, + }, }; use crate::utils::canonicalization::{ canonicalize_object, @@ -20,7 +27,7 @@ use super::create::{ #[derive(Debug, PartialEq)] pub enum JsonSigner { ActorKeyId(String), - DidPkh(DidPkh), + Did(Did), } pub struct SignatureData { @@ -67,9 +74,14 @@ pub fn get_json_signature( }; let signer = match proof.proof_type.as_str() { PROOF_TYPE_JCS_EIP191 => { - let did = proof.verification_method.parse() + let did_pkh: DidPkh = proof.verification_method.parse() .map_err(|_| VerificationError::InvalidProof("invalid DID"))?; - JsonSigner::DidPkh(did) + JsonSigner::Did(Did::Pkh(did_pkh)) + }, + PROOF_TYPE_JCS_MINISIGN => { + let did_key: DidKey = proof.verification_method.parse() + .map_err(|_| VerificationError::InvalidProof("invalid DID"))?; + JsonSigner::Did(Did::Key(did_key)) }, PROOF_TYPE_JCS_RSA => { JsonSigner::ActorKeyId(proof.verification_method) @@ -111,6 +123,15 @@ pub fn verify_eip191_json_signature( .map_err(|_| VerificationError::InvalidSignature) } +pub fn verify_minisign_json_signature( + signer: &DidKey, + message: &str, + signature: &str, +) -> Result<(), VerificationError> { + verify_minisign_signature(signer, message, signature) + .map_err(|_| VerificationError::InvalidSignature) +} + #[cfg(test)] mod tests { use serde_json::json; @@ -133,10 +154,10 @@ mod tests { }, }); let signature_data = get_json_signature(&signed_object).unwrap(); - let expected_signer = JsonSigner::DidPkh(DidPkh::from_address( + let expected_signer = JsonSigner::Did(Did::Pkh(DidPkh::from_address( &Currency::Ethereum, "0xb9c5714089478a327f09197987f16f9e5d936e8a", - )); + ))); assert_eq!(signature_data.signer, expected_signer); assert_eq!(signature_data.signature, "xxx"); } diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index a5ab54d..ed4ea7e 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -33,7 +33,10 @@ use crate::identity::{ }; use crate::json_signatures::{ create::{add_integrity_proof, IntegrityProof}, - verify::verify_eip191_json_signature, + verify::{ + verify_eip191_json_signature, + verify_minisign_json_signature, + }, }; use crate::mastodon_api::oauth::auth::get_current_user; use crate::mastodon_api::pagination::get_paginated_response; @@ -267,7 +270,11 @@ async fn send_signed_update( let canonical_json = canonicalize_object(&activity) .map_err(|_| HttpError::InternalError)?; let proof = match signer { - Did::Key(_) => return Err(ValidationError("unsupported DID type").into()), + Did::Key(signer) => { + verify_minisign_json_signature(&signer, &canonical_json, &data.signature) + .map_err(|_| ValidationError("invalid signature"))?; + IntegrityProof::jcs_minisign(&signer, &data.signature) + }, Did::Pkh(signer) => { verify_eip191_json_signature(&signer, &canonical_json, &data.signature) .map_err(|_| ValidationError("invalid signature"))?;