Verify activities containing EIP-155 integrity proof

This commit is contained in:
silverpill 2022-11-02 12:16:10 +00:00
parent cdd3bfb6df
commit 7f9b2a8768
2 changed files with 84 additions and 21 deletions

View file

@ -12,10 +12,14 @@ use crate::http_signatures::verify::{
use crate::json_signatures::verify::{
get_json_signature,
verify_jcs_rsa_signature,
verify_jcs_eip191_signature,
JsonSignatureVerificationError as JsonSignatureError,
JsonSigner,
};
use crate::models::profiles::queries::get_profile_by_remote_actor_id;
use crate::models::profiles::queries::{
get_profile_by_remote_actor_id,
search_profiles_by_did_only,
};
use crate::models::profiles::types::DbActorProfile;
use crate::utils::crypto::deserialize_public_key;
use super::fetcher::helpers::get_or_import_profile_by_actor_id;
@ -108,25 +112,50 @@ pub async fn verify_signed_activity(
}
})?;
let JsonSigner::ActorKeyId(ref key_id) = signature_data.signer;
let actor_id = key_id_to_actor_id(key_id)?;
let actor_profile = match get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&config.media_dir(),
&actor_id,
).await {
Ok(profile) => profile,
Err(HandlerError::DatabaseError(error)) => return Err(error.into()),
Err(other_error) => {
return Err(AuthenticationError::ActorError(other_error.to_string()));
let actor_profile = match signature_data.signer {
JsonSigner::ActorKeyId(ref key_id) => {
let actor_id = key_id_to_actor_id(key_id)?;
let actor_profile = match get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&config.media_dir(),
&actor_id,
).await {
Ok(profile) => profile,
Err(HandlerError::DatabaseError(error)) => {
return Err(error.into());
},
Err(other_error) => {
return Err(AuthenticationError::ActorError(other_error.to_string()));
},
};
let actor = actor_profile.actor_json.as_ref()
.ok_or(AuthenticationError::ActorError("invalid profile".to_string()))?;
let public_key =
deserialize_public_key(&actor.public_key.public_key_pem)?;
verify_jcs_rsa_signature(&signature_data, &public_key)?;
actor_profile
},
JsonSigner::DidPkh(ref signer) => {
let mut profiles = search_profiles_by_did_only(db_client, signer).await?;
if profiles.len() > 1 {
log::info!(
"signer with multiple profiles ({})",
profiles.len(),
);
};
if let Some(profile) = profiles.pop() {
verify_jcs_eip191_signature(
signer,
&signature_data.message,
&signature_data.signature,
)?;
profile
} else {
return Err(AuthenticationError::ActorError("unknown signer".to_string()));
}
},
};
let actor = actor_profile.actor_json.as_ref()
.ok_or(AuthenticationError::ActorError("invalid profile".to_string()))?;
let public_key = deserialize_public_key(&actor.public_key.public_key_pem)?;
verify_jcs_rsa_signature(&signature_data, &public_key)?;
Ok(actor_profile)
}

View file

@ -10,6 +10,7 @@ use crate::utils::crypto::verify_signature;
use super::canonicalization::{canonicalize_object, CanonicalizationError};
use super::create::{
IntegrityProof,
PROOF_TYPE_JCS_EIP191,
PROOF_TYPE_JCS_RSA,
PROOF_KEY,
PROOF_PURPOSE,
@ -18,6 +19,7 @@ use super::create::{
#[derive(Debug, PartialEq)]
pub enum JsonSigner {
ActorKeyId(String),
DidPkh(DidPkh),
}
pub struct SignatureData {
@ -62,10 +64,19 @@ pub fn get_json_signature(
if proof.proof_purpose != PROOF_PURPOSE {
return Err(VerificationError::InvalidProof("invalid proof purpose"));
};
if proof.proof_type != PROOF_TYPE_JCS_RSA {
return Err(VerificationError::InvalidProof("unsupported proof type"));
let signer = match proof.proof_type.as_str() {
PROOF_TYPE_JCS_EIP191 => {
let did = proof.verification_method.parse()
.map_err(|_| VerificationError::InvalidProof("invalid DID"))?;
JsonSigner::DidPkh(did)
},
PROOF_TYPE_JCS_RSA => {
JsonSigner::ActorKeyId(proof.verification_method)
},
_ => {
return Err(VerificationError::InvalidProof("unsupported proof type"));
},
};
let signer = JsonSigner::ActorKeyId(proof.verification_method);
let message = canonicalize_object(&object)?;
let signature_data = SignatureData {
signer: signer,
@ -110,8 +121,31 @@ mod tests {
use serde_json::json;
use crate::json_signatures::create::sign_object;
use crate::utils::crypto::generate_weak_private_key;
use crate::utils::currencies::Currency;
use super::*;
#[test]
fn test_get_json_signature_eip155() {
let signed_object = json!({
"type": "Test",
"id": "https://example.org/objects/1",
"proof": {
"type": "JcsEip191Signature2022",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a",
"created": "2020-11-05T19:23:24Z",
"proofValue": "xxx",
},
});
let signature_data = get_json_signature(&signed_object).unwrap();
let expected_signer = JsonSigner::DidPkh(DidPkh::from_address(
&Currency::Ethereum,
"0xb9c5714089478a327f09197987f16f9e5d936e8a",
));
assert_eq!(signature_data.signer, expected_signer);
assert_eq!(signature_data.signature, "xxx");
}
#[test]
fn test_create_and_verify_signature() {
let signer_key = generate_weak_private_key().unwrap();