Decode multibase value when parsing did:key
This commit is contained in:
parent
1bfb951df8
commit
efb51c1be6
3 changed files with 54 additions and 5 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -446,6 +446,12 @@ dependencies = [
|
|||
"alloc-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.1"
|
||||
|
@ -1681,6 +1687,7 @@ dependencies = [
|
|||
"ammonia",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bs58",
|
||||
"chrono",
|
||||
"clap",
|
||||
"comrak",
|
||||
|
|
|
@ -21,6 +21,8 @@ ammonia = "3.2.0"
|
|||
anyhow = "1.0.58"
|
||||
# Used for working with RSA keys, HTTP signatures and file uploads
|
||||
base64 = "0.13.0"
|
||||
# Used to decode base58btc
|
||||
bs58 = "0.4.0"
|
||||
# Used for working with dates
|
||||
chrono = { version = "0.4.22", features = ["serde"] }
|
||||
# Used to build admin CLI tool
|
||||
|
|
|
@ -10,7 +10,45 @@ const DID_KEY_RE: &str = r"did:key:(?P<key>z[a-km-zA-HJ-NP-Z1-9]+)";
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct DidKey {
|
||||
pub key: String,
|
||||
pub key: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum MultibaseError {
|
||||
#[error("invalid base string")]
|
||||
InvalidBaseString,
|
||||
|
||||
#[error("unknown base")]
|
||||
UnknownBase,
|
||||
|
||||
#[error(transparent)]
|
||||
DecodeError(#[from] bs58::decode::Error),
|
||||
}
|
||||
|
||||
/// Decodes multibase base58 (bitcoin) value
|
||||
/// https://github.com/multiformats/multibase
|
||||
fn decode_multibase_base58btc(value: &str)
|
||||
-> Result<Vec<u8>, MultibaseError>
|
||||
{
|
||||
let base = value.chars().next()
|
||||
.ok_or(MultibaseError::InvalidBaseString)?;
|
||||
// z == base58btc
|
||||
// https://github.com/multiformats/multibase#multibase-table
|
||||
if base.to_string() != "z" {
|
||||
return Err(MultibaseError::UnknownBase);
|
||||
};
|
||||
let encoded_data = &value[base.len_utf8()..];
|
||||
let data = bs58::decode(encoded_data)
|
||||
.with_alphabet(bs58::Alphabet::BITCOIN)
|
||||
.into_vec()?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn encode_multibase_base58btc(value: &[u8]) -> String {
|
||||
let result = bs58::encode(value)
|
||||
.with_alphabet(bs58::Alphabet::BITCOIN)
|
||||
.into_string();
|
||||
format!("z{}", result)
|
||||
}
|
||||
|
||||
impl FromStr for DidKey {
|
||||
|
@ -19,16 +57,17 @@ impl FromStr for DidKey {
|
|||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
let did_key_re = Regex::new(DID_KEY_RE).unwrap();
|
||||
let caps = did_key_re.captures(value).ok_or(DidParseError)?;
|
||||
let did_key = Self {
|
||||
key: caps["key"].to_string(),
|
||||
};
|
||||
let key = decode_multibase_base58btc(&caps["key"])
|
||||
.map_err(|_| DidParseError)?;
|
||||
let did_key = Self { key };
|
||||
Ok(did_key)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DidKey {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let did_str = format!("did:key:{}", self.key);
|
||||
let encoded_key = encode_multibase_base58btc(&self.key);
|
||||
let did_str = format!("did:key:{}", encoded_key);
|
||||
write!(formatter, "{}", did_str)
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +80,7 @@ mod tests {
|
|||
fn test_did_key_string_conversion() {
|
||||
let did_str = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
|
||||
let did_key: DidKey = did_str.parse().unwrap();
|
||||
assert_eq!(did_key.key.len(), 34); // Ed25519 public key
|
||||
assert_eq!(did_key.to_string(), did_str);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue