diff --git a/src/activitypub/actors/attachments.rs b/src/activitypub/actors/attachments.rs index c92454e..4cac006 100644 --- a/src/activitypub/actors/attachments.rs +++ b/src/activitypub/actors/attachments.rs @@ -11,7 +11,7 @@ use crate::frontend::get_subscription_page_url; use crate::identity::{ claims::create_identity_claim, did::Did, - minisign::verify_minisign_signature, + minisign::verify_minisign_identity_proof, signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, }; use crate::models::profiles::types::{ @@ -55,7 +55,7 @@ pub fn parse_identity_proof( if proof_type != PROOF_TYPE_ID_MINISIGN { return Err(ValidationError("unknown proof type")); }; - verify_minisign_signature( + verify_minisign_identity_proof( did_key, &message, signature, diff --git a/src/activitypub/authentication.rs b/src/activitypub/authentication.rs index e56ad76..c4e5cc0 100644 --- a/src/activitypub/authentication.rs +++ b/src/activitypub/authentication.rs @@ -12,8 +12,8 @@ use crate::http_signatures::verify::{ use crate::identity::did::Did; use crate::json_signatures::verify::{ get_json_signature, + verify_ed25519_json_signature, verify_eip191_json_signature, - verify_minisign_json_signature, verify_rsa_json_signature, JsonSignatureVerificationError as JsonSignatureError, JsonSigner, @@ -153,7 +153,7 @@ pub async fn verify_signed_activity( if let Some(profile) = profiles.pop() { match did { Did::Key(did_key) => { - verify_minisign_json_signature( + verify_ed25519_json_signature( &did_key, &signature_data.message, &signature_data.signature, diff --git a/src/identity/minisign.rs b/src/identity/minisign.rs index 4857ec8..d9f8323 100644 --- a/src/identity/minisign.rs +++ b/src/identity/minisign.rs @@ -1,4 +1,6 @@ /// https://jedisct1.github.io/minisign/ +use std::convert::TryInto; + use blake2::{Blake2b512, Digest}; use ed25519_dalek::{ PublicKey, @@ -58,7 +60,7 @@ pub fn minisign_key_to_did(key_b64: &str) -> Result { // Signature format: // base64( || || ) -fn parse_minisign_signature(signature_b64: &str) +pub fn parse_minisign_signature(signature_b64: &str) -> Result<[u8; 64], ParseError> { let signature_bin = base64::decode(signature_b64)?; @@ -79,7 +81,7 @@ fn parse_minisign_signature(signature_b64: &str) Ok(signature) } -fn verify_ed25519_signature( +fn _verify_ed25519_signature( message: &str, signer: [u8; 32], signature: [u8; 64], @@ -105,7 +107,7 @@ pub enum VerificationError { SignatureError(#[from] SignatureError), } -pub fn verify_minisign_signature( +pub fn verify_minisign_identity_proof( signer: &DidKey, message: &str, signature: &str, @@ -113,7 +115,24 @@ pub fn verify_minisign_signature( let ed25519_key = signer.try_ed25519_key()?; let ed25519_signature = parse_minisign_signature(signature)?; let message = format!("{}\n", message); - verify_ed25519_signature( + _verify_ed25519_signature( + &message, + ed25519_key, + ed25519_signature, + )?; + Ok(()) +} + +pub fn verify_ed25519_signature( + signer: &DidKey, + message: &str, + signature: &[u8], +) -> Result<(), VerificationError> { + let ed25519_key = signer.try_ed25519_key()?; + let ed25519_signature = signature.try_into() + .map_err(|_| ParseError::InvalidSignatureLength)?; + let message = format!("{}\n", message); + _verify_ed25519_signature( &message, ed25519_key, ed25519_signature, @@ -133,6 +152,6 @@ mod tests { let minisign_signature = "RUSA58rRENpGFVKxdZGMG1WdIJ+dlyP83qOqw6GP0H/Li6Brug2A3mFKLtleIRLi6IIG0smzOlX5CEsisNnc897OUHIOSNLsQQs="; let signer = minisign_key_to_did(minisign_key).unwrap(); - verify_minisign_signature(&signer, message, minisign_signature).unwrap(); + verify_minisign_identity_proof(&signer, message, minisign_signature).unwrap(); } } diff --git a/src/identity/signatures.rs b/src/identity/signatures.rs index 80facbe..3bc5eea 100644 --- a/src/identity/signatures.rs +++ b/src/identity/signatures.rs @@ -15,5 +15,9 @@ 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"; +// Similar to Ed25519Signature2020 +// https://w3c-ccg.github.io/di-eddsa-2020/#ed25519signature2020 +// - Canonicalization algorithm: JCS +// - Digest algorithm: BLAKE2b-512 +// - Signature algorithm: EdDSA +pub const PROOF_TYPE_JCS_ED25519: &str = "MitraJcsEd25519Signature2022"; diff --git a/src/json_signatures/create.rs b/src/json_signatures/create.rs index 2ab0a8a..44408bc 100644 --- a/src/json_signatures/create.rs +++ b/src/json_signatures/create.rs @@ -7,8 +7,8 @@ use crate::identity::{ did_key::DidKey, did_pkh::DidPkh, signatures::{ + PROOF_TYPE_JCS_ED25519, PROOF_TYPE_JCS_EIP191, - PROOF_TYPE_JCS_MINISIGN, PROOF_TYPE_JCS_RSA, }, }; @@ -61,16 +61,16 @@ impl IntegrityProof { } } - pub fn jcs_minisign( + pub fn jcs_ed25519( signer: &DidKey, - signature: &str, + signature: &[u8], ) -> Self { Self { - proof_type: PROOF_TYPE_JCS_MINISIGN.to_string(), + proof_type: PROOF_TYPE_JCS_ED25519.to_string(), proof_purpose: PROOF_PURPOSE.to_string(), verification_method: signer.to_string(), created: Utc::now(), - proof_value: signature.to_string(), + proof_value: base64::encode(signature), } } } diff --git a/src/json_signatures/verify.rs b/src/json_signatures/verify.rs index 4f724ec..5cc50bf 100644 --- a/src/json_signatures/verify.rs +++ b/src/json_signatures/verify.rs @@ -6,10 +6,10 @@ use crate::identity::{ did::Did, did_key::DidKey, did_pkh::DidPkh, - minisign::verify_minisign_signature, + minisign::verify_ed25519_signature, signatures::{ + PROOF_TYPE_JCS_ED25519, PROOF_TYPE_JCS_EIP191, - PROOF_TYPE_JCS_MINISIGN, PROOF_TYPE_JCS_RSA, }, }; @@ -78,7 +78,7 @@ pub fn get_json_signature( .map_err(|_| VerificationError::InvalidProof("invalid DID"))?; JsonSigner::Did(Did::Pkh(did_pkh)) }, - PROOF_TYPE_JCS_MINISIGN => { + PROOF_TYPE_JCS_ED25519 => { let did_key: DidKey = proof.verification_method.parse() .map_err(|_| VerificationError::InvalidProof("invalid DID"))?; JsonSigner::Did(Did::Key(did_key)) @@ -126,12 +126,13 @@ pub fn verify_eip191_json_signature( .map_err(|_| VerificationError::InvalidSignature) } -pub fn verify_minisign_json_signature( +pub fn verify_ed25519_json_signature( signer: &DidKey, message: &str, signature: &str, ) -> Result<(), VerificationError> { - verify_minisign_signature(signer, message, signature) + let signature_bin = base64::decode(signature)?; + verify_ed25519_signature(signer, message, &signature_bin) .map_err(|_| VerificationError::InvalidSignature) } diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index 9573fa6..3dd8e50 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -27,15 +27,16 @@ use crate::identity::{ did_pkh::DidPkh, minisign::{ minisign_key_to_did, - verify_minisign_signature, + parse_minisign_signature, + verify_minisign_identity_proof, }, signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, }; use crate::json_signatures::{ create::{add_integrity_proof, IntegrityProof}, verify::{ + verify_ed25519_json_signature, verify_eip191_json_signature, - verify_minisign_json_signature, }, }; use crate::mastodon_api::oauth::auth::get_current_user; @@ -293,9 +294,12 @@ async fn send_signed_update( .map_err(|_| HttpError::InternalError)?; let proof = match signer { Did::Key(signer) => { - verify_minisign_json_signature(&signer, &canonical_json, &data.signature) + let signature_bin = parse_minisign_signature(&data.signature) + .map_err(|_| ValidationError("invalid encoding"))?; + let signature_b64 = base64::encode(&signature_bin); + verify_ed25519_json_signature(&signer, &canonical_json, &signature_b64) .map_err(|_| ValidationError("invalid signature"))?; - IntegrityProof::jcs_minisign(&signer, &data.signature) + IntegrityProof::jcs_ed25519(&signer, &signature_bin) }, Did::Pkh(signer) => { let signature_bin = hex::decode(&data.signature) @@ -382,7 +386,7 @@ async fn create_identity_proof( // Verify proof let proof_type = match did { Did::Key(ref did_key) => { - verify_minisign_signature( + verify_minisign_identity_proof( did_key, &message, &proof_data.signature,