diff --git a/src/json_signatures/canonicalization.rs b/src/json_signatures/canonicalization.rs new file mode 100644 index 0000000..437b3e3 --- /dev/null +++ b/src/json_signatures/canonicalization.rs @@ -0,0 +1,13 @@ +use serde::Serialize; + +#[derive(thiserror::Error, Debug)] +#[error("canonicalization error")] +pub struct CanonicalizationError(#[from] serde_json::Error); + +/// JCS: https://www.rfc-editor.org/rfc/rfc8785 +pub fn canonicalize_object( + object: &impl Serialize, +) -> Result { + let object_str = serde_jcs::to_string(object)?; + Ok(object_str) +} diff --git a/src/json_signatures/create.rs b/src/json_signatures/create.rs index 7265fd0..744e0bf 100644 --- a/src/json_signatures/create.rs +++ b/src/json_signatures/create.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::utils::crypto::sign_message; +use super::canonicalization::{canonicalize_object, CanonicalizationError}; /// Data Integrity Proof /// https://w3c.github.io/vc-data-integrity/ @@ -31,6 +32,9 @@ pub enum JsonSignatureError { #[error(transparent)] JsonError(#[from] serde_json::Error), + #[error(transparent)] + CanonicalizationError(#[from] CanonicalizationError), + #[error("signing error")] SigningError(#[from] rsa::errors::Error), @@ -44,10 +48,9 @@ pub fn sign_object( signer_key_id: &str, ) -> Result { // Canonicalize - // JCS: https://www.rfc-editor.org/rfc/rfc8785 - let object_str = serde_jcs::to_string(object)?; + let message = canonicalize_object(object)?; // Sign - let signature_b64 = sign_message(signer_key, &object_str)?; + let signature_b64 = sign_message(signer_key, &message)?; // Insert proof let proof = Proof { proof_type: PROOF_TYPE.to_string(), diff --git a/src/json_signatures/mod.rs b/src/json_signatures/mod.rs index c414f99..bec976e 100644 --- a/src/json_signatures/mod.rs +++ b/src/json_signatures/mod.rs @@ -1,2 +1,3 @@ +mod canonicalization; pub mod create; pub mod verify; diff --git a/src/json_signatures/verify.rs b/src/json_signatures/verify.rs index 2ae2d32..05c2a70 100644 --- a/src/json_signatures/verify.rs +++ b/src/json_signatures/verify.rs @@ -2,6 +2,7 @@ use rsa::RsaPublicKey; use serde_json::Value; use crate::utils::crypto::verify_signature; +use super::canonicalization::{canonicalize_object, CanonicalizationError}; use super::create::{Proof, PROOF_TYPE, PROOF_PURPOSE}; pub struct SignatureData { @@ -21,8 +22,8 @@ pub enum JsonSignatureVerificationError { #[error("{0}")] InvalidProof(&'static str), - #[error("canonicalization error")] - CanonicalizationError, + #[error(transparent)] + CanonicalizationError(#[from] CanonicalizationError), #[error("invalid encoding")] InvalidEncoding(#[from] base64::DecodeError), @@ -48,11 +49,10 @@ pub fn get_json_signature( { return Err(VerificationError::InvalidProof("invalid proof")); }; - let canon = serde_jcs::to_string(&object) - .map_err(|_| VerificationError::CanonicalizationError)?; + let message = canonicalize_object(&object)?; let signature_data = SignatureData { key_id: proof.verification_method, - message: canon, + message: message, signature: proof.proof_value, }; Ok(signature_data)