diff --git a/crates/dids/Cargo.toml b/crates/dids/Cargo.toml index e59d97201..9ca39eb73 100644 --- a/crates/dids/Cargo.toml +++ b/crates/dids/Cargo.toml @@ -33,4 +33,7 @@ did-method-key.workspace = true did-pkh.workspace = true did-tz.workspace = true did-web.workspace = true -thiserror.workspace = true \ No newline at end of file +thiserror.workspace = true + +[dev-dependencies] +async-std = { workspace = true, features = ["attributes"] } \ No newline at end of file diff --git a/crates/dids/core/src/did/url.rs b/crates/dids/core/src/did/url.rs index ed023aae5..3df223ed2 100644 --- a/crates/dids/core/src/did/url.rs +++ b/crates/dids/core/src/did/url.rs @@ -36,14 +36,15 @@ impl DIDURL { /// /// Fails if the data is not a DID URL according to the /// [DID Syntax](https://w3c.github.io/did-core/#did-url-syntax). - pub fn new(data: &[u8]) -> Result<&Self, InvalidDIDURL<&[u8]>> { + pub fn new>(did_url: &T) -> Result<&Self, InvalidDIDURL<&T>> { + let data = did_url.as_ref(); match Self::validate(data) { Ok(()) => Ok(unsafe { // SAFETY: DID is a transparent wrapper over `[u8]`, // and we just checked that `data` is a DID URL. std::mem::transmute::<&[u8], &Self>(data) }), - Err(e) => Err(InvalidDIDURL(data, e)), + Err(e) => Err(InvalidDIDURL(did_url, e)), } } diff --git a/crates/dids/core/src/operation.rs b/crates/dids/core/src/operation.rs deleted file mode 100644 index 9a78326f8..000000000 --- a/crates/dids/core/src/operation.rs +++ /dev/null @@ -1,122 +0,0 @@ -/// Something that can be used to derive (generate) a DID. -#[derive(Debug, Clone, PartialEq, Eq)] -#[non_exhaustive] -pub enum Source<'a> { - /// A public key. - Key(&'a JWK), - /// A public key and additional pattern. - KeyAndPattern(&'a JWK, &'a str), -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -#[serde(rename_all = "camelCase")] -/// [DID Parameters](https://www.w3.org/TR/did-core/#did-parameters). -/// -/// As specified in DID Core and/or in [DID Specification -/// Registries](https://www.w3.org/TR/did-spec-registries/#parameters). -pub struct DIDParameters { - #[serde(skip_serializing_if = "Option::is_none")] - pub service: Option, // ASCII - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(alias = "relative-ref")] - /// [`relativeRef`](https://www.w3.org/TR/did-spec-registries/#relativeRef-param) parameter. - pub relative_ref: Option, // ASCII, percent-encoding - /// [`versionId`](https://www.w3.org/TR/did-spec-registries/#versionId-param) parameter. - #[serde(skip_serializing_if = "Option::is_none")] - pub version_id: Option, // ASCII - /// [`versionTime`](https://www.w3.org/TR/did-spec-registries/#versionTime-param) parameter. - #[serde(skip_serializing_if = "Option::is_none")] - pub version_time: Option>, // ASCII - /// [`hl`](https://www.w3.org/TR/did-spec-registries/#hl-param) parameter. - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(rename = "hl")] - pub hashlink: Option, // ASCII - /// Additional parameters. - #[serde(flatten)] - pub property_set: Option>, -} - -/// DID Create Operation -/// -/// -pub struct DIDCreate { - pub update_key: Option, - pub recovery_key: Option, - pub verification_key: Option, - pub options: Map, -} - -/// DID Update Operation -/// -/// -pub struct DIDUpdate { - pub did: String, - pub update_key: Option, - pub new_update_key: Option, - pub operation: DIDDocumentOperation, - pub options: Map, -} - -/// DID Recover Operation -/// -/// -pub struct DIDRecover { - pub did: String, - pub recovery_key: Option, - pub new_update_key: Option, - pub new_recovery_key: Option, - pub new_verification_key: Option, - pub options: Map, -} - -/// DID Deactivate Operation -/// -/// -pub struct DIDDeactivate { - pub did: String, - pub key: Option, - pub options: Map, -} - -/// DID Document Operation -/// -/// This should represent [didDocument][dd] and [didDocumentOperation][ddo] specified by DID -/// Registration. -/// -/// [dd]: https://identity.foundation/did-registration/#diddocumentoperation -/// [ddo]: https://identity.foundation/did-registration/#diddocument -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(tag = "didDocumentOperation", content = "didDocument")] -#[serde(rename_all = "camelCase")] -#[allow(clippy::large_enum_variant)] -pub enum DIDDocumentOperation { - /// Set the contents of the DID document - /// - /// setDidDocument operation defined by DIF DID Registration - SetDidDocument(Document), - - /// Add properties to the DID document - /// - /// addToDidDocument operation defined by DIF DID Registration - AddToDidDocument(HashMap), - - /// Remove properties from the DID document - /// - /// removeFromDidDocument operation defined by DIF Registration - RemoveFromDidDocument(Vec), - - /// Add or update a verification method in the DID document - SetVerificationMethod { - vmm: VerificationMethodMap, - purposes: Vec, - }, - - /// Add or update a service map in the DID document - SetService(Service), - - /// Remove a verification method in the DID document - RemoveVerificationMethod(DIDURL), - - /// Add or update a service map in the DID document - RemoveService(DIDURL), -} \ No newline at end of file diff --git a/crates/dids/core/src/resolution.rs b/crates/dids/core/src/resolution.rs index 9e4c006e0..8d2c98ab9 100644 --- a/crates/dids/core/src/resolution.rs +++ b/crates/dids/core/src/resolution.rs @@ -25,38 +25,51 @@ pub use http::*; /// [DID URL dereferencing](DIDResolver::dereference). pub const MEDIA_TYPE_URL: &str = "text/url"; +/// DID resolution error. +/// +/// Error raised by the [`DIDResolver::resolve`] method. #[derive(Debug, thiserror::Error)] pub enum Error { + /// DID method is not supported by this resolver. #[error("DID method `{0}` not supported")] MethodNotSupported(String), + /// DID document could not be found. #[error("DID document not found")] NotFound, + /// Resolver doesn't know what representation to use for the DID document. #[error("no representation specified")] NoRepresentation, + /// Requested DID document representation is not supported. #[error("DID representation `{0}` not supported")] RepresentationNotSupported(String), + /// Invalid data provided to the resolver. #[error(transparent)] InvalidData(InvalidData), + /// Invalid method-specific identifier. #[error("invalid method specific identifier: {0}")] InvalidMethodSpecificId(String), + /// Invalid resolution options. #[error("invalid options")] InvalidOptions, + /// Internal resolver-specific error. #[error("DID resolver internal error: {0}")] Internal(String), } impl Error { + /// Creates a new internal error. pub fn internal(error: impl ToString) -> Self { Self::Internal(error.to_string()) } + /// Returns the error kind. pub fn kind(&self) -> ErrorKind { match self { Self::MethodNotSupported(_) => ErrorKind::MethodNotSupported, @@ -77,6 +90,9 @@ impl From for Error { } } +/// Resolution error kind. +/// +/// Each resolution [`Error`] has a kind provided by the [`Error::kind`] method. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum ErrorKind { MethodNotSupported, @@ -116,10 +132,18 @@ impl DIDResolver for T { } } -/// A [DID resolver](https://www.w3.org/TR/did-core/#dfn-did-resolvers), -/// implementing the [DID Resolution](https://www.w3.org/TR/did-core/#did-resolution) -/// [algorithm](https://w3c-ccg.github.io/did-resolution/#resolving-algorithm) and -/// optionally [DID URL Dereferencing](https://www.w3.org/TR/did-core/#did-url-dereferencing). +/// [DID resolver](https://www.w3.org/TR/did-core/#dfn-did-resolvers). +/// +/// Any type implementing the [DID Resolution](https://www.w3.org/TR/did-core/#did-resolution) +/// [algorithm](https://w3c-ccg.github.io/did-resolution/#resolving-algorithm) +/// through the [`resolve`](DIDResolver::resolve) method +/// and the [DID URL Dereferencing](https://www.w3.org/TR/did-core/#did-url-dereferencing) +/// algorithm through the [`dereference`](DIDResolver::dereference) method. +/// +/// This library provides the [`AnyDidMethod`] that implements this trait +/// by grouping various DID method implementations. +/// +/// [`AnyDidMethod`]: <../dids/struct.AnyDidMethod.html> pub trait DIDResolver { /// Resolves a DID representation. /// diff --git a/crates/dids/core/src/verification_relationship.rs b/crates/dids/core/src/verification_relationship.rs deleted file mode 100644 index 272644c9a..000000000 --- a/crates/dids/core/src/verification_relationship.rs +++ /dev/null @@ -1,82 +0,0 @@ -/// A [verification relationship](https://w3c.github.io/did-core/#dfn-verification-relationship). -/// -/// The relationship between a [verification method][VerificationMethod] and a DID -/// Subject (as described by a [DID Document][Document]) is considered analogous to a [proof -/// purpose](crate::vc::ProofPurpose). -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] -#[serde(try_from = "String")] -#[serde(rename_all = "camelCase")] -pub enum VerificationRelationship { - AssertionMethod, - Authentication, - KeyAgreement, - ContractAgreement, - CapabilityInvocation, - CapabilityDelegation, -} - -impl Default for VerificationRelationship { - fn default() -> Self { - Self::AssertionMethod - } -} - -impl FromStr for VerificationRelationship { - type Err = Error; - fn from_str(purpose: &str) -> Result { - match purpose { - "authentication" => Ok(Self::Authentication), - "assertionMethod" => Ok(Self::AssertionMethod), - "keyAgreement" => Ok(Self::KeyAgreement), - "contractAgreement" => Ok(Self::ContractAgreement), - "capabilityInvocation" => Ok(Self::CapabilityInvocation), - "capabilityDelegation" => Ok(Self::CapabilityDelegation), - _ => Err(Error::UnsupportedVerificationRelationship), - } - } -} - -impl TryFrom for VerificationRelationship { - type Error = Error; - fn try_from(purpose: String) -> Result { - Self::from_str(&purpose) - } -} - -impl From for String { - fn from(purpose: VerificationRelationship) -> String { - match purpose { - VerificationRelationship::Authentication => "authentication".to_string(), - VerificationRelationship::AssertionMethod => "assertionMethod".to_string(), - VerificationRelationship::KeyAgreement => "keyAgreement".to_string(), - VerificationRelationship::ContractAgreement => "contractAgreement".to_string(), - VerificationRelationship::CapabilityInvocation => "capabilityInvocation".to_string(), - VerificationRelationship::CapabilityDelegation => "capabilityDelegation".to_string(), - } - } -} - -impl VerificationRelationship { - pub fn to_iri(&self) -> &Iri { - match self { - VerificationRelationship::Authentication => { - iri!("https://w3id.org/security#authenticationMethod") - } - VerificationRelationship::AssertionMethod => { - iri!("https://w3id.org/security#assertionMethod") - } - VerificationRelationship::KeyAgreement => { - iri!("https://w3id.org/security#keyAgreementMethod") - } - VerificationRelationship::ContractAgreement => { - iri!("https://w3id.org/security#contractAgreementMethod") - } - VerificationRelationship::CapabilityInvocation => { - iri!("https://w3id.org/security#capabilityInvocationMethod") - } - VerificationRelationship::CapabilityDelegation => { - iri!("https://w3id.org/security#capabilityDelegationMethod") - } - } - } -} \ No newline at end of file diff --git a/crates/dids/methods/pkh/src/lib.rs b/crates/dids/methods/pkh/src/lib.rs index 07191a03a..7a071ae52 100644 --- a/crates/dids/methods/pkh/src/lib.rs +++ b/crates/dids/methods/pkh/src/lib.rs @@ -135,6 +135,8 @@ const REFERENCE_TEZOS_MAINNET: &str = "NetXdQprcVkpaWU"; const REFERENCE_SOLANA_MAINNET: &str = "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ"; /// did:pkh DID Method +/// +/// See: pub struct DIDPKH; type ResolutionResult = Result<(Document, JsonLdContext), Error>; diff --git a/crates/dids/src/lib.rs b/crates/dids/src/lib.rs index a21b265ba..4d01576d5 100644 --- a/crates/dids/src/lib.rs +++ b/crates/dids/src/lib.rs @@ -1,7 +1,169 @@ //! DID Methods. //! -//! This library provides an interface for DIDs and -//! implementations for various DID methods. +//! This library provides Decentralized Identifiers (DIDs), a type of +//! identifier defined by the W3C that enables verifiable, self-sovereign +//! digital identities. +//! Unlike traditional identifiers, such as email addresses or usernames, +//! DIDs are not tied to a central authority. Instead, they are generated and +//! managed on decentralized networks like blockchains, providing greater +//! privacy, security, and control to the individual or entity that owns them. +//! +//! Each DID is an URI using the `did` scheme. This library uses the [`DID`] and +//! [`DIDBuf`] (similar to [`str`] and [`String`]) to parse and store DIDs. +//! +//! ``` +//! use ssi_dids::{DID, DIDBuf}; +//! +//! // Create a `&DID` from a `&str`. +//! let did = DID::new("did:web:w3c-ccg.github.io:user:alice").unwrap(); +//! +//! // Create a `DIDBuf` from a `String`. +//! let owned_did = DIDBuf::from_string("did:web:w3c-ccg.github.io:user:alice".to_owned()).unwrap(); +//! ``` +//! +//! Just like regular URLs, it is possible to provide the DID with a fragment +//! part. The result is a DID URL, which can be parsed and stored using +//! [`DIDURL`] and [`DIDURLBuf`]. +//! +//! ``` +//! use ssi_dids::{DIDURL, DIDURLBuf}; +//! +//! // Create a `&DIDURL` from a `&str`. +//! let did_url = DIDURL::new("did:web:w3c-ccg.github.io:user:alice#key").unwrap(); +//! +//! // Create a `DIDBuf` from a `String`. +//! let owned_did_url = DIDURLBuf::from_string("did:web:w3c-ccg.github.io:user:bob#key".to_owned()).unwrap(); +//! ``` +//! +//! Note that a DID URL, with a fragment, is not a valid DID. +//! +//! # DID document resolution +//! +//! DID resolution is the process of retrieving the DID document associated with +//! a specific DID. +//! A DID document is a JSON-LD formatted file that contains crucial information +//! needed to interact with the DID, such as verification methods containing the +//! user's public keys, and service endpoints. Here is an example DID document: +//! ```json +//! { +//! "@context": [ +//! "https://www.w3.org/ns/did/v1", +//! "https://w3id.org/security/suites/jws-2020/v1" +//! ], +//! "id": "did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9", +//! "verificationMethod": [ +//! { +//! "id": "did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0", +//! "type": "JsonWebKey2020", +//! "controller": "did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9", +//! "publicKeyJwk": { +//! "crv": "P-256", +//! "kty": "EC", +//! "x": "acbIQiuMs3i8_uszEjJ2tpTtRM4EU3yz91PH6CdH2V0", +//! "y": "_KcyLj9vWMptnmKtm46GqDz8wf74I5LKgrl2GzH3nSE" +//! } +//! } +//! ], +//! "assertionMethod": ["did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0"], +//! "authentication": ["did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0"], +//! "capabilityInvocation": ["did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0"], +//! "capabilityDelegation": ["did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0"], +//! "keyAgreement": ["did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0"] +//! } +//! ``` +//! +//! DID documents are represented using the [`Document`] type and can be +//! resolved from a DID using any implementation of the [`DIDResolver`] trait. +//! The [`AnyDidMethod`] type is provided as a default implementation for +//! [`DIDResolver`] that supports various *DID methods* (see below). +//! +//! ``` +//! # #[async_std::main] async fn main() { +//! use ssi_dids::{DID, AnyDidMethod, DIDResolver}; +//! +//! // Create a DID. +//! let did = DID::new("did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9").unwrap(); +//! +//! // Setup the DID resolver. +//! let resolver = AnyDidMethod::default(); +//! +//! // Resolve the DID document (equal to the example document above). +//! let document = resolver.resolve(did).await.unwrap().document; +//! +//! // Extract the first verification method. +//! let vm = document.verification_method.first().unwrap(); +//! # } +//! ``` +//! +//! Instead of resolving a DID document and extracting verification methods +//! manually, you can use the `dereference` method to resolve a DID URL: +//! ``` +//! # #[async_std::main] async fn main() { +//! use ssi_dids::{DIDURL, AnyDidMethod, DIDResolver}; +//! +//! // Create a DID URL with the fragment `#0` referencing a verification method. +//! let did_url = DIDURL::new("did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9#0").unwrap(); +//! +//! // Setup the DID resolver. +//! let resolver = AnyDidMethod::default(); +//! +//! // Dereference the verification method. +//! let vm = resolver +//! .dereference(did_url) +//! .await +//! .unwrap() +//! .content +//! .into_verification_method() +//! .unwrap(); +//! # } +//! ``` +//! +//! # DID methods +//! +//! A key component of the DID system is the concept of DID methods. A DID +//! method defines how a specific type of DID is created, resolved, updated, +//! and deactivated on a particular decentralized network or ledger. +//! Each DID method corresponds to a unique identifier format and a set of +//! operations that can be performed on the associated DIDs. +//! The general syntax of DIDs depends on the method used: +//! +//! ```text +//! did:method:method-specific-id +//! ``` +//! +//! There exists various DID methods, each defined by their own specification. +//! In this library, methods are defining by implementing the [`DIDMethod`] +//! trait. Implementations are provided for the following methods: +//! - [`did:key`](https://w3c-ccg.github.io/did-method-key/): for static +//! cryptographic keys, implemented by [`DIDKey`]. +//! - [`did:jwk`](https://github.com/quartzjer/did-jwk/blob/main/spec.md): +//! for [Json Web Keys (JWK)](https://datatracker.ietf.org/doc/html/rfc7517) +//! implemented by [`DIDJWK`]. +//! - [`did:web`](https://w3c-ccg.github.io/did-method-web/): for web-hosted DID +//! documents, implemented by [`DIDWeb`]. +//! - [`did:pkh`](https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md): +//! implemented by [`DIDPKH`]. +//! - [`did:ethr`](https://github.com/decentralized-identity/ethr-did-resolver/): +//! implemented by [`DIDEthr`]. +//! - [`did:ion`](https://identity.foundation/sidetree/spec/v1.0.0/#did-uri-composition): +//! implemented by [`DIDION`]. +//! - [`did:tz`](https://github.com/spruceid/did-tezos/): implemented by +//! [`DIDTz`]. +//! +//! The [`AnyDidMethod`] regroups all those methods into one [`DIDResolver`] +//! implementation. +//! +//! DID method types can also be used to generate fresh DID URLs: +//! ``` +//! use ssi_jwk::JWK; +//! use ssi_dids::DIDJWK; +//! +//! /// Generate a new JWK. +//! let jwk = JWK::generate_p256(); +//! +//! /// Generate a DID URL out of our JWK URL. +//! let did_url = DIDJWK::generate_url(&jwk); +//! ``` // Re-export core definitions. pub use ssi_dids_core::*; @@ -23,6 +185,9 @@ pub use pkh::DIDPKH; pub use tz::DIDTz; pub use web::DIDWeb; +/// DID generation error. +/// +/// Error raised by the [`AnyDidMethod::generate`] method. #[derive(Debug, thiserror::Error)] pub enum GenerateError { #[error(transparent)] @@ -41,17 +206,75 @@ pub enum GenerateError { UnsupportedMethodPattern(String), } +/// DID resolver for any known DID method. +/// +/// This type regroups all the [`DIDMethod`] implementations provided by `ssi` +/// into a single [`DIDResolver`] trait implementation. +/// +/// # Supported methods +/// +/// Here is the list of DID methods currently supported by this resolver: +/// - [`did:key`](https://w3c-ccg.github.io/did-method-key/): for static +/// cryptographic keys, implemented by [`DIDKey`]. +/// - [`did:jwk`](https://github.com/quartzjer/did-jwk/blob/main/spec.md): +/// for [Json Web Keys (JWK)](https://datatracker.ietf.org/doc/html/rfc7517) +/// implemented by [`DIDJWK`]. +/// - [`did:web`](https://w3c-ccg.github.io/did-method-web/): for web-hosted DID +/// documents, implemented by [`DIDWeb`]. +/// - [`did:pkh`](https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md): +/// implemented by [`DIDPKH`]. +/// - [`did:ethr`](https://github.com/decentralized-identity/ethr-did-resolver/): +/// implemented by [`DIDEthr`]. +/// - [`did:ion`](https://identity.foundation/sidetree/spec/v1.0.0/#did-uri-composition): +/// implemented by [`DIDION`]. +/// - [`did:tz`](https://github.com/spruceid/did-tezos/): implemented by +/// [`DIDTz`]. #[derive(Default, Clone)] pub struct AnyDidMethod { + /// `did:ion` method configuration. ion: DIDION, + + /// `did:tz` method configuration. tz: DIDTz, } impl AnyDidMethod { + /// Creates a new resolver using the following `did:ion` and `did:tz` method + /// resolvers. + /// + /// Use the [`Default`] implementation if you don't want to configure + /// `DIDION` and `DIDTz` yourself. pub fn new(ion: DIDION, tz: DIDTz) -> Self { Self { ion, tz } } + /// Generate a new DID from a JWK. + /// + /// The `method_pattern` argument is used to select and configure the DID + /// method. Accepted patterns are + /// - `key` to generate a `did:key` DID, + /// - `jwk` to generate a `did:jwk` DID, + /// - `ethr` to generate a `did:ethr` DID, + /// - `pkh:{pkh_name}` to generate a `did:pkh` DID, where `{pkh_name}` + /// should be replaced by the network id as specified by the + /// [`DIDPKH::generate`] function. + /// - `tz` to generate a `did:tz` DID. + /// + /// # Example + /// + /// ``` + /// use ssi_jwk::JWK; + /// use ssi_dids::AnyDidMethod; + /// + /// // Create a DID resolver. + /// let resolver = AnyDidMethod::default(); + /// + /// // Create a JWK. + /// let jwk = JWK::generate_p256(); + /// + /// // Generate a `did:jwk` DID for this JWK: + /// let did = resolver.generate(&jwk, "jwk").unwrap(); + /// ``` pub fn generate( &self, key: &ssi_jwk::JWK, diff --git a/examples/issue.rs b/examples/issue.rs index 93ee97001..4a368309e 100644 --- a/examples/issue.rs +++ b/examples/issue.rs @@ -25,7 +25,7 @@ async fn issue(proof_format: &str) { "@context": ["https://www.w3.org/2018/credentials/v1"], "type": "VerifiableCredential", "issuer": "did:example:foo", - "issuanceDate": ssi::xsd_types::DateTime::now(), + "issuanceDate": ssi::xsd::DateTime::now(), "credentialSubject": { "id": uuid::Uuid::new_v4().urn().to_string() } diff --git a/src/lib.rs b/src/lib.rs index 460eb5f3a..f4c0fc536 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,7 +244,9 @@ #![doc = document_features::document_features!()] #![cfg_attr(docsrs, feature(doc_auto_cfg), feature(doc_cfg))] -pub use xsd_types; +/// XSD types. +#[doc(inline)] +pub use xsd_types as xsd; /// Collection of common names defined by SSI. pub mod prelude; @@ -286,6 +288,7 @@ pub use ssi_security as security; pub use ssi_claims as claims; /// Claims status. +#[doc(inline)] pub use ssi_status as status; /// Default verification parameters type. @@ -344,5 +347,7 @@ pub use ssi_multicodec as multicodec; #[doc(inline)] pub use ssi_ssh as ssh; +/// BBS cryptoscheme. #[cfg(feature = "bbs")] +#[doc(inline)] pub use ssi_bbs as bbs; diff --git a/src/prelude.rs b/src/prelude.rs index 4db90dbcc..994414506 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,7 +10,7 @@ pub use crate::{ }, dids::{DIDResolver, DIDJWK}, verification_methods::{AnyJwkMethod, AnyMethod, SingleSecretSigner}, - xsd_types::DateTime, + xsd::DateTime, DefaultVerificationParameters, JWK, };