For now, only did-web.
H3V4EM4IBB7YSJV63CXX33B4FJFXNGH2QYQSBKDC7HLMDPBQ2H5QC // Copyright © 2023 Kim Altintop <kim@eagain.io>// SPDX-License-Identifier: GPL-2.0-onlyuse core::fmt;use std::{collections::HashMap,iter,ops::Deref,str::FromStr,};use base64::{engine::general_purpose::URL_SAFE_NO_PAD,Engine as _,};use derive_more::From;use ed25519_compact as ed25519;use itertools::Itertools as _;use pgp::Deserializable as _;use url::Url;#[cfg(test)]mod tests;pub mod error {use thiserror::Error;#[derive(Debug, Error)]pub enum DID {#[error("not a DID")]NotADid,#[error("unsupported method")]UnsupportedMethod,#[error("unexpected eof")]UnexpectedEof,#[error("malformed method-specific identifier: `{0}`")]MalformedIdentifier(String),#[error("invalid method-specific identifier")]InvalidIdentifier(#[from] url::ParseError),}#[derive(Debug, Error)]pub enum DIDUrl {#[error("not a DID URL")]NotADidUrl,#[error("not a valid URL")]InvalidUrl(#[from] url::ParseError),}}#[derive(Debug, serde::Deserialize)]#[serde(rename_all = "camelCase")]pub struct Document {pub id: DID,#[serde(deserialize_with = "deserialize_verification_methods")]pub verification_method: Vec<VerificationMethod>,#[serde(default)]pub also_known_as: Vec<Url>,}#[derive(Debug)]pub struct VerificationMethod {pub id: String,pub controller: DID,pub public_key: PublicKey,}#[derive(Debug, From)]pub enum PublicKey {Ed25519(ed25519::PublicKey),Pgp(pgp::SignedPublicKey),}fn deserialize_verification_methods<'de, D>(deserializer: D,) -> Result<Vec<VerificationMethod>, D::Error>whereD: serde::Deserializer<'de>,{struct Visitor;impl<'de> serde::de::Visitor<'de> for Visitor {type Value = Vec<VerificationMethod>;fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {f.write_str("a list of verification methods")}fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>whereS: serde::de::SeqAccess<'de>,{let mut out = seq.size_hint().map(Vec::with_capacity).unwrap_or_default();while let Some(val) = seq.next_element::<VerificationMethodMap>()? {let key = if let Some(key) = val.public_key_jwk {key.0.into()} else if let Some(key) = val.public_key_base58 {key.0.into()} else if let Some(key) = val.public_key_multibase {key.0.into()} else if let Some(key) = val.public_key_pgp {key.0.into()} else {return Err(serde::de::Error::missing_field("public_key"));};out.push(VerificationMethod {id: val.id,controller: val.controller,public_key: key,})}Ok(out)}}deserializer.deserialize_seq(Visitor)}/// A [decentralized identifier] (DID).////// The only currently supported [method] is [did-web].////// # Examples////// ```text/// did:web:example.com/// did:web:example.com:u:bob/// ```////// [decentralized identifier]: https://www.w3.org/TR/did-core/#dfn-decentralized-identifiers/// [method]: https://www.w3.org/TR/did-core/#dfn-did-methods/// [did-web]: https://w3c-ccg.github.io/did-method-web/#[derive(Debug, serde::Deserialize)]#[serde(try_from = "String")]pub struct DID(String);impl DID {pub fn parse<S>(s: S) -> Result<Self, error::DID>whereS: AsRef<str> + Into<String>,{let uri = Url::parse(s.as_ref())?;if uri.scheme() != "did" {return Err(error::DID::NotADid);}let mut iter = uri.path().split(':');let method = iter.next().ok_or(error::DID::UnexpectedEof)?;if method != "web" {return Err(error::DID::UnsupportedMethod);}if iter.any(|segment| segment.contains('/')) {return Err(error::DID::MalformedIdentifier(uri.path().strip_prefix("web:").unwrap().to_owned(),));}let iter = uri.path().split(':').skip(1);let suf = iter::once("https://").chain(iter).join("/");let _ = Url::parse(&suf)?;Ok(Self(s.into()))}pub fn id(&self) -> &str {self}pub async fn resolve(&self) -> anyhow::Result<Document> {let mut url = Url::parse(&iter::once("https://").chain(self.split(':').skip(2)).join("/"),)?;let is_empty_path = url.path() == "/";{let mut path = url.path_segments_mut().unwrap();if is_empty_path {path.push("/.well-known");}path.push("/did.json");}Ok(reqwest::get(url).await?.json().await?)}}impl fmt::Display for DID {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {f.write_str(self)}}impl FromStr for DID {type Err = error::DID;fn from_str(s: &str) -> Result<Self, Self::Err> {DID::parse(s)}}impl TryFrom<String> for DID {type Error = error::DID;fn try_from(s: String) -> Result<Self, Self::Error> {DID::parse(s)}}impl Deref for DID {type Target = str;fn deref(&self) -> &Self::Target {&self.0}}impl AsRef<str> for DID {fn as_ref(&self) -> &str {self}}#[derive(Debug, serde::Deserialize)]#[serde(rename_all = "camelCase")]struct VerificationMethodMap {id: String,controller: DID,public_key_jwk: Option<PublicKeyJwk>,public_key_base58: Option<PublicKeyBase58>,public_key_multibase: Option<PublicKeyMultibase>,public_key_pgp: Option<PublicKeyPgp>,}#[derive(Debug)]struct PublicKeyJwk(ed25519::PublicKey);impl<'de> serde::Deserialize<'de> for PublicKeyJwk {fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>whereD: serde::Deserializer<'de>,{let map: HashMap<String, String> = serde::Deserialize::deserialize(deserializer)?;match map.get("kty").map(|s| s.as_str()) {Some("OKP") => Ok(()),Some(x) => Err(serde::de::Error::custom(format!("unsupported kty: {x}"))),None => Err(serde::de::Error::custom("missing kty")),}?;match map.get("crv").map(|s| s.as_str()) {Some("Ed25519") => Ok(()),Some(x) => Err(serde::de::Error::custom(format!("unsupported crv: {x}"))),None => Err(serde::de::Error::custom("missing crv")),}?;let b64: &str = map.get("x").ok_or(serde::de::Error::custom("missing x"))?;let bytes = URL_SAFE_NO_PAD.decode(b64).map_err(serde::de::Error::custom)?;let x = ed25519::PublicKey::from_slice(&bytes).map_err(serde::de::Error::custom)?;Ok(Self(x))}}#[derive(Debug)]struct PublicKeyBase58(ed25519::PublicKey);impl<'de> serde::Deserialize<'de> for PublicKeyBase58 {fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>whereD: serde::Deserializer<'de>,{let b58: &str = serde::Deserialize::deserialize(deserializer)?;let bytes = bs58::decode(b58).into_vec().map_err(serde::de::Error::custom)?;let x = ed25519::PublicKey::from_slice(&bytes).map_err(serde::de::Error::custom)?;Ok(Self(x))}}#[derive(Debug)]struct PublicKeyMultibase(ed25519::PublicKey);impl<'de> serde::Deserialize<'de> for PublicKeyMultibase {fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>whereD: serde::Deserializer<'de>,{let mb: &str = serde::Deserialize::deserialize(deserializer)?;let (_base, bytes) = multibase::decode(mb).map_err(serde::de::Error::custom)?;let x = ed25519::PublicKey::from_slice(&bytes[2..]).map_err(serde::de::Error::custom)?;Ok(Self(x))}}#[derive(Debug)]struct PublicKeyPgp(pgp::SignedPublicKey);impl<'de> serde::Deserialize<'de> for PublicKeyPgp {fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>whereD: serde::Deserializer<'de>,{let ascii: String = serde::Deserialize::deserialize(deserializer)?;let (key, _) =pgp::SignedPublicKey::from_string(&ascii).map_err(serde::de::Error::custom)?;Ok(Self(key))}}
// Copyright © 2023 Kim Altintop <kim@eagain.io>// SPDX-License-Identifier: GPL-2.0-onlyuse super::*;#[test]fn valid_did() {for ex in ["did:web:example.com","did:web:example.com:u:bob","did:web:eagain.io:kim",] {let did: DID = ex.parse().unwrap();assert_eq!(did.id(), ex);assert_eq!(&did.to_string(), ex);}}#[test]fn invalid_did_scheme() {for ex in ["d1d:web:example.com", "https://example.com"] {match ex.parse::<DID>() {Ok(did) => unreachable!("did scheme accepted: {ex} -> {did}"),Err(e) => {if !matches!(e, error::DID::NotADid) {unreachable!("unexpected error: {e}")}},}}}#[test]fn invalid_did_method() {for ex in ["did:plc:deafbeef", "did:example:123456789abcdefghi"] {match ex.parse::<DID>() {Ok(did) => unreachable!("did method accepted: {ex} -> {did}"),Err(e) => {if !matches!(e, error::DID::UnsupportedMethod) {unreachable!("unexpected error: {e}")}},}}}#[test]fn invalid_method_specific_identifier() {for ex in ["did:web:eagain.io/kim"] {match ex.parse::<DID>() {Ok(did) => unreachable!("did accepted: {ex} -> {did}"),Err(e) => {if !matches!(e, error::DID::MalformedIdentifier(..)) {unreachable!("unexpected error: {e}")}},}}}#[test]fn verification_methods() {let input = [r#"{"id": "jwk","type": "JsonWebKey2020","controller": "did:web:example.com","publicKeyJwk": {"kty": "OKP","crv": "Ed25519","x": "CV-aGlld3nVdgnhoZK0D36Wk-9aIMlZjZOK2XhPMnkQ"}}"#,r#"{"id": "ed2018","type": "Ed25519VerificationKey2018","controller": "did:web:example.com","publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"}"#,r#"{"id": "ed2020","type": "Ed25519VerificationKey2020","controller": "did:web::example.com:u:bob","publicKeyMultibase": "z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP"}"#,r#"{"id": "pgp","type": "PgpVerificationKey2021","controller": "did:web:example.com","publicKeyPgp": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\n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\r\n=JzF5\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"}"#,];for js in input {serde_json::from_str::<VerificationMethodMap>(js).unwrap_or_else(|e| {panic!("failed to decode {js}:\n{e:#?}");});}}#[test]fn resolve() {let did = DID::parse("did:web:eagain.io:kim").unwrap();let doc = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(did.resolve()).unwrap();eprintln!("{doc:#?}");}
[[package]]name = "data-encoding-macro"version = "0.1.13"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99"dependencies = ["data-encoding","data-encoding-macro-internal",][[package]]name = "data-encoding-macro-internal"version = "0.1.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772"dependencies = ["data-encoding","syn 1.0.109",]