Use multibase encoding for integrity proofs

This commit is contained in:
silverpill 2022-11-19 15:08:40 +00:00
parent 4a5bcba127
commit 49a55d888f
3 changed files with 31 additions and 29 deletions

View file

@ -12,11 +12,14 @@ use crate::identity::{
PROOF_TYPE_JCS_RSA, PROOF_TYPE_JCS_RSA,
}, },
}; };
use crate::utils::canonicalization::{ use crate::utils::{
canonicalize_object, canonicalization::{
CanonicalizationError, canonicalize_object,
CanonicalizationError,
},
crypto_rsa::create_rsa_signature,
multibase::encode_multibase_base58btc,
}; };
use crate::utils::crypto_rsa::create_rsa_signature;
pub(super) const PROOF_KEY: &str = "proof"; pub(super) const PROOF_KEY: &str = "proof";
pub(super) const PROOF_PURPOSE: &str = "assertionMethod"; pub(super) const PROOF_PURPOSE: &str = "assertionMethod";
@ -44,7 +47,7 @@ impl IntegrityProof {
proof_purpose: PROOF_PURPOSE.to_string(), proof_purpose: PROOF_PURPOSE.to_string(),
verification_method: signer_key_id.to_string(), verification_method: signer_key_id.to_string(),
created: Utc::now(), created: Utc::now(),
proof_value: base64::encode(signature), proof_value: encode_multibase_base58btc(signature),
} }
} }
@ -57,7 +60,7 @@ impl IntegrityProof {
proof_purpose: PROOF_PURPOSE.to_string(), proof_purpose: PROOF_PURPOSE.to_string(),
verification_method: signer.to_string(), verification_method: signer.to_string(),
created: Utc::now(), created: Utc::now(),
proof_value: base64::encode(signature), proof_value: encode_multibase_base58btc(signature),
} }
} }
@ -70,7 +73,7 @@ impl IntegrityProof {
proof_purpose: PROOF_PURPOSE.to_string(), proof_purpose: PROOF_PURPOSE.to_string(),
verification_method: signer.to_string(), verification_method: signer.to_string(),
created: Utc::now(), created: Utc::now(),
proof_value: base64::encode(signature), proof_value: encode_multibase_base58btc(signature),
} }
} }
} }
@ -157,7 +160,7 @@ mod tests {
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();
// Put * in place of date to avoid escaping all curly brackets // Put * in place of date to avoid escaping all curly brackets
let expected_result = r#"{"actor":"https://example.org/users/test","id":"https://example.org/objects/1","object":{"content":"test","type":"Note"},"proof":{"created":"*","proofPurpose":"assertionMethod","proofValue":"P4ye1hDvrGQCCClzHfCU9xobMAeqlUfgEWGlZfOTE3WmjH8JC/OJwlsjUMOUwTVlyKStp+AY+zzU4z6mjZN0Ug==","type":"JcsRsaSignature2022","verificationMethod":"https://example.org/users/test#main-key"},"to":["https://example.org/users/yyy","https://example.org/users/xxx"],"type":"Create"}"#; let expected_result = r#"{"actor":"https://example.org/users/test","id":"https://example.org/objects/1","object":{"content":"test","type":"Note"},"proof":{"created":"*","proofPurpose":"assertionMethod","proofValue":"z2Gh9LYrXjSqFrkia6gMg7xp2wftn1hqmYeEXxrsH9Eh6agB2VYraSYrDoSufbXEHnnyHMCoDSAriLpVacj6E4LFK","type":"JcsRsaSignature2022","verificationMethod":"https://example.org/users/test#main-key"},"to":["https://example.org/users/yyy","https://example.org/users/xxx"],"type":"Create"}"#;
assert_eq!( assert_eq!(
serde_json::to_string(&result).unwrap(), serde_json::to_string(&result).unwrap(),
expected_result.replace('*', signature_date), expected_result.replace('*', signature_date),

View file

@ -13,11 +13,14 @@ use crate::identity::{
PROOF_TYPE_JCS_RSA, PROOF_TYPE_JCS_RSA,
}, },
}; };
use crate::utils::canonicalization::{ use crate::utils::{
canonicalize_object, canonicalization::{
CanonicalizationError, canonicalize_object,
CanonicalizationError,
},
crypto_rsa::verify_rsa_signature,
multibase::{decode_multibase_base58btc, MultibaseError},
}; };
use crate::utils::crypto_rsa::verify_rsa_signature;
use super::create::{ use super::create::{
IntegrityProof, IntegrityProof,
PROOF_KEY, PROOF_KEY,
@ -33,7 +36,7 @@ pub enum JsonSigner {
pub struct SignatureData { pub struct SignatureData {
pub signer: JsonSigner, pub signer: JsonSigner,
pub message: String, pub message: String,
pub signature: String, pub signature: Vec<u8>,
} }
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
@ -51,7 +54,7 @@ pub enum JsonSignatureVerificationError {
CanonicalizationError(#[from] CanonicalizationError), CanonicalizationError(#[from] CanonicalizationError),
#[error("invalid encoding")] #[error("invalid encoding")]
InvalidEncoding(#[from] base64::DecodeError), InvalidEncoding(#[from] MultibaseError),
#[error("invalid signature")] #[error("invalid signature")]
InvalidSignature, InvalidSignature,
@ -91,10 +94,11 @@ pub fn get_json_signature(
}, },
}; };
let message = canonicalize_object(&object)?; let message = canonicalize_object(&object)?;
let signature = decode_multibase_base58btc(&proof.proof_value)?;
let signature_data = SignatureData { let signature_data = SignatureData {
signer: signer, signer: signer,
message: message, message: message,
signature: proof.proof_value, signature: signature,
}; };
Ok(signature_data) Ok(signature_data)
} }
@ -103,11 +107,10 @@ pub fn verify_rsa_json_signature(
signature_data: &SignatureData, signature_data: &SignatureData,
signer_key: &RsaPublicKey, signer_key: &RsaPublicKey,
) -> Result<(), VerificationError> { ) -> Result<(), VerificationError> {
let signature = base64::decode(&signature_data.signature)?;
let is_valid_signature = verify_rsa_signature( let is_valid_signature = verify_rsa_signature(
signer_key, signer_key,
&signature_data.message, &signature_data.message,
&signature, &signature_data.signature,
); );
if !is_valid_signature { if !is_valid_signature {
return Err(VerificationError::InvalidSignature); return Err(VerificationError::InvalidSignature);
@ -118,10 +121,9 @@ pub fn verify_rsa_json_signature(
pub fn verify_eip191_json_signature( pub fn verify_eip191_json_signature(
signer: &DidPkh, signer: &DidPkh,
message: &str, message: &str,
signature: &str, signature: &[u8],
) -> Result<(), VerificationError> { ) -> Result<(), VerificationError> {
let signature_bin = base64::decode(signature)?; let signature_hex = hex::encode(signature);
let signature_hex = hex::encode(&signature_bin);
verify_eip191_signature(signer, message, &signature_hex) verify_eip191_signature(signer, message, &signature_hex)
.map_err(|_| VerificationError::InvalidSignature) .map_err(|_| VerificationError::InvalidSignature)
} }
@ -129,10 +131,9 @@ pub fn verify_eip191_json_signature(
pub fn verify_ed25519_json_signature( pub fn verify_ed25519_json_signature(
signer: &DidKey, signer: &DidKey,
message: &str, message: &str,
signature: &str, signature: &[u8],
) -> Result<(), VerificationError> { ) -> Result<(), VerificationError> {
let signature_bin = base64::decode(signature)?; verify_ed25519_signature(signer, message, signature)
verify_ed25519_signature(signer, message, &signature_bin)
.map_err(|_| VerificationError::InvalidSignature) .map_err(|_| VerificationError::InvalidSignature)
} }
@ -154,7 +155,7 @@ mod tests {
"proofPurpose": "assertionMethod", "proofPurpose": "assertionMethod",
"verificationMethod": "did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a", "verificationMethod": "did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a",
"created": "2020-11-05T19:23:24Z", "created": "2020-11-05T19:23:24Z",
"proofValue": "xxx", "proofValue": "zE5J",
}, },
}); });
let signature_data = get_json_signature(&signed_object).unwrap(); let signature_data = get_json_signature(&signed_object).unwrap();
@ -163,7 +164,7 @@ mod tests {
"0xb9c5714089478a327f09197987f16f9e5d936e8a", "0xb9c5714089478a327f09197987f16f9e5d936e8a",
))); )));
assert_eq!(signature_data.signer, expected_signer); assert_eq!(signature_data.signer, expected_signer);
assert_eq!(signature_data.signature, "xxx"); assert_eq!(hex::encode(signature_data.signature), "abcd");
} }
#[test] #[test]

View file

@ -296,16 +296,14 @@ async fn send_signed_update(
Did::Key(signer) => { Did::Key(signer) => {
let signature_bin = parse_minisign_signature(&data.signature) let signature_bin = parse_minisign_signature(&data.signature)
.map_err(|_| ValidationError("invalid encoding"))?; .map_err(|_| ValidationError("invalid encoding"))?;
let signature_b64 = base64::encode(&signature_bin); verify_ed25519_json_signature(&signer, &canonical_json, &signature_bin)
verify_ed25519_json_signature(&signer, &canonical_json, &signature_b64)
.map_err(|_| ValidationError("invalid signature"))?; .map_err(|_| ValidationError("invalid signature"))?;
IntegrityProof::jcs_ed25519(&signer, &signature_bin) IntegrityProof::jcs_ed25519(&signer, &signature_bin)
}, },
Did::Pkh(signer) => { Did::Pkh(signer) => {
let signature_bin = hex::decode(&data.signature) let signature_bin = hex::decode(&data.signature)
.map_err(|_| ValidationError("invalid encoding"))?; .map_err(|_| ValidationError("invalid encoding"))?;
let signature_b64 = base64::encode(&signature_bin); verify_eip191_json_signature(&signer, &canonical_json, &signature_bin)
verify_eip191_json_signature(&signer, &canonical_json, &signature_b64)
.map_err(|_| ValidationError("invalid signature"))?; .map_err(|_| ValidationError("invalid signature"))?;
IntegrityProof::jcs_eip191(&signer, &signature_bin) IntegrityProof::jcs_eip191(&signer, &signature_bin)
}, },