-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cli did create web #263
cli did create web #263
Changes from 4 commits
72fea60
9d60e25
5a03e7c
86cbc0d
906f251
c9a8e73
497eefb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
mod resolver; | ||
|
||
use super::{MethodError, Result}; | ||
use crate::dids::{ | ||
data_model::document::Document, | ||
did::Did, | ||
resolution::{ | ||
resolution_metadata::{ResolutionMetadata, ResolutionMetadataError}, | ||
resolution_result::ResolutionResult, | ||
use crate::{ | ||
crypto::jwk::Jwk, | ||
dids::{ | ||
data_model::{document::Document, verification_method::VerificationMethod}, | ||
did::Did, | ||
resolution::{ | ||
resolution_metadata::{ResolutionMetadata, ResolutionMetadataError}, | ||
resolution_result::ResolutionResult, | ||
}, | ||
}, | ||
}; | ||
use resolver::Resolver; | ||
|
@@ -18,6 +21,29 @@ pub struct DidWeb { | |
} | ||
|
||
impl DidWeb { | ||
pub fn new(domain: &str, public_jwk: Jwk) -> Result<Self> { | ||
let did = format!("did:web:{}", domain); | ||
|
||
let verification_method = VerificationMethod { | ||
id: format!("{}#key-0", did), | ||
KendallWeihe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
r#type: "JsonWebKey2020".to_string(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nitro-neal didn't we standardize this to just |
||
controller: did.clone(), | ||
public_key_jwk: public_jwk, | ||
}; | ||
|
||
let document = Document { | ||
id: did.clone(), | ||
context: Some(vec!["https://www.w3.org/ns/did/v1".to_string()]), | ||
verification_method: vec![verification_method], | ||
..Default::default() | ||
}; | ||
|
||
Ok(DidWeb { | ||
did: Did::new(&did)?, | ||
document, | ||
}) | ||
} | ||
|
||
pub async fn from_uri(uri: &str) -> Result<Self> { | ||
let resolution_result = DidWeb::resolve(uri); | ||
match resolution_result.document { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
use clap::Subcommand; | ||
use url::Url; | ||
use std::sync::Arc; | ||
use web5::{ | ||
crypto::dsa::ed25519::{Ed25519Generator, Ed25519Signer}, | ||
dids::{ | ||
methods::{did_dht::DidDht, did_jwk::DidJwk}, | ||
methods::{did_dht::DidDht, did_jwk::DidJwk, did_web::DidWeb}, | ||
portable_did::PortableDid, | ||
}, | ||
}; | ||
|
@@ -18,6 +19,10 @@ pub enum Commands { | |
}, | ||
Web { | ||
domain: String, | ||
#[arg(long)] | ||
no_indent: bool, | ||
#[arg(long)] | ||
json_escape: bool, | ||
}, | ||
Dht { | ||
#[arg(long)] | ||
|
@@ -63,8 +68,60 @@ impl Commands { | |
|
||
print_portable_did(portable_did, no_indent, json_escape); | ||
} | ||
Commands::Web { domain: _ } => { | ||
println!("🚧 not currently supported 🚧"); | ||
Commands::Web { | ||
domain, | ||
no_indent, | ||
json_escape, | ||
} => { | ||
let private_jwk = Ed25519Generator::generate(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that with did web especially, we should allow people to pass in the own private key / portable did. We can add this as a feature in the future though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed, on the private key input (portable DID slightly different use case I haven't thought through -- creating a new DID with an existing DID), but yeah not a priority at this moment |
||
let mut public_jwk = private_jwk.clone(); | ||
public_jwk.d = None; | ||
|
||
let valid_url = if domain.starts_with("http://") || domain.starts_with("https://") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is really amazing code @diehuxx 👏 so good, in fact, I'm going to move it inside the also I spy a slight bug in the case wherein both a |
||
let url = Url::parse(domain).expect("Invalid URL"); | ||
|
||
// Ensure "http://" is only allowed for localhost or 127.0.0.1 | ||
if url.scheme() == "http" && !(url.host_str() == Some("localhost") || url.host_str() == Some("127.0.0.1")) { | ||
panic!("Only https is allowed except for localhost or 127.0.0.1 with http"); | ||
} | ||
|
||
// Get the trimmed URL string without the scheme | ||
let trimmed_url = url[url::Position::BeforeHost..].to_string(); | ||
|
||
// Remove the scheme | ||
let normalized = if trimmed_url.starts_with("//") { | ||
&trimmed_url[2..] | ||
} else { | ||
&trimmed_url | ||
}; | ||
|
||
normalized.to_string() | ||
} else { | ||
Url::parse(&format!("https://{}", domain)).expect("Invalid URL"); | ||
domain.clone() | ||
}; | ||
|
||
let normalized = if valid_url.ends_with("/did.json") { | ||
valid_url.trim_end_matches("/did.json").to_string() | ||
} else if valid_url.ends_with("/.well-known") { | ||
valid_url.trim_end_matches("/.well-known").to_string() | ||
} else if valid_url.ends_with("/") { | ||
valid_url.trim_end_matches("/").to_string() | ||
} else { | ||
valid_url.clone() | ||
}; | ||
|
||
let encoded_domain = normalized.replace(":", "%3A"); | ||
let encoded_domain = encoded_domain.replace("/", ":"); | ||
|
||
let did_web = DidWeb::new(&encoded_domain, public_jwk).unwrap(); | ||
let portable_did = PortableDid { | ||
did_uri: did_web.did.uri, | ||
document: did_web.document, | ||
private_jwks: vec![private_jwk], | ||
}; | ||
|
||
print_portable_did(portable_did, no_indent, json_escape) | ||
} | ||
Commands::Dht { | ||
no_publish, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't quite right because the domain has to be encoded according to the spec. See here and here. Also web5-go as inspiration.
Probably we should use a strongly typed
Url
here to ensure the passeddomain: &str
is a valid domain.I believe also did:web has a requirement of enforcing
https
overhttp
, but with the caveat that, if the domain islocalhost
thenhttp
is allowed. We're currently setup to handle this in resolution, but here too, we should use a strongly typedUrl
to ensure the domain islocalhost
and not something likelocalhost-neal-example.com
. Feel free to improve the resolution code as well in this PR if you think it's appropriate.