From 0352b840f0ef0b8f57b343151b9d6ee08c716f74 Mon Sep 17 00:00:00 2001 From: Enrico Marconi <31142849+UMR1352@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:44:43 +0100 Subject: [PATCH] Support %-encoded characters in DID method id (#1303) --- identity_did/Cargo.toml | 2 +- identity_did/src/did.rs | 31 +++++++++++++++++++------------ identity_did/src/did_url.rs | 2 +- identity_did/src/error.rs | 16 ++++++++-------- identity_did/src/lib.rs | 2 +- identity_document/Cargo.toml | 2 +- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/identity_did/Cargo.toml b/identity_did/Cargo.toml index 31c636b70f..9b32efb13b 100644 --- a/identity_did/Cargo.toml +++ b/identity_did/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace = true description = "Agnostic implementation of the Decentralized Identifiers (DID) standard." [dependencies] -did_url = { version = "0.1", default-features = false, features = ["std", "serde"] } +did_url_parser = { version = "0.2.0", features = ["std", "serde"] } form_urlencoded = { version = "1.2.0", default-features = false, features = ["alloc"] } identity_core = { version = "=1.1.1", path = "../identity_core" } serde.workspace = true diff --git a/identity_did/src/did.rs b/identity_did/src/did.rs index eb07f61a08..de9cf61183 100644 --- a/identity_did/src/did.rs +++ b/identity_did/src/did.rs @@ -8,7 +8,7 @@ use core::fmt::Formatter; use core::str::FromStr; use std::hash::Hash; -use did_url::DID as BaseDIDUrl; +use did_url_parser::DID as BaseDIDUrl; use identity_core::common::KeyComparable; @@ -111,14 +111,7 @@ impl CoreDID { /// /// Returns `Err` if the input is not a valid [`DID`]. pub fn parse(input: impl AsRef) -> Result { - let base_did_url: BaseDIDUrl = BaseDIDUrl::parse(input).map_err(Error::from)?; - Self::try_from_base_did(base_did_url) - } - - /// Try convert a [`BaseDIDUrl`] into a [`CoreDID`]. - fn try_from_base_did(base_did_url: BaseDIDUrl) -> Result { - Self::check_validity(&base_did_url)?; - Ok(Self(base_did_url)) + BaseDIDUrl::parse(input).map(Self).map_err(Error::from) } /// Set the method name of the [`DID`]. @@ -145,9 +138,23 @@ impl CoreDID { /// Validates whether a string is a valid [`DID`] method-id. pub fn valid_method_id(value: &str) -> Result<(), Error> { - if !value.chars().all(is_char_method_id) { - return Err(Error::InvalidMethodId); + // if !value.chars().all(is_char_method_id) { + // return Err(Error::InvalidMethodId); + // } + let mut chars = value.chars(); + while let Some(c) = chars.next() { + match c { + '%' => { + let digits = chars.clone().take(2).collect::(); + u8::from_str_radix(&digits, 16).map_err(|_| Error::InvalidMethodId)?; + chars.next(); + chars.next(); + } + c if is_char_method_id(c) => (), + _ => return Err(Error::InvalidMethodId), + } } + Ok(()) } @@ -185,7 +192,7 @@ impl TryFrom for CoreDID { type Error = Error; fn try_from(base_did_url: BaseDIDUrl) -> Result { - Self::try_from_base_did(base_did_url) + Ok(Self(base_did_url)) } } diff --git a/identity_did/src/did_url.rs b/identity_did/src/did_url.rs index 60c7d6c84e..0e8eebcace 100644 --- a/identity_did/src/did_url.rs +++ b/identity_did/src/did_url.rs @@ -10,7 +10,7 @@ use std::cmp::Ordering; use std::hash::Hash; use std::hash::Hasher; -use did_url::DID as BaseDIDUrl; +use did_url_parser::DID as BaseDIDUrl; use identity_core::common::KeyComparable; use identity_core::common::Url; diff --git a/identity_did/src/error.rs b/identity_did/src/error.rs index b2c1ab1469..e9bf4f51b4 100644 --- a/identity_did/src/error.rs +++ b/identity_did/src/error.rs @@ -23,15 +23,15 @@ pub enum Error { Other(&'static str), } -impl From for Error { - fn from(error: did_url::Error) -> Self { +impl From for Error { + fn from(error: did_url_parser::Error) -> Self { match error { - did_url::Error::InvalidFragment => Self::InvalidFragment, - did_url::Error::InvalidMethodId => Self::InvalidMethodId, - did_url::Error::InvalidMethodName => Self::InvalidMethodName, - did_url::Error::InvalidPath => Self::InvalidPath, - did_url::Error::InvalidQuery => Self::InvalidQuery, - did_url::Error::InvalidScheme => Self::InvalidScheme, + did_url_parser::Error::InvalidFragment => Self::InvalidFragment, + did_url_parser::Error::InvalidMethodId => Self::InvalidMethodId, + did_url_parser::Error::InvalidMethodName => Self::InvalidMethodName, + did_url_parser::Error::InvalidPath => Self::InvalidPath, + did_url_parser::Error::InvalidQuery => Self::InvalidQuery, + did_url_parser::Error::InvalidScheme => Self::InvalidScheme, error => Self::Other(error.as_str()), } } diff --git a/identity_did/src/lib.rs b/identity_did/src/lib.rs index f6fb2c368c..9289419211 100644 --- a/identity_did/src/lib.rs +++ b/identity_did/src/lib.rs @@ -23,7 +23,7 @@ mod error; pub use crate::did_url::DIDUrl; pub use crate::did_url::RelativeDIDUrl; -pub use ::did_url::DID as BaseDIDUrl; +pub use ::did_url_parser::DID as BaseDIDUrl; pub use did::CoreDID; pub use did::DID; pub use error::Error; diff --git a/identity_document/Cargo.toml b/identity_document/Cargo.toml index 6605cc8325..c2fceac707 100644 --- a/identity_document/Cargo.toml +++ b/identity_document/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true description = "Method-agnostic implementation of the Decentralized Identifiers (DID) standard." [dependencies] -did_url = { version = "0.1", default-features = false, features = ["std", "serde"] } +did_url_parser = { version = "0.2.0", features = ["std", "serde"] } identity_core = { version = "=1.1.1", path = "../identity_core" } identity_did = { version = "=1.1.1", path = "../identity_did" } identity_verification = { version = "=1.1.1", path = "../identity_verification", default-features = false }