From b7853fb0d561e796990a486cb23d5a47c11fafe4 Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Tue, 11 Jun 2024 14:30:31 +0200 Subject: [PATCH 01/22] Resolver trait and CompoundResolver macro --- Cargo.toml | 2 + compound_resolver/Cargo.toml | 20 +++++ compound_resolver/src/lib.rs | 106 ++++++++++++++++++++++++ identity_new_resolver/Cargo.toml | 20 +++++ identity_new_resolver/src/error.rs | 13 +++ identity_new_resolver/src/lib.rs | 7 ++ identity_new_resolver/src/resolver.rs | 7 ++ identity_new_resolver/tests/compound.rs | 47 +++++++++++ 8 files changed, 222 insertions(+) create mode 100644 compound_resolver/Cargo.toml create mode 100644 compound_resolver/src/lib.rs create mode 100644 identity_new_resolver/Cargo.toml create mode 100644 identity_new_resolver/src/error.rs create mode 100644 identity_new_resolver/src/lib.rs create mode 100644 identity_new_resolver/src/resolver.rs create mode 100644 identity_new_resolver/tests/compound.rs diff --git a/Cargo.toml b/Cargo.toml index a0375aa810..861ef7dbc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ members = [ "identity_ecdsa_verifier", "identity_eddsa_verifier", "examples", + "identity_new_resolver", + "compound_resolver", ] exclude = ["bindings/wasm", "bindings/grpc"] diff --git a/compound_resolver/Cargo.toml b/compound_resolver/Cargo.toml new file mode 100644 index 0000000000..af45437b9c --- /dev/null +++ b/compound_resolver/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "compound_resolver" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +proc-macro2 = "1.0.85" +quote = "1.0.36" +syn = { versin = "2.0.66", features = ["parsing"] } + +[lints] +workspace = true + +[lib] +proc-macro = true diff --git a/compound_resolver/src/lib.rs b/compound_resolver/src/lib.rs new file mode 100644 index 0000000000..02e6368752 --- /dev/null +++ b/compound_resolver/src/lib.rs @@ -0,0 +1,106 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse::Parse, punctuated::Punctuated, Attribute, Data, DeriveInput, Field, Ident, Token}; + +#[proc_macro_derive(CompoundResolver, attributes(resolver))] +pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { + let DeriveInput { + ident: struct_ident, + data, + generics, + .. + } = syn::parse_macro_input!(input); + + let Data::Struct(data) = data else { + panic!("Derive macro \"CompoundResolver\" only works on structs"); + }; + + data + .fields + .into_iter() + // parse all the fields that are annoted with #[resolver(..)] + .filter_map(ResolverField::from_field) + // create an iterator over (field_name, Resolver::I, Resolver::T) + .flat_map(|ResolverField { ident, impls }| { + impls + .into_iter() + .map(move |(input_ty, target_ty)| (ident.clone(), input_ty, target_ty)) + }) + // generates code that forward the implementation of Resolver to field_name. + .map(|(field_name, input_ty, target_ty)| { + quote! { + impl ::identity_new_resolver::Resolver<#target_ty, #input_ty> for #struct_ident #generics { + async fn resolve(&self, input: &#input_ty) -> std::result::Result<#target_ty, ::identity_new_resolver::Error> { + self.#field_name.resolve(input).await + } + } + } + }) + .collect::() + .into() +} + +/// A field annotated with `#[resolver(Input -> Target, ..)]` +struct ResolverField { + ident: Ident, + impls: Vec<(Ident, Ident)>, +} + +impl ResolverField { + pub fn from_field(field: Field) -> Option { + let Field { attrs, ident, .. } = field; + let Some(ident) = ident else { + panic!("Derive macro \"CompoundResolver\" only works on struct with named fields"); + }; + + let impls: Vec<(Ident, Ident)> = attrs + .into_iter() + .flat_map(|attr| parse_resolver_attribute(attr).into_iter()) + .collect(); + + if !impls.is_empty() { + Some(ResolverField { ident, impls }) + } else { + None + } + } +} + +fn parse_resolver_attribute(attr: Attribute) -> Vec<(Ident, Ident)> { + if attr.path().is_ident("resolver") { + attr + .parse_args_with(Punctuated::::parse_terminated) + .expect("invalid resolver annotation") + .into_iter() + .map(Into::into) + .collect() + } else { + vec![] + } +} + +struct ResolverTy { + pub input: Ident, + pub target: Ident, +} + +impl From for (Ident, Ident) { + fn from(value: ResolverTy) -> Self { + (value.input, value.target) + } +} + +impl Parse for ResolverTy { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let mut tys = Punctuated::]>::parse_separated_nonempty(input)? + .into_iter() + .take(2); + + Ok({ + ResolverTy { + input: tys.next().unwrap(), + target: tys.next().unwrap(), + } + }) + } +} diff --git a/identity_new_resolver/Cargo.toml b/identity_new_resolver/Cargo.toml new file mode 100644 index 0000000000..aadc8c7b0c --- /dev/null +++ b/identity_new_resolver/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "identity_new_resolver" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +anyhow = "1.0.86" +thiserror.workspace = true +compound_resolver = { path = "../compound_resolver" } + +[lints] +workspace = true + +[dev-dependencies] +tokio = { version = "1.38.0", features = ["macros", "rt"] } diff --git a/identity_new_resolver/src/error.rs b/identity_new_resolver/src/error.rs new file mode 100644 index 0000000000..d9d9b984a9 --- /dev/null +++ b/identity_new_resolver/src/error.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Debug, Error)] +pub enum Error { + #[error("The requested item \"{0}\" was not found.")] + NotFound(String), + #[error("Failed to parse the provided input into a resolvable type: {0}")] + ParsingFailure(#[source] anyhow::Error), + #[error(transparent)] + Generic(anyhow::Error), +} diff --git a/identity_new_resolver/src/lib.rs b/identity_new_resolver/src/lib.rs new file mode 100644 index 0000000000..6238ab24db --- /dev/null +++ b/identity_new_resolver/src/lib.rs @@ -0,0 +1,7 @@ +mod resolver; +mod error; + +pub use error::{Result, Error}; +pub use resolver::Resolver; + +pub use compound_resolver::CompoundResolver; \ No newline at end of file diff --git a/identity_new_resolver/src/resolver.rs b/identity_new_resolver/src/resolver.rs new file mode 100644 index 0000000000..1a95ad8537 --- /dev/null +++ b/identity_new_resolver/src/resolver.rs @@ -0,0 +1,7 @@ +#![allow(async_fn_in_trait)] + +use crate::Result; + +pub trait Resolver { + async fn resolve(&self, input: &I) -> Result; +} diff --git a/identity_new_resolver/tests/compound.rs b/identity_new_resolver/tests/compound.rs new file mode 100644 index 0000000000..602a750c2b --- /dev/null +++ b/identity_new_resolver/tests/compound.rs @@ -0,0 +1,47 @@ +use identity_new_resolver::{CompoundResolver, Result, Resolver}; + +struct DidKey; +struct DidJwk; +struct DidWeb; + +struct CoreDoc; + +struct DidKeyResolver; +impl Resolver for DidKeyResolver { + async fn resolve(&self, _input: &DidKey) -> Result { + Ok(CoreDoc {}) + } +} +struct DidJwkResolver; +impl Resolver for DidJwkResolver { + async fn resolve(&self, _input: &DidJwk) -> Result { + Ok(CoreDoc {}) + } +} +struct DidWebResolver; +impl Resolver for DidWebResolver { + async fn resolve(&self, _input: &DidWeb) -> Result { + Ok(CoreDoc {}) + } +} + +#[derive(CompoundResolver)] +struct SuperDidResolver { + #[resolver(DidKey -> CoreDoc)] + did_key: DidKeyResolver, + #[resolver(DidJwk -> CoreDoc)] + did_jwk: DidJwkResolver, + #[resolver(DidWeb -> CoreDoc)] + did_web: DidWebResolver, +} + +#[tokio::test] +async fn test_compound_resolver() { + let super_resolver = SuperDidResolver { + did_key: DidKeyResolver {}, + did_jwk: DidJwkResolver {}, + did_web: DidWebResolver {}, + }; + + assert!(super_resolver.resolve(&DidJwk {}).await.is_ok()); +} From 0114b35677e63e5c74d2837e770d40e62138ae01 Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Tue, 11 Jun 2024 14:56:56 +0200 Subject: [PATCH 02/22] invert Resolver type parameters --- compound_resolver/src/lib.rs | 2 +- identity_new_resolver/src/resolver.rs | 2 +- identity_new_resolver/tests/compound.rs | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compound_resolver/src/lib.rs b/compound_resolver/src/lib.rs index 02e6368752..7c2b29e35c 100644 --- a/compound_resolver/src/lib.rs +++ b/compound_resolver/src/lib.rs @@ -29,7 +29,7 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { // generates code that forward the implementation of Resolver to field_name. .map(|(field_name, input_ty, target_ty)| { quote! { - impl ::identity_new_resolver::Resolver<#target_ty, #input_ty> for #struct_ident #generics { + impl ::identity_new_resolver::Resolver<#input_ty, #target_ty> for #struct_ident #generics { async fn resolve(&self, input: &#input_ty) -> std::result::Result<#target_ty, ::identity_new_resolver::Error> { self.#field_name.resolve(input).await } diff --git a/identity_new_resolver/src/resolver.rs b/identity_new_resolver/src/resolver.rs index 1a95ad8537..e9f27a767b 100644 --- a/identity_new_resolver/src/resolver.rs +++ b/identity_new_resolver/src/resolver.rs @@ -2,6 +2,6 @@ use crate::Result; -pub trait Resolver { +pub trait Resolver { async fn resolve(&self, input: &I) -> Result; } diff --git a/identity_new_resolver/tests/compound.rs b/identity_new_resolver/tests/compound.rs index 602a750c2b..5a9efe80cf 100644 --- a/identity_new_resolver/tests/compound.rs +++ b/identity_new_resolver/tests/compound.rs @@ -1,4 +1,4 @@ -use identity_new_resolver::{CompoundResolver, Result, Resolver}; +use identity_new_resolver::{CompoundResolver, Resolver, Result}; struct DidKey; struct DidJwk; @@ -7,19 +7,19 @@ struct DidWeb; struct CoreDoc; struct DidKeyResolver; -impl Resolver for DidKeyResolver { +impl Resolver for DidKeyResolver { async fn resolve(&self, _input: &DidKey) -> Result { Ok(CoreDoc {}) } } struct DidJwkResolver; -impl Resolver for DidJwkResolver { +impl Resolver for DidJwkResolver { async fn resolve(&self, _input: &DidJwk) -> Result { Ok(CoreDoc {}) } } struct DidWebResolver; -impl Resolver for DidWebResolver { +impl Resolver for DidWebResolver { async fn resolve(&self, _input: &DidWeb) -> Result { Ok(CoreDoc {}) } @@ -37,11 +37,11 @@ struct SuperDidResolver { #[tokio::test] async fn test_compound_resolver() { - let super_resolver = SuperDidResolver { - did_key: DidKeyResolver {}, - did_jwk: DidJwkResolver {}, - did_web: DidWebResolver {}, - }; + let super_resolver = SuperDidResolver { + did_key: DidKeyResolver {}, + did_jwk: DidJwkResolver {}, + did_web: DidWebResolver {}, + }; - assert!(super_resolver.resolve(&DidJwk {}).await.is_ok()); + assert!(super_resolver.resolve(&DidJwk {}).await.is_ok()); } From 88a538e864074d82e121e534e9e00c1fbefc7c4c Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Tue, 11 Jun 2024 15:18:15 +0200 Subject: [PATCH 03/22] associated type Target instead of type parameter T --- compound_resolver/src/lib.rs | 5 +++-- identity_new_resolver/src/resolver.rs | 5 +++-- identity_new_resolver/tests/compound.rs | 15 +++++++++------ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compound_resolver/src/lib.rs b/compound_resolver/src/lib.rs index 7c2b29e35c..f5a3a06b92 100644 --- a/compound_resolver/src/lib.rs +++ b/compound_resolver/src/lib.rs @@ -29,8 +29,9 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { // generates code that forward the implementation of Resolver to field_name. .map(|(field_name, input_ty, target_ty)| { quote! { - impl ::identity_new_resolver::Resolver<#input_ty, #target_ty> for #struct_ident #generics { - async fn resolve(&self, input: &#input_ty) -> std::result::Result<#target_ty, ::identity_new_resolver::Error> { + impl ::identity_new_resolver::Resolver<#input_ty> for #struct_ident #generics { + type Target = #target_ty; + async fn resolve(&self, input: &#input_ty) -> std::result::Result { self.#field_name.resolve(input).await } } diff --git a/identity_new_resolver/src/resolver.rs b/identity_new_resolver/src/resolver.rs index e9f27a767b..b7499a3991 100644 --- a/identity_new_resolver/src/resolver.rs +++ b/identity_new_resolver/src/resolver.rs @@ -2,6 +2,7 @@ use crate::Result; -pub trait Resolver { - async fn resolve(&self, input: &I) -> Result; +pub trait Resolver { + type Target; + async fn resolve(&self, input: &I) -> Result; } diff --git a/identity_new_resolver/tests/compound.rs b/identity_new_resolver/tests/compound.rs index 5a9efe80cf..3b6901b329 100644 --- a/identity_new_resolver/tests/compound.rs +++ b/identity_new_resolver/tests/compound.rs @@ -7,20 +7,23 @@ struct DidWeb; struct CoreDoc; struct DidKeyResolver; -impl Resolver for DidKeyResolver { - async fn resolve(&self, _input: &DidKey) -> Result { +impl Resolver for DidKeyResolver { + type Target = CoreDoc; + async fn resolve(&self, _input: &DidKey) -> Result { Ok(CoreDoc {}) } } struct DidJwkResolver; -impl Resolver for DidJwkResolver { - async fn resolve(&self, _input: &DidJwk) -> Result { +impl Resolver for DidJwkResolver { + type Target = CoreDoc; + async fn resolve(&self, _input: &DidJwk) -> Result { Ok(CoreDoc {}) } } struct DidWebResolver; -impl Resolver for DidWebResolver { - async fn resolve(&self, _input: &DidWeb) -> Result { +impl Resolver for DidWebResolver { + type Target = CoreDoc; + async fn resolve(&self, _input: &DidWeb) -> Result { Ok(CoreDoc {}) } } From bfd5d59af8944cfdb9bf6cadb41e068c86e8ee8c Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Wed, 12 Jun 2024 13:00:13 +0200 Subject: [PATCH 04/22] fix type issue in #[resolver(..)] annotation, support for multiple resolvers with the same signature --- compound_resolver/Cargo.toml | 3 +- compound_resolver/src/lib.rs | 103 +++++++++++++++++------- identity_new_resolver/tests/compound.rs | 51 +++++++++++- 3 files changed, 126 insertions(+), 31 deletions(-) diff --git a/compound_resolver/Cargo.toml b/compound_resolver/Cargo.toml index af45437b9c..a78d82539d 100644 --- a/compound_resolver/Cargo.toml +++ b/compound_resolver/Cargo.toml @@ -9,9 +9,10 @@ repository.workspace = true rust-version.workspace = true [dependencies] +itertools = "0.13.0" proc-macro2 = "1.0.85" quote = "1.0.36" -syn = { versin = "2.0.66", features = ["parsing"] } +syn = { versin = "2.0.66", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/compound_resolver/src/lib.rs b/compound_resolver/src/lib.rs index f5a3a06b92..7e6d1bf7e1 100644 --- a/compound_resolver/src/lib.rs +++ b/compound_resolver/src/lib.rs @@ -1,6 +1,7 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse::Parse, punctuated::Punctuated, Attribute, Data, DeriveInput, Field, Ident, Token}; +use syn::{parse::Parse, punctuated::Punctuated, Attribute, Data, DeriveInput, Expr, Field, Ident, Token, Type}; +use itertools::Itertools; #[proc_macro_derive(CompoundResolver, attributes(resolver))] pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { @@ -20,19 +21,25 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { .into_iter() // parse all the fields that are annoted with #[resolver(..)] .filter_map(ResolverField::from_field) - // create an iterator over (field_name, Resolver::I, Resolver::T) + // create an iterator over (field_name, Resolver::I, Resolver::T, predicate) .flat_map(|ResolverField { ident, impls }| { impls .into_iter() - .map(move |(input_ty, target_ty)| (ident.clone(), input_ty, target_ty)) + .map(move |ResolverImpl { input, target, pred }| ((input, target), (ident.clone(), pred))) }) - // generates code that forward the implementation of Resolver to field_name. - .map(|(field_name, input_ty, target_ty)| { + // Group together all resolvers with the same signature (input_ty, target_ty). + .into_group_map() + .into_iter() + // generates code that forward the implementation of Resolver to field_name, if there's multiple fields + // implementing that trait, use `pred` to decide which one to call. + .map(|((input_ty, target_ty), impls)| { + let len = impls.len(); + let impl_block = gen_impl_block_multiple_resolvers(impls.into_iter(), len); quote! { impl ::identity_new_resolver::Resolver<#input_ty> for #struct_ident #generics { type Target = #target_ty; async fn resolve(&self, input: &#input_ty) -> std::result::Result { - self.#field_name.resolve(input).await + #impl_block } } } @@ -41,10 +48,38 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { .into() } +fn gen_impl_block_single_resolver(field_name: Ident) -> proc_macro2::TokenStream { + quote! { + self.#field_name.resolve(input).await + } +} + +fn gen_impl_block_single_resolver_with_pred(field_name: Ident, pred: Expr) -> proc_macro2::TokenStream { + let invocation_block = gen_impl_block_single_resolver(field_name); + quote! { + if #pred { return #invocation_block } + } +} + +fn gen_impl_block_multiple_resolvers(impls: impl Iterator)>, len: usize) -> proc_macro2::TokenStream { + impls + .enumerate() + .map(|(i, (field_name, pred))| { + if let Some(pred) = pred { + gen_impl_block_single_resolver_with_pred(field_name, pred) + } else if i == len - 1 { + gen_impl_block_single_resolver(field_name) + } else { + panic!("Multiple resolvers with the same signature. Expected predicate"); + } + }) + .collect() +} + /// A field annotated with `#[resolver(Input -> Target, ..)]` struct ResolverField { ident: Ident, - impls: Vec<(Ident, Ident)>, + impls: Vec, } impl ResolverField { @@ -54,10 +89,10 @@ impl ResolverField { panic!("Derive macro \"CompoundResolver\" only works on struct with named fields"); }; - let impls: Vec<(Ident, Ident)> = attrs + let impls = attrs .into_iter() .flat_map(|attr| parse_resolver_attribute(attr).into_iter()) - .collect(); + .collect::>(); if !impls.is_empty() { Some(ResolverField { ident, impls }) @@ -67,41 +102,53 @@ impl ResolverField { } } -fn parse_resolver_attribute(attr: Attribute) -> Vec<(Ident, Ident)> { +fn parse_resolver_attribute(attr: Attribute) -> Vec { if attr.path().is_ident("resolver") { attr - .parse_args_with(Punctuated::::parse_terminated) + .parse_args_with(Punctuated::::parse_terminated) .expect("invalid resolver annotation") .into_iter() - .map(Into::into) .collect() } else { vec![] } } -struct ResolverTy { - pub input: Ident, - pub target: Ident, +struct ResolverImpl { + pub input: Type, + pub target: Type, + pub pred: Option, } -impl From for (Ident, Ident) { - fn from(value: ResolverTy) -> Self { - (value.input, value.target) - } -} - -impl Parse for ResolverTy { +impl Parse for ResolverImpl { fn parse(input: syn::parse::ParseStream) -> syn::Result { - let mut tys = Punctuated::]>::parse_separated_nonempty(input)? - .into_iter() - .take(2); + // let mut tys = Punctuated::]>::parse_separated_nonempty(input)? + // .into_iter() + // .take(2); + let input_ty = input.parse::()?; + let _ = input.parse::]>()?; + let target_ty = input.parse::()?; + let pred = if input.peek(Token![if]) { + let _ = input.parse::()?; + Some(input.parse::()?) + } else { + None + }; Ok({ - ResolverTy { - input: tys.next().unwrap(), - target: tys.next().unwrap(), + ResolverImpl { + input: input_ty, + target: target_ty, + pred } }) } } + +#[test] +fn test_parse_resolver_attribute() { + syn::parse_str::("DidKey -> CoreDoc").unwrap(); + syn::parse_str::("DidKey -> Vec").unwrap(); + syn::parse_str::("Vec -> &str").unwrap(); + syn::parse_str::("DidIota -> IotaDoc if input.method_id() == \"iota\"").unwrap(); +} diff --git a/identity_new_resolver/tests/compound.rs b/identity_new_resolver/tests/compound.rs index 3b6901b329..b60480dfcb 100644 --- a/identity_new_resolver/tests/compound.rs +++ b/identity_new_resolver/tests/compound.rs @@ -1,10 +1,14 @@ -use identity_new_resolver::{CompoundResolver, Resolver, Result}; +use identity_new_resolver::{CompoundResolver, Resolver, Result, Error}; struct DidKey; struct DidJwk; struct DidWeb; +struct DidIota { + network: u32, +} struct CoreDoc; +struct IotaDoc; struct DidKeyResolver; impl Resolver for DidKeyResolver { @@ -28,6 +32,21 @@ impl Resolver for DidWebResolver { } } +struct Client { + network: u32, +} + +impl Resolver for Client { + type Target = IotaDoc; + async fn resolve(&self, input: &DidIota) -> Result { + if input.network == self.network { + Ok(IotaDoc {}) + } else { + Err(Error::Generic(anyhow::anyhow!("Invalid network"))) + } + } +} + #[derive(CompoundResolver)] struct SuperDidResolver { #[resolver(DidKey -> CoreDoc)] @@ -38,8 +57,18 @@ struct SuperDidResolver { did_web: DidWebResolver, } +#[derive(CompoundResolver)] +struct IdentityClient { + #[resolver(DidKey -> CoreDoc, DidJwk -> CoreDoc, DidWeb -> CoreDoc)] + dids: SuperDidResolver, + #[resolver(DidIota -> IotaDoc if input.network == 0)] + iota: Client, + #[resolver(DidIota -> IotaDoc)] + shimmer: Client, +} + #[tokio::test] -async fn test_compound_resolver() { +async fn test_compound_resolver_simple() { let super_resolver = SuperDidResolver { did_key: DidKeyResolver {}, did_jwk: DidJwkResolver {}, @@ -48,3 +77,21 @@ async fn test_compound_resolver() { assert!(super_resolver.resolve(&DidJwk {}).await.is_ok()); } + +#[tokio::test] +async fn test_compound_resolver_conflicts() { + let super_resolver = SuperDidResolver { + did_key: DidKeyResolver {}, + did_jwk: DidJwkResolver {}, + did_web: DidWebResolver {}, + }; + let identity_client = IdentityClient { + dids: super_resolver, + iota: Client { network: 0}, + shimmer: Client {network: 1}, + }; + + assert!(identity_client.resolve(&DidJwk {}).await.is_ok()); + assert!(identity_client.resolve(&DidIota { network: 1}).await.is_ok()); + assert!(identity_client.resolve(&DidIota { network: 0}).await.is_ok()); +} From 29d29b77a4c9706e4130e431b32f676bb469322a Mon Sep 17 00:00:00 2001 From: wulfraem Date: Wed, 12 Jun 2024 14:42:09 +0200 Subject: [PATCH 05/22] Pin and bump `bls12_381_plus` dependency (#1378) --- Cargo.toml | 1 + bindings/wasm/Cargo.toml | 1 + examples/Cargo.toml | 1 + identity_credential/Cargo.toml | 3 ++- identity_jose/Cargo.toml | 1 + identity_storage/Cargo.toml | 3 ++- identity_stronghold/Cargo.toml | 4 +++- 7 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0375aa810..0b349651b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ exclude = ["bindings/wasm", "bindings/grpc"] [workspace.dependencies] +bls12_381_plus = { version = "=0.8.15" } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } thiserror = { version = "1.0", default-features = false } strum = { version = "0.25", default-features = false, features = ["std", "derive"] } diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 27d693e23b..8648bd3f4e 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -17,6 +17,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] async-trait = { version = "0.1", default-features = false } +bls12_381_plus = "=0.8.15" console_error_panic_hook = { version = "0.1" } futures = { version = "0.3" } identity_eddsa_verifier = { path = "../../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 6830f2035e..a8b1588221 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dependencies] anyhow = "1.0.62" +bls12_381_plus.workspace = true identity_eddsa_verifier = { path = "../identity_eddsa_verifier", default-features = false } identity_iota = { path = "../identity_iota", default-features = false, features = ["iota-client", "client", "memstore", "domain-linkage", "revocation-bitmap", "status-list-2021", "jpt-bbs-plus"] } identity_stronghold = { path = "../identity_stronghold", default-features = false, features = ["bbs-plus"] } diff --git a/identity_credential/Cargo.toml b/identity_credential/Cargo.toml index e93fdd0699..07f119b853 100644 --- a/identity_credential/Cargo.toml +++ b/identity_credential/Cargo.toml @@ -13,6 +13,7 @@ description = "An implementation of the Verifiable Credentials standard." [dependencies] async-trait = { version = "0.1.64", default-features = false } +bls12_381_plus = { workspace = true, optional = true } flate2 = { version = "1.0.28", default-features = false, features = ["rust_backend"], optional = true } futures = { version = "0.3", default-features = false, optional = true } identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } @@ -58,7 +59,7 @@ validator = ["dep:itertools", "dep:serde_repr", "credential", "presentation"] domain-linkage = ["validator"] domain-linkage-fetch = ["domain-linkage", "dep:reqwest", "dep:futures"] sd-jwt = ["credential", "validator", "dep:sd-jwt-payload"] -jpt-bbs-plus = ["credential", "validator", "dep:zkryptium", "dep:json-proof-token"] +jpt-bbs-plus = ["credential", "validator", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"] [lints] workspace = true diff --git a/identity_jose/Cargo.toml b/identity_jose/Cargo.toml index 98a802ffbe..3176142f33 100644 --- a/identity_jose/Cargo.toml +++ b/identity_jose/Cargo.toml @@ -12,6 +12,7 @@ rust-version.workspace = true description = "A library for JOSE (JSON Object Signing and Encryption)" [dependencies] +bls12_381_plus.workspace = true identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } iota-crypto = { version = "0.23", default-features = false, features = ["std", "sha"] } json-proof-token.workspace = true diff --git a/identity_storage/Cargo.toml b/identity_storage/Cargo.toml index 0f1e423b7d..54c1a63b36 100644 --- a/identity_storage/Cargo.toml +++ b/identity_storage/Cargo.toml @@ -14,6 +14,7 @@ description = "Abstractions over storage for cryptographic keys used in DID Docu [dependencies] anyhow = "1.0.82" async-trait = { version = "0.1.64", default-features = false } +bls12_381_plus = { workspace = true, optional = true } futures = { version = "0.3.27", default-features = false, features = ["async-await"] } identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } identity_credential = { version = "=1.3.0", path = "../identity_credential", default-features = false, features = ["credential", "presentation", "revocation-bitmap"] } @@ -46,7 +47,7 @@ send-sync-storage = [] # Implements the JwkStorageDocumentExt trait for IotaDocument iota-document = ["dep:identity_iota_core"] # Enables JSON Proof Token & BBS+ related features -jpt-bbs-plus = ["identity_credential/jpt-bbs-plus", "dep:zkryptium", "dep:json-proof-token"] +jpt-bbs-plus = ["identity_credential/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"] [lints] workspace = true diff --git a/identity_stronghold/Cargo.toml b/identity_stronghold/Cargo.toml index 6fb1b82b07..cd3cabd0bb 100644 --- a/identity_stronghold/Cargo.toml +++ b/identity_stronghold/Cargo.toml @@ -13,6 +13,7 @@ description = "Secure JWK storage with Stronghold for IOTA Identity" [dependencies] async-trait = { version = "0.1.64", default-features = false } +bls12_381_plus = { workspace = true, optional = true } identity_storage = { version = "=1.3.0", path = "../identity_storage", default_features = false } identity_verification = { version = "=1.3.0", path = "../identity_verification", default_features = false } iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"] } @@ -26,6 +27,7 @@ zkryptium = { workspace = true, optional = true } [dev-dependencies] anyhow = "1.0.82" +bls12_381_plus = { workspace = true } identity_did = { version = "=1.3.0", path = "../identity_did", default_features = false } identity_storage = { version = "=1.3.0", path = "../identity_storage", default_features = false, features = ["jpt-bbs-plus"] } json-proof-token = { workspace = true } @@ -36,7 +38,7 @@ zkryptium = { workspace = true } default = [] # Enables `Send` + `Sync` bounds for the trait implementations on `StrongholdStorage`. send-sync-storage = ["identity_storage/send-sync-storage"] -bbs-plus = ["identity_storage/jpt-bbs-plus", "dep:zkryptium", "dep:json-proof-token"] +bbs-plus = ["identity_storage/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"] [lints] workspace = true From 9c1eab488ec0314ffe099b9d809a98a8352eba0d Mon Sep 17 00:00:00 2001 From: Enrico Marconi <31142849+UMR1352@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:24:33 +0200 Subject: [PATCH 06/22] fix syntax in documentation link (#1372) --- .../jpt_credential_validator/jpt_credential_validator_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/wasm/src/credential/jpt_credential_validator/jpt_credential_validator_utils.rs b/bindings/wasm/src/credential/jpt_credential_validator/jpt_credential_validator_utils.rs index cfdf9c6e9e..c2def61059 100644 --- a/bindings/wasm/src/credential/jpt_credential_validator/jpt_credential_validator_utils.rs +++ b/bindings/wasm/src/credential/jpt_credential_validator/jpt_credential_validator_utils.rs @@ -27,7 +27,7 @@ impl WasmJptCredentialValidatorUtils { WasmJptCredentialValidatorUtils } - /// Utility for extracting the issuer field of a {@link `Credential`} as a DID. + /// Utility for extracting the issuer field of a {@link Credential} as a DID. /// # Errors /// Fails if the issuer field is not a valid DID. #[wasm_bindgen(js_name = "extractIssuer")] From e1e25421807d6978ea09fc8223b3ec4c22564e82 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:44:54 +0200 Subject: [PATCH 07/22] Release v1.3.1 (#1379) --- CHANGELOG.md | 15 +++++++++++++-- README.md | 4 ++-- examples/Cargo.toml | 2 +- identity_core/Cargo.toml | 2 +- identity_credential/Cargo.toml | 10 +++++----- identity_did/Cargo.toml | 4 ++-- identity_document/Cargo.toml | 8 ++++---- identity_ecdsa_verifier/Cargo.toml | 4 ++-- identity_eddsa_verifier/Cargo.toml | 4 ++-- identity_iota/Cargo.toml | 18 +++++++++--------- identity_iota/README.md | 4 ++-- identity_iota_core/Cargo.toml | 12 ++++++------ identity_jose/Cargo.toml | 4 ++-- identity_resolver/Cargo.toml | 12 ++++++------ identity_storage/Cargo.toml | 18 +++++++++--------- identity_stronghold/Cargo.toml | 10 +++++----- identity_verification/Cargo.toml | 8 ++++---- 17 files changed, 75 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f42479f29..45d3fa510e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,27 @@ # Changelog +## [v1.3.1](https://github.com/iotaledger/identity.rs/tree/v1.3.1) (2024-06-12) + +[Full Changelog](https://github.com/iotaledger/identity.rs/compare/v1.3.0...v1.3.1) + +### Patch + +- Pin and bump `bls12_381_plus` dependency [\#1378](https://github.com/iotaledger/identity.rs/pull/1378) + +# Changelog + ## [v1.3.0](https://github.com/iotaledger/identity.rs/tree/v1.3.0) (2024-05-28) [Full Changelog](https://github.com/iotaledger/identity.rs/compare/v1.2.0...v1.3.0) ### Added -- Add ZK BBS+-based selectively disclosable credentials (JPT) [\#1355](https://github.com/iotaledger/identity.rs/pull/1355) + +- Add ZK BBS+-based selectively disclosable credentials \(JPT\) [\#1355](https://github.com/iotaledger/identity.rs/pull/1355) - Add EcDSA verifier [\#1353](https://github.com/iotaledger/identity.rs/pull/1353) ### Patch -- Support for specification-compliant verification method type `JsonWebKey2020` [\#1367](https://github.com/iotaledger/identity.rs/pull/1367) +- Support for specification-compliant verification method type `JsonWebKey2020` [\#1367](https://github.com/iotaledger/identity.rs/pull/1367) ## [v1.2.0](https://github.com/iotaledger/identity.rs/tree/v1.2.0) (2024-03-27) diff --git a/README.md b/README.md index af03f510af..e8001e6788 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ If you want to include IOTA Identity in your project, simply add it as a depende ```toml [dependencies] -identity_iota = { version = "1.3.0" } +identity_iota = { version = "1.3.1" } ``` To try out the [examples](https://github.com/iotaledger/identity.rs/blob/HEAD/examples), you can also do this: @@ -88,7 +88,7 @@ version = "1.0.0" edition = "2021" [dependencies] -identity_iota = { version = "1.3.0", features = ["memstore"] } +identity_iota = { version = "1.3.1", features = ["memstore"] } iota-sdk = { version = "1.0.2", default-features = true, features = ["tls", "client", "stronghold"] } tokio = { version = "1", features = ["full"] } anyhow = "1.0.62" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a8b1588221..9fe5984123 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "examples" -version = "1.3.0" +version = "1.3.1" authors = ["IOTA Stiftung"] edition = "2021" publish = false diff --git a/identity_core/Cargo.toml b/identity_core/Cargo.toml index 39c15fabd0..0f7a8a34eb 100644 --- a/identity_core/Cargo.toml +++ b/identity_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_core" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true diff --git a/identity_credential/Cargo.toml b/identity_credential/Cargo.toml index 07f119b853..2a4b11d09c 100644 --- a/identity_credential/Cargo.toml +++ b/identity_credential/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_credential" -version = "1.3.0" +version = "1.3.1" authors = ["IOTA Stiftung"] edition = "2021" homepage.workspace = true @@ -16,10 +16,10 @@ async-trait = { version = "0.1.64", default-features = false } bls12_381_plus = { workspace = true, optional = true } flate2 = { version = "1.0.28", default-features = false, features = ["rust_backend"], optional = true } futures = { version = "0.3", default-features = false, optional = true } -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } indexmap = { version = "2.0", default-features = false, features = ["std", "serde"] } itertools = { version = "0.11", default-features = false, features = ["use_std"], optional = true } json-proof-token = { workspace = true, optional = true } diff --git a/identity_did/Cargo.toml b/identity_did/Cargo.toml index 5fdca4b370..5b4e85069c 100644 --- a/identity_did/Cargo.toml +++ b/identity_did/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_did" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition = "2021" homepage.workspace = true @@ -13,7 +13,7 @@ description = "Agnostic implementation of the Decentralized Identifiers (DID) st [dependencies] 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.3.0", path = "../identity_core" } +identity_core = { version = "=1.3.1", path = "../identity_core" } serde.workspace = true strum.workspace = true thiserror.workspace = true diff --git a/identity_document/Cargo.toml b/identity_document/Cargo.toml index 091e1a0ee4..456323707d 100644 --- a/identity_document/Cargo.toml +++ b/identity_document/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_document" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -13,9 +13,9 @@ description = "Method-agnostic implementation of the Decentralized Identifiers ( [dependencies] did_url_parser = { version = "0.2.0", features = ["std", "serde"] } -identity_core = { version = "=1.3.0", path = "../identity_core" } -identity_did = { version = "=1.3.0", path = "../identity_did" } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core" } +identity_did = { version = "=1.3.1", path = "../identity_did" } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } indexmap = { version = "2.0", default-features = false, features = ["std", "serde"] } serde.workspace = true strum.workspace = true diff --git a/identity_ecdsa_verifier/Cargo.toml b/identity_ecdsa_verifier/Cargo.toml index 13ec1edb2a..654b8aebe3 100644 --- a/identity_ecdsa_verifier/Cargo.toml +++ b/identity_ecdsa_verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_ecdsa_verifier" -version = "1.3.0" +version = "1.3.1" authors = ["IOTA Stiftung", "Filancore GmbH"] edition.workspace = true homepage.workspace = true @@ -15,7 +15,7 @@ description = "JWS ECDSA signature verification for IOTA Identity" workspace = true [dependencies] -identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } k256 = { version = "0.13.3", default-features = false, features = ["std", "ecdsa", "ecdsa-core"], optional = true } p256 = { version = "0.13.2", default-features = false, features = ["std", "ecdsa", "ecdsa-core"], optional = true } signature = { version = "2", default-features = false } diff --git a/identity_eddsa_verifier/Cargo.toml b/identity_eddsa_verifier/Cargo.toml index 0af8f31dd0..eedd1d652e 100644 --- a/identity_eddsa_verifier/Cargo.toml +++ b/identity_eddsa_verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_eddsa_verifier" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -12,7 +12,7 @@ rust-version.workspace = true description = "JWS EdDSA signature verification for IOTA Identity" [dependencies] -identity_jose = { version = "=1.3.0", path = "../identity_jose", default-features = false } +identity_jose = { version = "=1.3.1", path = "../identity_jose", default-features = false } iota-crypto = { version = "0.23", default-features = false, features = ["std"] } [features] diff --git a/identity_iota/Cargo.toml b/identity_iota/Cargo.toml index 0e0187801e..4e32790288 100644 --- a/identity_iota/Cargo.toml +++ b/identity_iota/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_iota" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -12,14 +12,14 @@ rust-version.workspace = true description = "Framework for Self-Sovereign Identity with IOTA DID." [dependencies] -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_credential = { version = "=1.3.0", path = "../identity_credential", features = ["validator"], default-features = false } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } -identity_iota_core = { version = "=1.3.0", path = "../identity_iota_core", default-features = false } -identity_resolver = { version = "=1.3.0", path = "../identity_resolver", default-features = false, optional = true } -identity_storage = { version = "=1.3.0", path = "../identity_storage", default-features = false, features = ["iota-document"] } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_credential = { version = "=1.3.1", path = "../identity_credential", features = ["validator"], default-features = false } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } +identity_iota_core = { version = "=1.3.1", path = "../identity_iota_core", default-features = false } +identity_resolver = { version = "=1.3.1", path = "../identity_resolver", default-features = false, optional = true } +identity_storage = { version = "=1.3.1", path = "../identity_storage", default-features = false, features = ["iota-document"] } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } [dev-dependencies] anyhow = "1.0.64" diff --git a/identity_iota/README.md b/identity_iota/README.md index af03f510af..e8001e6788 100644 --- a/identity_iota/README.md +++ b/identity_iota/README.md @@ -54,7 +54,7 @@ If you want to include IOTA Identity in your project, simply add it as a depende ```toml [dependencies] -identity_iota = { version = "1.3.0" } +identity_iota = { version = "1.3.1" } ``` To try out the [examples](https://github.com/iotaledger/identity.rs/blob/HEAD/examples), you can also do this: @@ -88,7 +88,7 @@ version = "1.0.0" edition = "2021" [dependencies] -identity_iota = { version = "1.3.0", features = ["memstore"] } +identity_iota = { version = "1.3.1", features = ["memstore"] } iota-sdk = { version = "1.0.2", default-features = true, features = ["tls", "client", "stronghold"] } tokio = { version = "1", features = ["full"] } anyhow = "1.0.62" diff --git a/identity_iota_core/Cargo.toml b/identity_iota_core/Cargo.toml index e2539b28c0..0ddb2bd6b9 100644 --- a/identity_iota_core/Cargo.toml +++ b/identity_iota_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_iota_core" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -14,11 +14,11 @@ description = "An IOTA Ledger integration for the IOTA DID Method." [dependencies] async-trait = { version = "0.1.56", default-features = false, optional = true } futures = { version = "0.3", default-features = false } -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_credential = { version = "=1.3.0", path = "../identity_credential", default-features = false, features = ["validator"] } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_credential = { version = "=1.3.1", path = "../identity_credential", default-features = false, features = ["validator"] } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } iota-sdk = { version = "1.1.5", default-features = false, features = ["serde", "std"], optional = true } num-derive = { version = "0.4", default-features = false } num-traits = { version = "0.2", default-features = false, features = ["std"] } diff --git a/identity_jose/Cargo.toml b/identity_jose/Cargo.toml index 3176142f33..32d3824a9a 100644 --- a/identity_jose/Cargo.toml +++ b/identity_jose/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_jose" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -13,7 +13,7 @@ description = "A library for JOSE (JSON Object Signing and Encryption)" [dependencies] bls12_381_plus.workspace = true -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } iota-crypto = { version = "0.23", default-features = false, features = ["std", "sha"] } json-proof-token.workspace = true serde.workspace = true diff --git a/identity_resolver/Cargo.toml b/identity_resolver/Cargo.toml index e6d93b03f0..a85969c286 100644 --- a/identity_resolver/Cargo.toml +++ b/identity_resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_resolver" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -15,16 +15,16 @@ description = "DID Resolution utilities for the identity.rs library." # This is currently necessary for the ResolutionHandler trait. This can be made an optional dependency if alternative ways of attaching handlers are introduced. async-trait = { version = "0.1", default-features = false } futures = { version = "0.3" } -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_credential = { version = "=1.3.0", path = "../identity_credential", default-features = false, features = ["validator"] } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_credential = { version = "=1.3.1", path = "../identity_credential", default-features = false, features = ["validator"] } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } serde = { version = "1.0", default-features = false, features = ["std", "derive"] } strum.workspace = true thiserror = { version = "1.0", default-features = false } [dependencies.identity_iota_core] -version = "=1.3.0" +version = "=1.3.1" path = "../identity_iota_core" default-features = false features = ["send-sync-client-ext", "iota-client"] diff --git a/identity_storage/Cargo.toml b/identity_storage/Cargo.toml index 54c1a63b36..08a0d68d7d 100644 --- a/identity_storage/Cargo.toml +++ b/identity_storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_storage" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -16,12 +16,12 @@ anyhow = "1.0.82" async-trait = { version = "0.1.64", default-features = false } bls12_381_plus = { workspace = true, optional = true } futures = { version = "0.3.27", default-features = false, features = ["async-await"] } -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_credential = { version = "=1.3.0", path = "../identity_credential", default-features = false, features = ["credential", "presentation", "revocation-bitmap"] } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } -identity_iota_core = { version = "=1.3.0", path = "../identity_iota_core", default-features = false, optional = true } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default_features = false } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_credential = { version = "=1.3.1", path = "../identity_credential", default-features = false, features = ["credential", "presentation", "revocation-bitmap"] } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } +identity_iota_core = { version = "=1.3.1", path = "../identity_iota_core", default-features = false, optional = true } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default_features = false } iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"], optional = true } json-proof-token = { workspace = true, optional = true } rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true } @@ -33,8 +33,8 @@ tokio = { version = "1.29.0", default-features = false, features = ["macros", "s zkryptium = { workspace = true, optional = true } [dev-dependencies] -identity_credential = { version = "=1.3.0", path = "../identity_credential", features = ["revocation-bitmap"] } -identity_eddsa_verifier = { version = "=1.3.0", path = "../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } +identity_credential = { version = "=1.3.1", path = "../identity_credential", features = ["revocation-bitmap"] } +identity_eddsa_verifier = { version = "=1.3.1", path = "../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } once_cell = { version = "1.18", default-features = false } tokio = { version = "1.29.0", default-features = false, features = ["macros", "sync", "rt"] } diff --git a/identity_stronghold/Cargo.toml b/identity_stronghold/Cargo.toml index cd3cabd0bb..56ae126bdc 100644 --- a/identity_stronghold/Cargo.toml +++ b/identity_stronghold/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_stronghold" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -14,8 +14,8 @@ description = "Secure JWK storage with Stronghold for IOTA Identity" [dependencies] async-trait = { version = "0.1.64", default-features = false } bls12_381_plus = { workspace = true, optional = true } -identity_storage = { version = "=1.3.0", path = "../identity_storage", default_features = false } -identity_verification = { version = "=1.3.0", path = "../identity_verification", default_features = false } +identity_storage = { version = "=1.3.1", path = "../identity_storage", default_features = false } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default_features = false } iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"] } iota-sdk = { version = "1.1.5", default-features = false, features = ["client", "stronghold"] } iota_stronghold = { version = "2.1.0", default-features = false } @@ -28,8 +28,8 @@ zkryptium = { workspace = true, optional = true } [dev-dependencies] anyhow = "1.0.82" bls12_381_plus = { workspace = true } -identity_did = { version = "=1.3.0", path = "../identity_did", default_features = false } -identity_storage = { version = "=1.3.0", path = "../identity_storage", default_features = false, features = ["jpt-bbs-plus"] } +identity_did = { version = "=1.3.1", path = "../identity_did", default_features = false } +identity_storage = { version = "=1.3.1", path = "../identity_storage", default_features = false, features = ["jpt-bbs-plus"] } json-proof-token = { workspace = true } tokio = { version = "1.29.0", default-features = false, features = ["macros", "sync", "rt"] } zkryptium = { workspace = true } diff --git a/identity_verification/Cargo.toml b/identity_verification/Cargo.toml index 41ba1f2aa3..2ff4fb1e9b 100644 --- a/identity_verification/Cargo.toml +++ b/identity_verification/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_verification" -version = "1.3.0" +version = "1.3.1" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -10,9 +10,9 @@ rust-version.workspace = true description = "Verification data types and functionality for identity.rs" [dependencies] -identity_core = { version = "=1.3.0", path = "./../identity_core", default-features = false } -identity_did = { version = "=1.3.0", path = "./../identity_did", default-features = false } -identity_jose = { version = "=1.3.0", path = "./../identity_jose", default-features = false } +identity_core = { version = "=1.3.1", path = "./../identity_core", default-features = false } +identity_did = { version = "=1.3.1", path = "./../identity_did", default-features = false } +identity_jose = { version = "=1.3.1", path = "./../identity_jose", default-features = false } serde.workspace = true serde_json.workspace = true strum.workspace = true From 5671118e4e85f1a3a7301b9da1229bd0555cdfe2 Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Thu, 13 Jun 2024 16:06:04 +0200 Subject: [PATCH 08/22] resolver integration --- Cargo.toml | 1 - compound_resolver/Cargo.toml | 4 +- compound_resolver/src/lib.rs | 32 +- examples/0_basic/2_resolve_did.rs | 14 - examples/0_basic/6_create_vp.rs | 11 +- examples/0_basic/7_revoke_vc.rs | 4 +- examples/0_basic/8_stronghold.rs | 4 +- examples/1_advanced/10_zkp_revocation.rs | 5 +- examples/1_advanced/5_custom_resolution.rs | 82 ++-- examples/1_advanced/6_domain_linkage.rs | 8 +- examples/1_advanced/9_zkp.rs | 7 +- identity_iota/Cargo.toml | 8 +- identity_iota/src/lib.rs | 1 + identity_new_resolver/Cargo.toml | 20 - identity_new_resolver/src/error.rs | 13 - identity_new_resolver/src/lib.rs | 7 - identity_new_resolver/src/resolver.rs | 8 - identity_new_resolver/tests/compound.rs | 97 ---- identity_resolver/Cargo.toml | 39 +- identity_resolver/README.md | 4 - identity_resolver/src/error.rs | 85 +--- identity_resolver/src/iota.rs | 64 +++ identity_resolver/src/lib.rs | 27 +- identity_resolver/src/resolution/commands.rs | 142 ------ identity_resolver/src/resolution/mod.rs | 14 - identity_resolver/src/resolution/resolver.rs | 417 ------------------ identity_resolver/src/resolution/tests/mod.rs | 6 - .../src/resolution/tests/resolution.rs | 281 ------------ .../src/resolution/tests/send_sync.rs | 26 -- identity_resolver/src/resolver.rs | 17 + 30 files changed, 176 insertions(+), 1272 deletions(-) delete mode 100644 identity_new_resolver/Cargo.toml delete mode 100644 identity_new_resolver/src/error.rs delete mode 100644 identity_new_resolver/src/lib.rs delete mode 100644 identity_new_resolver/src/resolver.rs delete mode 100644 identity_new_resolver/tests/compound.rs delete mode 100644 identity_resolver/README.md create mode 100644 identity_resolver/src/iota.rs delete mode 100644 identity_resolver/src/resolution/commands.rs delete mode 100644 identity_resolver/src/resolution/mod.rs delete mode 100644 identity_resolver/src/resolution/resolver.rs delete mode 100644 identity_resolver/src/resolution/tests/mod.rs delete mode 100644 identity_resolver/src/resolution/tests/resolution.rs delete mode 100644 identity_resolver/src/resolution/tests/send_sync.rs create mode 100644 identity_resolver/src/resolver.rs diff --git a/Cargo.toml b/Cargo.toml index 861ef7dbc1..bb908e0ecf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ members = [ "identity_ecdsa_verifier", "identity_eddsa_verifier", "examples", - "identity_new_resolver", "compound_resolver", ] diff --git a/compound_resolver/Cargo.toml b/compound_resolver/Cargo.toml index a78d82539d..51c009c12c 100644 --- a/compound_resolver/Cargo.toml +++ b/compound_resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "compound_resolver" -version = "0.1.0" +version = "1.3.0" authors.workspace = true edition.workspace = true homepage.workspace = true @@ -12,7 +12,7 @@ rust-version.workspace = true itertools = "0.13.0" proc-macro2 = "1.0.85" quote = "1.0.36" -syn = { versin = "2.0.66", features = ["full", "extra-traits"] } +syn = { version = "2.0.66", features = ["full", "extra-traits"] } [lints] workspace = true diff --git a/compound_resolver/src/lib.rs b/compound_resolver/src/lib.rs index 7e6d1bf7e1..a778c9141a 100644 --- a/compound_resolver/src/lib.rs +++ b/compound_resolver/src/lib.rs @@ -1,7 +1,16 @@ +use itertools::Itertools; use proc_macro::TokenStream; use quote::quote; -use syn::{parse::Parse, punctuated::Punctuated, Attribute, Data, DeriveInput, Expr, Field, Ident, Token, Type}; -use itertools::Itertools; +use syn::parse::Parse; +use syn::punctuated::Punctuated; +use syn::Attribute; +use syn::Data; +use syn::DeriveInput; +use syn::Expr; +use syn::Field; +use syn::Ident; +use syn::Token; +use syn::Type; #[proc_macro_derive(CompoundResolver, attributes(resolver))] pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { @@ -21,13 +30,12 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { .into_iter() // parse all the fields that are annoted with #[resolver(..)] .filter_map(ResolverField::from_field) - // create an iterator over (field_name, Resolver::I, Resolver::T, predicate) + // Group together all resolvers with the same signature (input_ty, target_ty). .flat_map(|ResolverField { ident, impls }| { impls .into_iter() .map(move |ResolverImpl { input, target, pred }| ((input, target), (ident.clone(), pred))) }) - // Group together all resolvers with the same signature (input_ty, target_ty). .into_group_map() .into_iter() // generates code that forward the implementation of Resolver to field_name, if there's multiple fields @@ -36,9 +44,9 @@ pub fn derive_macro_compound_resolver(input: TokenStream) -> TokenStream { let len = impls.len(); let impl_block = gen_impl_block_multiple_resolvers(impls.into_iter(), len); quote! { - impl ::identity_new_resolver::Resolver<#input_ty> for #struct_ident #generics { + impl ::identity_iota::resolver::Resolver<#input_ty> for #struct_ident #generics { type Target = #target_ty; - async fn resolve(&self, input: &#input_ty) -> std::result::Result { + async fn resolve(&self, input: &#input_ty) -> std::result::Result { #impl_block } } @@ -61,8 +69,11 @@ fn gen_impl_block_single_resolver_with_pred(field_name: Ident, pred: Expr) -> pr } } -fn gen_impl_block_multiple_resolvers(impls: impl Iterator)>, len: usize) -> proc_macro2::TokenStream { - impls +fn gen_impl_block_multiple_resolvers( + impls: impl Iterator)>, + len: usize, +) -> proc_macro2::TokenStream { + impls .enumerate() .map(|(i, (field_name, pred))| { if let Some(pred) = pred { @@ -122,9 +133,6 @@ struct ResolverImpl { impl Parse for ResolverImpl { fn parse(input: syn::parse::ParseStream) -> syn::Result { - // let mut tys = Punctuated::]>::parse_separated_nonempty(input)? - // .into_iter() - // .take(2); let input_ty = input.parse::()?; let _ = input.parse::]>()?; let target_ty = input.parse::()?; @@ -139,7 +147,7 @@ impl Parse for ResolverImpl { ResolverImpl { input: input_ty, target: target_ty, - pred + pred, } }) } diff --git a/examples/0_basic/2_resolve_did.rs b/examples/0_basic/2_resolve_did.rs index 4e648f8370..e56167d54c 100644 --- a/examples/0_basic/2_resolve_did.rs +++ b/examples/0_basic/2_resolve_did.rs @@ -9,7 +9,6 @@ use identity_iota::iota::block::address::Address; use identity_iota::iota::IotaDocument; use identity_iota::iota::IotaIdentityClientExt; -use identity_iota::prelude::Resolver; use identity_iota::storage::JwkMemStore; use identity_iota::storage::KeyIdMemstore; use iota_sdk::client::secret::stronghold::StrongholdSecretManager; @@ -45,19 +44,6 @@ async fn main() -> anyhow::Result<()> { let client_document: IotaDocument = client.resolve_did(&did).await?; println!("Client resolved DID Document: {client_document:#}"); - // We can also create a `Resolver` that has additional convenience methods, - // for example to resolve presentation issuers or to verify presentations. - let mut resolver = Resolver::::new(); - - // We need to register a handler that can resolve IOTA DIDs. - // This convenience method only requires us to provide a client. - resolver.attach_iota_handler(client.clone()); - - let resolver_document: IotaDocument = resolver.resolve(&did).await.unwrap(); - - // Client and Resolver resolve to the same document in this case. - assert_eq!(client_document, resolver_document); - // We can also resolve the Alias Output directly. let alias_output: AliasOutput = client.resolve_did_output(&did).await?; diff --git a/examples/0_basic/6_create_vp.rs b/examples/0_basic/6_create_vp.rs index 8c157295ef..138c763c05 100644 --- a/examples/0_basic/6_create_vp.rs +++ b/examples/0_basic/6_create_vp.rs @@ -7,8 +7,6 @@ //! //! cargo run --release --example 6_create_vp -use std::collections::HashMap; - use examples::create_did; use examples::MemStorage; use identity_eddsa_verifier::EdDSAJwsVerifier; @@ -190,12 +188,9 @@ async fn main() -> anyhow::Result<()> { let presentation_verifier_options: JwsVerificationOptions = JwsVerificationOptions::default().nonce(challenge.to_owned()); - let mut resolver: Resolver = Resolver::new(); - resolver.attach_iota_handler(client); - // Resolve the holder's document. let holder_did: CoreDID = JwtPresentationValidatorUtils::extract_holder(&presentation_jwt)?; - let holder: IotaDocument = resolver.resolve(&holder_did).await?; + let holder: IotaDocument = client.resolve(&holder_did).await?; // Validate presentation. Note that this doesn't validate the included credentials. let presentation_validation_options = @@ -211,7 +206,7 @@ async fn main() -> anyhow::Result<()> { .iter() .map(JwtCredentialValidatorUtils::extract_issuer_from_jwt) .collect::, _>>()?; - let issuers_documents: HashMap = resolver.resolve_multiple(&issuers).await?; + let issuers_documents: Vec = client.resolve_multiple(&issuers).await?; // Validate the credentials in the presentation. let credential_validator: JwtCredentialValidator = @@ -221,7 +216,7 @@ async fn main() -> anyhow::Result<()> { for (index, jwt_vc) in jwt_credentials.iter().enumerate() { // SAFETY: Indexing should be fine since we extracted the DID from each credential and resolved it. - let issuer_document: &IotaDocument = &issuers_documents[&issuers[index]]; + let issuer_document: &IotaDocument = &issuers_documents[index]; let _decoded_credential: DecodedJwtCredential = credential_validator .validate::<_, Object>(jwt_vc, issuer_document, &validation_options, FailFast::FirstError) diff --git a/examples/0_basic/7_revoke_vc.rs b/examples/0_basic/7_revoke_vc.rs index 864041f3e3..b0512bb913 100644 --- a/examples/0_basic/7_revoke_vc.rs +++ b/examples/0_basic/7_revoke_vc.rs @@ -211,10 +211,8 @@ async fn main() -> anyhow::Result<()> { client.publish_did_output(&secret_manager_issuer, alias_output).await?; // We expect the verifiable credential to be revoked. - let mut resolver: Resolver = Resolver::new(); - resolver.attach_iota_handler(client); let resolved_issuer_did: IotaDID = JwtCredentialValidatorUtils::extract_issuer_from_jwt(&credential_jwt)?; - let resolved_issuer_doc: IotaDocument = resolver.resolve(&resolved_issuer_did).await?; + let resolved_issuer_doc: IotaDocument = client.resolve(&resolved_issuer_did).await?; let validation_result = validator.validate::<_, Object>( &credential_jwt, diff --git a/examples/0_basic/8_stronghold.rs b/examples/0_basic/8_stronghold.rs index 0681e5b612..4aa223a027 100644 --- a/examples/0_basic/8_stronghold.rs +++ b/examples/0_basic/8_stronghold.rs @@ -89,9 +89,7 @@ async fn main() -> anyhow::Result<()> { .await?; // Resolve the published DID Document. - let mut resolver = Resolver::::new(); - resolver.attach_iota_handler(client.clone()); - let resolved_document: IotaDocument = resolver.resolve(document.id()).await.unwrap(); + let resolved_document: IotaDocument = client.resolve(document.id()).await.unwrap(); drop(stronghold_storage); diff --git a/examples/1_advanced/10_zkp_revocation.rs b/examples/1_advanced/10_zkp_revocation.rs index a78dea0e76..55c57f1467 100644 --- a/examples/1_advanced/10_zkp_revocation.rs +++ b/examples/1_advanced/10_zkp_revocation.rs @@ -413,12 +413,9 @@ async fn main() -> anyhow::Result<()> { let presentation_verifier_options: JwsVerificationOptions = JwsVerificationOptions::default().nonce(challenge.to_owned()); - let mut resolver: Resolver = Resolver::new(); - resolver.attach_iota_handler(client.clone()); - // Resolve the holder's document. let holder_did: CoreDID = JwtPresentationValidatorUtils::extract_holder(&presentation_jwt)?; - let holder: IotaDocument = resolver.resolve(&holder_did).await?; + let holder: IotaDocument = client.resolve(&holder_did).await?; // Validate presentation. Note that this doesn't validate the included credentials. let presentation_validation_options = diff --git a/examples/1_advanced/5_custom_resolution.rs b/examples/1_advanced/5_custom_resolution.rs index b0675c8dd5..4492d3ea6d 100644 --- a/examples/1_advanced/5_custom_resolution.rs +++ b/examples/1_advanced/5_custom_resolution.rs @@ -12,6 +12,8 @@ use identity_iota::did::DID; use identity_iota::document::CoreDocument; use identity_iota::iota::IotaDID; use identity_iota::iota::IotaDocument; +use identity_iota::resolver::CompoundResolver; +use identity_iota::resolver::Error as ResolverError; use identity_iota::resolver::Resolver; use identity_iota::storage::JwkMemStore; use identity_iota::storage::KeyIdMemstore; @@ -25,21 +27,38 @@ use iota_sdk::types::block::address::Address; /// /// NOTE: Since both `IotaDocument` and `FooDocument` implement `Into` we could have used /// Resolver in this example and just worked with `CoreDocument` representations throughout. + +// Create a resolver capable of resolving FooDocument. +struct FooResolver; +impl Resolver for FooResolver { + type Target = FooDocument; + async fn resolve(&self, input: &CoreDID) -> Result { + Ok(resolve_did_foo(input.clone()).await?) + } +} + +// Combine it with a resolver of IotaDocuments, creating a new resolver capable of resolving both. +#[derive(CompoundResolver)] +struct FooAndIotaResolver { + #[resolver(CoreDID -> FooDocument)] + foo: FooResolver, + #[resolver(IotaDID -> IotaDocument)] + iota: Client, +} + #[tokio::main] async fn main() -> anyhow::Result<()> { - // Create a resolver returning an enum of the documents we are interested in and attach handlers for the "foo" and - // "iota" methods. - let mut resolver: Resolver = Resolver::new(); - // Create a new client to interact with the IOTA ledger. let client: Client = Client::builder() .with_primary_node(API_ENDPOINT, None)? .finish() .await?; - // This is a convenience method for attaching a handler for the "iota" method by providing just a client. - resolver.attach_iota_handler(client.clone()); - resolver.attach_handler("foo".to_owned(), resolve_did_foo); + // Create a resolver capable of resolving both IotaDocument and FooDocument. + let resolver = FooAndIotaResolver { + iota: client.clone(), + foo: FooResolver {}, + }; // A fake did:foo DID for demonstration purposes. let did_foo: CoreDID = "did:foo:0e9c8294eeafee326a4e96d65dbeaca0".parse()?; @@ -58,28 +77,14 @@ async fn main() -> anyhow::Result<()> { let iota_did: IotaDID = iota_document.id().clone(); // Resolve did_foo to get an abstract document. - let did_foo_doc: Document = resolver.resolve(&did_foo).await?; + let did_foo_doc: FooDocument = resolver.resolve(&did_foo).await?; // Resolve iota_did to get an abstract document. - let iota_doc: Document = resolver.resolve(&iota_did).await?; - - // The Resolver is mainly meant for validating presentations, but here we will just - // check that the resolved documents match our expectations. - - let Document::Foo(did_foo_document) = did_foo_doc else { - anyhow::bail!("expected a foo DID document when resolving a foo DID"); - }; + let iota_doc: IotaDocument = resolver.resolve(&iota_did).await?; - println!( - "Resolved DID foo document: {}", - did_foo_document.as_ref().to_json_pretty()? - ); - - let Document::Iota(iota_document) = iota_doc else { - anyhow::bail!("expected an IOTA DID document when resolving an IOTA DID") - }; + println!("Resolved DID foo document: {}", did_foo_doc.as_ref().to_json_pretty()?); - println!("Resolved IOTA DID document: {}", iota_document.to_json_pretty()?); + println!("Resolved IOTA DID document: {}", iota_doc.to_json_pretty()?); Ok(()) } @@ -108,33 +113,6 @@ impl From for CoreDocument { } } -// Enum of the document types we want to handle. -enum Document { - Foo(FooDocument), - Iota(IotaDocument), -} - -impl From for Document { - fn from(value: FooDocument) -> Self { - Self::Foo(value) - } -} - -impl From for Document { - fn from(value: IotaDocument) -> Self { - Self::Iota(value) - } -} - -impl AsRef for Document { - fn as_ref(&self) -> &CoreDocument { - match self { - Self::Foo(doc) => doc.as_ref(), - Self::Iota(doc) => doc.as_ref(), - } - } -} - /// Resolve a did to a DID document if the did method is "foo". async fn resolve_did_foo(did: CoreDID) -> anyhow::Result { let doc = CoreDocument::from_json(&format!( diff --git a/examples/1_advanced/6_domain_linkage.rs b/examples/1_advanced/6_domain_linkage.rs index 6e7a629110..20d23f975c 100644 --- a/examples/1_advanced/6_domain_linkage.rs +++ b/examples/1_advanced/6_domain_linkage.rs @@ -134,10 +134,6 @@ async fn main() -> anyhow::Result<()> { // while the second answers "What domain is this DID linked to?". // ===================================================== - // Init a resolver for resolving DID Documents. - let mut resolver: Resolver = Resolver::new(); - resolver.attach_iota_handler(client.clone()); - // ===================================================== // → Case 1: starting from domain // ===================================================== @@ -152,7 +148,7 @@ async fn main() -> anyhow::Result<()> { assert_eq!(linked_dids.len(), 1); // Resolve the DID Document of the DID that issued the credential. - let issuer_did_document: IotaDocument = resolver.resolve(&did).await?; + let issuer_did_document: IotaDocument = client.resolve(&did).await?; // Validate the linkage between the Domain Linkage Credential in the configuration and the provided issuer DID. let validation_result: Result<(), DomainLinkageValidationError> = @@ -167,7 +163,7 @@ async fn main() -> anyhow::Result<()> { // ===================================================== // → Case 2: starting from a DID // ===================================================== - let did_document: IotaDocument = resolver.resolve(&did).await?; + let did_document: IotaDocument = client.resolve(&did).await?; // Get the Linked Domain Services from the DID Document. let linked_domain_services: Vec = did_document diff --git a/examples/1_advanced/9_zkp.rs b/examples/1_advanced/9_zkp.rs index eeb4246280..97a10b0864 100644 --- a/examples/1_advanced/9_zkp.rs +++ b/examples/1_advanced/9_zkp.rs @@ -164,12 +164,9 @@ async fn main() -> anyhow::Result<()> { // Step 4: Holder resolves Issuer's DID, retrieve Issuer's document and validate the Credential // ============================================================================================ - let mut resolver: Resolver = Resolver::new(); - resolver.attach_iota_handler(client); - // Holder resolves issuer's DID let issuer: CoreDID = JptCredentialValidatorUtils::extract_issuer_from_issued_jpt(&credential_jpt).unwrap(); - let issuer_document: IotaDocument = resolver.resolve(&issuer).await?; + let issuer_document: IotaDocument = client.resolve(&issuer).await?; // Holder validates the credential and retrieve the JwpIssued, needed to construct the JwpPresented let decoded_credential = JptCredentialValidator::validate::<_, Object>( @@ -237,7 +234,7 @@ async fn main() -> anyhow::Result<()> { // Verifier resolve Issuer DID let issuer: CoreDID = JptPresentationValidatorUtils::extract_issuer_from_presented_jpt(&presentation_jpt).unwrap(); - let issuer_document: IotaDocument = resolver.resolve(&issuer).await?; + let issuer_document: IotaDocument = client.resolve(&issuer).await?; let presentation_validation_options = JptPresentationValidationOptions::default().nonce(challenge); diff --git a/identity_iota/Cargo.toml b/identity_iota/Cargo.toml index 0e0187801e..8d6092880a 100644 --- a/identity_iota/Cargo.toml +++ b/identity_iota/Cargo.toml @@ -17,9 +17,10 @@ identity_credential = { version = "=1.3.0", path = "../identity_credential", fea identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } identity_iota_core = { version = "=1.3.0", path = "../identity_iota_core", default-features = false } -identity_resolver = { version = "=1.3.0", path = "../identity_resolver", default-features = false, optional = true } identity_storage = { version = "=1.3.0", path = "../identity_storage", default-features = false, features = ["iota-document"] } identity_verification = { version = "=1.3.0", path = "../identity_verification", default-features = false } +identity_resolver = { version = "=1.3.0", path = "../identity_resolver", default-features = false, features = ["iota"] } +compound_resolver = { version = "=1.3.0", path = "../compound_resolver" } [dev-dependencies] anyhow = "1.0.64" @@ -34,20 +35,19 @@ default = ["revocation-bitmap", "client", "iota-client", "resolver"] client = ["identity_iota_core/client"] # Enables the iota-client integration, the client trait implementations for it, and the `IotaClientExt` trait. -iota-client = ["identity_iota_core/iota-client", "identity_resolver?/iota"] +iota-client = ["identity_iota_core/iota-client", "identity_resolver/iota"] # Enables revocation with `RevocationBitmap2022`. revocation-bitmap = [ "identity_credential/revocation-bitmap", "identity_iota_core/revocation-bitmap", - "identity_resolver?/revocation-bitmap", ] # Enables revocation with `StatusList2021`. status-list-2021 = ["revocation-bitmap", "identity_credential/status-list-2021"] # Enables support for the `Resolver`. -resolver = ["dep:identity_resolver"] +resolver = [] # Enables `Send` + `Sync` bounds for the storage traits. send-sync-storage = ["identity_storage/send-sync-storage"] diff --git a/identity_iota/src/lib.rs b/identity_iota/src/lib.rs index 9ab2e53805..d84eb2765f 100644 --- a/identity_iota/src/lib.rs +++ b/identity_iota/src/lib.rs @@ -95,6 +95,7 @@ pub mod prelude { pub mod resolver { //! DID resolution utilities + pub use compound_resolver::CompoundResolver; pub use identity_resolver::*; } diff --git a/identity_new_resolver/Cargo.toml b/identity_new_resolver/Cargo.toml deleted file mode 100644 index aadc8c7b0c..0000000000 --- a/identity_new_resolver/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "identity_new_resolver" -version = "0.1.0" -authors.workspace = true -edition.workspace = true -homepage.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true - -[dependencies] -anyhow = "1.0.86" -thiserror.workspace = true -compound_resolver = { path = "../compound_resolver" } - -[lints] -workspace = true - -[dev-dependencies] -tokio = { version = "1.38.0", features = ["macros", "rt"] } diff --git a/identity_new_resolver/src/error.rs b/identity_new_resolver/src/error.rs deleted file mode 100644 index d9d9b984a9..0000000000 --- a/identity_new_resolver/src/error.rs +++ /dev/null @@ -1,13 +0,0 @@ -use thiserror::Error; - -pub type Result = std::result::Result; - -#[derive(Debug, Error)] -pub enum Error { - #[error("The requested item \"{0}\" was not found.")] - NotFound(String), - #[error("Failed to parse the provided input into a resolvable type: {0}")] - ParsingFailure(#[source] anyhow::Error), - #[error(transparent)] - Generic(anyhow::Error), -} diff --git a/identity_new_resolver/src/lib.rs b/identity_new_resolver/src/lib.rs deleted file mode 100644 index 6238ab24db..0000000000 --- a/identity_new_resolver/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod resolver; -mod error; - -pub use error::{Result, Error}; -pub use resolver::Resolver; - -pub use compound_resolver::CompoundResolver; \ No newline at end of file diff --git a/identity_new_resolver/src/resolver.rs b/identity_new_resolver/src/resolver.rs deleted file mode 100644 index b7499a3991..0000000000 --- a/identity_new_resolver/src/resolver.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(async_fn_in_trait)] - -use crate::Result; - -pub trait Resolver { - type Target; - async fn resolve(&self, input: &I) -> Result; -} diff --git a/identity_new_resolver/tests/compound.rs b/identity_new_resolver/tests/compound.rs deleted file mode 100644 index b60480dfcb..0000000000 --- a/identity_new_resolver/tests/compound.rs +++ /dev/null @@ -1,97 +0,0 @@ -use identity_new_resolver::{CompoundResolver, Resolver, Result, Error}; - -struct DidKey; -struct DidJwk; -struct DidWeb; -struct DidIota { - network: u32, -} - -struct CoreDoc; -struct IotaDoc; - -struct DidKeyResolver; -impl Resolver for DidKeyResolver { - type Target = CoreDoc; - async fn resolve(&self, _input: &DidKey) -> Result { - Ok(CoreDoc {}) - } -} -struct DidJwkResolver; -impl Resolver for DidJwkResolver { - type Target = CoreDoc; - async fn resolve(&self, _input: &DidJwk) -> Result { - Ok(CoreDoc {}) - } -} -struct DidWebResolver; -impl Resolver for DidWebResolver { - type Target = CoreDoc; - async fn resolve(&self, _input: &DidWeb) -> Result { - Ok(CoreDoc {}) - } -} - -struct Client { - network: u32, -} - -impl Resolver for Client { - type Target = IotaDoc; - async fn resolve(&self, input: &DidIota) -> Result { - if input.network == self.network { - Ok(IotaDoc {}) - } else { - Err(Error::Generic(anyhow::anyhow!("Invalid network"))) - } - } -} - -#[derive(CompoundResolver)] -struct SuperDidResolver { - #[resolver(DidKey -> CoreDoc)] - did_key: DidKeyResolver, - #[resolver(DidJwk -> CoreDoc)] - did_jwk: DidJwkResolver, - #[resolver(DidWeb -> CoreDoc)] - did_web: DidWebResolver, -} - -#[derive(CompoundResolver)] -struct IdentityClient { - #[resolver(DidKey -> CoreDoc, DidJwk -> CoreDoc, DidWeb -> CoreDoc)] - dids: SuperDidResolver, - #[resolver(DidIota -> IotaDoc if input.network == 0)] - iota: Client, - #[resolver(DidIota -> IotaDoc)] - shimmer: Client, -} - -#[tokio::test] -async fn test_compound_resolver_simple() { - let super_resolver = SuperDidResolver { - did_key: DidKeyResolver {}, - did_jwk: DidJwkResolver {}, - did_web: DidWebResolver {}, - }; - - assert!(super_resolver.resolve(&DidJwk {}).await.is_ok()); -} - -#[tokio::test] -async fn test_compound_resolver_conflicts() { - let super_resolver = SuperDidResolver { - did_key: DidKeyResolver {}, - did_jwk: DidJwkResolver {}, - did_web: DidWebResolver {}, - }; - let identity_client = IdentityClient { - dids: super_resolver, - iota: Client { network: 0}, - shimmer: Client {network: 1}, - }; - - assert!(identity_client.resolve(&DidJwk {}).await.is_ok()); - assert!(identity_client.resolve(&DidIota { network: 1}).await.is_ok()); - assert!(identity_client.resolve(&DidIota { network: 0}).await.is_ok()); -} diff --git a/identity_resolver/Cargo.toml b/identity_resolver/Cargo.toml index e6d93b03f0..d28ba767a2 100644 --- a/identity_resolver/Cargo.toml +++ b/identity_resolver/Cargo.toml @@ -4,42 +4,23 @@ version = "1.3.0" authors.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["iota", "did", "identity", "resolver", "resolution"] license.workspace = true -readme = "./README.md" repository.workspace = true rust-version.workspace = true -description = "DID Resolution utilities for the identity.rs library." [dependencies] -# This is currently necessary for the ResolutionHandler trait. This can be made an optional dependency if alternative ways of attaching handlers are introduced. -async-trait = { version = "0.1", default-features = false } -futures = { version = "0.3" } -identity_core = { version = "=1.3.0", path = "../identity_core", default-features = false } -identity_credential = { version = "=1.3.0", path = "../identity_credential", default-features = false, features = ["validator"] } -identity_did = { version = "=1.3.0", path = "../identity_did", default-features = false } -identity_document = { version = "=1.3.0", path = "../identity_document", default-features = false } -serde = { version = "1.0", default-features = false, features = ["std", "derive"] } -strum.workspace = true -thiserror = { version = "1.0", default-features = false } +anyhow = "1.0.86" +thiserror.workspace = true +identity_iota_core = { version = "=1.3.0", path = "../identity_iota_core", optional = true } +identity_did = { version = "=1.3.0", path = "../identity_did", optional = true } +iota-sdk = { version = "1.1.5", default-features = false, features = ["client"], optional = true } -[dependencies.identity_iota_core] -version = "=1.3.0" -path = "../identity_iota_core" -default-features = false -features = ["send-sync-client-ext", "iota-client"] -optional = true +[lints] +workspace = true [dev-dependencies] -identity_iota_core = { path = "../identity_iota_core", features = ["test"] } -iota-sdk = { version = "1.1.5" } -tokio = { version = "1.29.0", default-features = false, features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.38.0", features = ["macros", "rt"] } [features] -default = ["revocation-bitmap", "iota"] -revocation-bitmap = ["identity_credential/revocation-bitmap", "identity_iota_core?/revocation-bitmap"] -# Enables the IOTA integration for the resolver. -iota = ["dep:identity_iota_core"] - -[lints] -workspace = true +default = ["iota"] +iota = ["dep:iota-sdk", "dep:identity_iota_core", "dep:identity_did"] diff --git a/identity_resolver/README.md b/identity_resolver/README.md deleted file mode 100644 index 4ce84dce0e..0000000000 --- a/identity_resolver/README.md +++ /dev/null @@ -1,4 +0,0 @@ -IOTA Identity - Resolver -=== - -This crate provides a pluggable Resolver implementation that allows for abstracting over the resolution of different DID methods. diff --git a/identity_resolver/src/error.rs b/identity_resolver/src/error.rs index d72a78fd4a..a7e1ddfecf 100644 --- a/identity_resolver/src/error.rs +++ b/identity_resolver/src/error.rs @@ -1,74 +1,13 @@ -// Copyright 2020-2022 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -/// Alias for a `Result` with the error type [`Error`]. -pub type Result = core::result::Result; - -/// Error returned from the [Resolver's](crate::Resolver) methods. -/// -/// The [`Self::error_cause`](Self::error_cause()) method provides information about the cause of the error. -#[derive(Debug)] -pub struct Error { - error_cause: ErrorCause, -} - -impl Error { - pub(crate) fn new(cause: ErrorCause) -> Self { - Self { error_cause: cause } - } - - /// Returns the cause of the error. - pub fn error_cause(&self) -> &ErrorCause { - &self.error_cause - } - - /// Converts the error into [`ErrorCause`]. - pub fn into_error_cause(self) -> ErrorCause { - self.error_cause - } -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.error_cause) - } -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.error_cause.source() - } -} - -/// Error failure modes associated with the methods on the [Resolver's](crate::Resolver). -/// -/// NOTE: This is a "read only error" in the sense that it can only be constructed by the methods in this crate. -#[derive(Debug, thiserror::Error, strum::IntoStaticStr)] -#[non_exhaustive] -pub enum ErrorCause { - /// Caused by a failure to parse a DID string during DID resolution. - #[error("did resolution failed: could not parse the given did")] - #[non_exhaustive] - DIDParsingError { - /// The source of the parsing error. - source: Box, - }, - /// A handler attached to the [`Resolver`](crate::resolution::Resolver) attempted to resolve the DID, but the - /// resolution did not succeed. - #[error("did resolution failed: the attached handler failed")] - #[non_exhaustive] - HandlerError { - /// The source of the handler error. - source: Box, - }, - /// Caused by attempting to resolve a DID whose method does not have a corresponding handler attached to the - /// [`Resolver`](crate::resolution::Resolver). - #[error("did resolution failed: the DID method \"{method}\" is not supported by the resolver")] - UnsupportedMethodError { - /// The method that is unsupported. - method: String, - }, - /// No client attached to the specific network. - #[error("none of the attached clients support the network {0}")] - UnsupportedNetwork(String), +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Debug, Error)] +pub enum Error { + #[error("The requested item \"{0}\" was not found.")] + NotFound(String), + #[error("Failed to parse the provided input into a resolvable type: {0}")] + ParsingFailure(#[source] anyhow::Error), + #[error(transparent)] + Generic(#[from] anyhow::Error), } diff --git a/identity_resolver/src/iota.rs b/identity_resolver/src/iota.rs new file mode 100644 index 0000000000..533a1f46b8 --- /dev/null +++ b/identity_resolver/src/iota.rs @@ -0,0 +1,64 @@ +use super::Error; +use super::Resolver; +use super::Result; +use identity_did::CoreDID; +use identity_iota_core::Error as IdentityError; +use identity_iota_core::IotaDID; +use identity_iota_core::IotaDocument; +use identity_iota_core::IotaIdentityClientExt; +use iota_sdk::client::node_api::error::Error as IotaApiError; +use iota_sdk::client::Client; +use iota_sdk::client::Error as SdkError; + +impl Resolver for Client { + type Target = IotaDocument; + async fn resolve(&self, did: &IotaDID) -> Result { + self.resolve_did(did).await.map_err(|e| match e { + IdentityError::DIDResolutionError(SdkError::Node(IotaApiError::NotFound(_))) => Error::NotFound(did.to_string()), + e => Error::Generic(e.into()), + }) + } +} + +impl Resolver for Client { + type Target = IotaDocument; + async fn resolve(&self, did: &CoreDID) -> Result { + let iota_did = IotaDID::try_from(did.clone()).map_err(|e| Error::ParsingFailure(e.into()))?; + self.resolve(&iota_did).await + } +} + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::Context; + + async fn get_iota_client() -> anyhow::Result { + const API_ENDPOINT: &str = "https://api.stardust-mainnet.iotaledger.net"; + Client::builder() + .with_primary_node(API_ENDPOINT, None)? + .finish() + .await + .context("Failed to create client to iota mainnet") + } + + #[tokio::test] + async fn resolution_of_existing_doc_works() -> anyhow::Result<()> { + let client = get_iota_client().await?; + let did = "did:iota:0xf4d6f08f5a1b80dd578da7dc1b49c886d580acd4cf7d48119dfeb82b538ad88a".parse::()?; + + assert!(client.resolve(&did).await.is_ok()); + + Ok(()) + } + + #[tokio::test] + async fn resolution_of_non_existing_doc_fails_with_not_found() -> anyhow::Result<()> { + let client = get_iota_client().await?; + let did = "did:iota:0xf4d6f08f5a1b80ee578da7dc1b49c886d580acd4cf7d48119dfeb82b538ad88a".parse::()?; + + assert!(matches!(client.resolve(&did).await.unwrap_err(), Error::NotFound(_))); + + Ok(()) + } +} diff --git a/identity_resolver/src/lib.rs b/identity_resolver/src/lib.rs index b773741b09..d984f7e052 100644 --- a/identity_resolver/src/lib.rs +++ b/identity_resolver/src/lib.rs @@ -1,23 +1,8 @@ -// Copyright 2020-2022 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -#![forbid(unsafe_code)] -#![doc = include_str!("./../README.md")] -#![warn( - rust_2018_idioms, - unreachable_pub, - missing_docs, - rustdoc::missing_crate_level_docs, - rustdoc::broken_intra_doc_links, - rustdoc::private_intra_doc_links, - rustdoc::private_doc_tests, - clippy::missing_safety_doc -)] - mod error; -mod resolution; +#[cfg(feature = "iota")] +mod iota; +mod resolver; -pub use self::error::Error; -pub use self::error::ErrorCause; -pub use self::error::Result; -pub use resolution::*; +pub use error::Error; +pub use error::Result; +pub use resolver::Resolver; diff --git a/identity_resolver/src/resolution/commands.rs b/identity_resolver/src/resolution/commands.rs deleted file mode 100644 index 6dd186a841..0000000000 --- a/identity_resolver/src/resolution/commands.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2020-2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use core::future::Future; -use identity_did::DID; - -use crate::Error; -use crate::ErrorCause; -use crate::Result; -use std::pin::Pin; - -/// Internal trait used by the resolver to apply the command pattern. -/// -/// The resolver is generic over the type of command which enables -/// support for both multi-threaded and single threaded use cases. -pub trait Command<'a, T>: std::fmt::Debug + private::Sealed { - type Output: Future + 'a; - - fn apply(&self, input: &'a str) -> Self::Output; -} - -mod private { - use super::SendSyncCommand; - use super::SingleThreadedCommand; - pub trait Sealed {} - impl Sealed for SendSyncCommand {} - impl Sealed for SingleThreadedCommand {} -} - -impl std::fmt::Debug for SendSyncCommand { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("") - } -} - -impl std::fmt::Debug for SingleThreadedCommand { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("") - } -} - -/// Internal representation of a thread safe handler. -type SendSyncCallback = - Box Fn(&'r str) -> Pin> + 'r + Send>> + Send + Sync>; - -/// Wrapper around a thread safe callback. -pub struct SendSyncCommand { - fun: SendSyncCallback, -} - -impl<'a, DOC: 'static> Command<'a, Result> for SendSyncCommand { - type Output = Pin> + 'a + Send>>; - fn apply(&self, input: &'a str) -> Self::Output { - (self.fun)(input) - } -} - -impl SendSyncCommand { - /// Converts a handler represented as a closure to a command. - /// - /// This is achieved by first producing a callback represented as a dynamic asynchronous function pointer - /// which is invoked by the [Resolver](crate::Resolver) at a later point. - /// When the callback is invoked the `Resolver` will then pass a DID represented as a string slice which is then - /// converted to the DID type required by the handler and then the handler is called. - pub(super) fn new(handler: F) -> Self - where - D: DID + Send + for<'r> TryFrom<&'r str, Error = DIDERR> + 'static, - DOCUMENT: 'static + Into, - F: Fn(D) -> Fut + 'static + Clone + Send + Sync, - Fut: Future> + Send, - E: Into>, - DIDERR: Into>, - { - let fun: SendSyncCallback = Box::new(move |input: &str| { - let handler_clone: F = handler.clone(); - let did_parse_attempt = D::try_from(input) - .map_err(|error| ErrorCause::DIDParsingError { source: error.into() }) - .map_err(Error::new); - - Box::pin(async move { - let did: D = did_parse_attempt?; - handler_clone(did) - .await - .map(Into::into) - .map_err(|error| ErrorCause::HandlerError { source: error.into() }) - .map_err(Error::new) - }) - }); - - Self { fun } - } -} - -// =========================================================================== -// Single threaded commands -// =========================================================================== - -/// Internal representation of a single threaded handler. -pub(super) type SingleThreadedCallback = - Box Fn(&'r str) -> Pin> + 'r>>>; - -/// Wrapper around a single threaded callback. -pub struct SingleThreadedCommand { - fun: SingleThreadedCallback, -} -impl<'a, DOC: 'static> Command<'a, Result> for SingleThreadedCommand { - type Output = Pin> + 'a>>; - fn apply(&self, input: &'a str) -> Self::Output { - (self.fun)(input) - } -} - -impl SingleThreadedCommand { - /// Equivalent to [`SendSyncCommand::new`](SendSyncCommand::new()), but with less `Send` + `Sync` bounds. - pub(super) fn new(handler: F) -> Self - where - D: DID + for<'r> TryFrom<&'r str, Error = DIDERR> + 'static, - DOCUMENT: 'static + Into, - F: Fn(D) -> Fut + 'static + Clone, - Fut: Future>, - E: Into>, - DIDERR: Into>, - { - let fun: SingleThreadedCallback = Box::new(move |input: &str| { - let handler_clone: F = handler.clone(); - let did_parse_attempt = D::try_from(input) - .map_err(|error| ErrorCause::DIDParsingError { source: error.into() }) - .map_err(Error::new); - - Box::pin(async move { - let did: D = did_parse_attempt?; - handler_clone(did) - .await - .map(Into::into) - .map_err(|error| ErrorCause::HandlerError { source: error.into() }) - .map_err(Error::new) - }) - }); - - Self { fun } - } -} diff --git a/identity_resolver/src/resolution/mod.rs b/identity_resolver/src/resolution/mod.rs deleted file mode 100644 index 06a923d446..0000000000 --- a/identity_resolver/src/resolution/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2020-2022 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -mod commands; -mod resolver; -#[cfg(test)] -mod tests; - -use self::commands::SingleThreadedCommand; -use identity_document::document::CoreDocument; - -pub use resolver::Resolver; -/// Alias for a [`Resolver`] that is not [`Send`] + [`Sync`]. -pub type SingleThreadedResolver = Resolver>; diff --git a/identity_resolver/src/resolution/resolver.rs b/identity_resolver/src/resolution/resolver.rs deleted file mode 100644 index b8ceffbc7f..0000000000 --- a/identity_resolver/src/resolution/resolver.rs +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2020-2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use core::future::Future; -use futures::stream::FuturesUnordered; -use futures::TryStreamExt; -use identity_did::DID; -use std::collections::HashSet; - -use identity_document::document::CoreDocument; -use std::collections::HashMap; -use std::marker::PhantomData; - -use crate::Error; -use crate::ErrorCause; -use crate::Result; - -use super::commands::Command; -use super::commands::SendSyncCommand; -use super::commands::SingleThreadedCommand; - -/// Convenience type for resolving DID documents from different DID methods. -/// -/// # Configuration -/// -/// The resolver will only be able to resolve DID documents for methods it has been configured for. This is done by -/// attaching method specific handlers with [`Self::attach_handler`](Self::attach_handler()). -pub struct Resolver> -where - CMD: for<'r> Command<'r, Result>, -{ - command_map: HashMap, - _required: PhantomData, -} - -impl Resolver -where - M: for<'r> Command<'r, Result>, -{ - /// Constructs a new [`Resolver`]. - /// - /// # Example - /// - /// Construct a `Resolver` that resolves DID documents of type - /// [`CoreDocument`](::identity_document::document::CoreDocument). - /// ``` - /// # use identity_resolver::Resolver; - /// # use identity_document::document::CoreDocument; - /// - /// let mut resolver = Resolver::::new(); - /// // Now attach some handlers whose output can be converted to a `CoreDocument`. - /// ``` - pub fn new() -> Self { - Self { - command_map: HashMap::new(), - _required: PhantomData::, - } - } - - /// Fetches the DID Document of the given DID. - /// - /// # Errors - /// - /// Errors if the resolver has not been configured to handle the method corresponding to the given DID or the - /// resolution process itself fails. - /// - /// ## Example - /// - /// ``` - /// # use identity_resolver::Resolver; - /// # use identity_did::CoreDID; - /// # use identity_document::document::CoreDocument; - /// - /// async fn configure_and_resolve( - /// did: CoreDID, - /// ) -> std::result::Result> { - /// let resolver: Resolver = configure_resolver(Resolver::new()); - /// let resolved_doc: CoreDocument = resolver.resolve(&did).await?; - /// Ok(resolved_doc) - /// } - /// - /// fn configure_resolver(mut resolver: Resolver) -> Resolver { - /// resolver.attach_handler("foo".to_owned(), resolve_foo); - /// // Attach handlers for other DID methods we are interested in. - /// resolver - /// } - /// - /// async fn resolve_foo(did: CoreDID) -> std::result::Result { - /// todo!() - /// } - /// ``` - pub async fn resolve(&self, did: &D) -> Result { - let method: &str = did.method(); - let delegate: &M = self - .command_map - .get(method) - .ok_or_else(|| ErrorCause::UnsupportedMethodError { - method: method.to_owned(), - }) - .map_err(Error::new)?; - - delegate.apply(did.as_str()).await - } - - /// Concurrently fetches the DID Documents of the multiple given DIDs. - /// - /// # Errors - /// * If the resolver has not been configured to handle the method of any of the given DIDs. - /// * If the resolution process of any DID fails. - /// - /// ## Note - /// * If `dids` contains duplicates, these will be resolved only once. - pub async fn resolve_multiple(&self, dids: &[D]) -> Result> { - let futures = FuturesUnordered::new(); - - // Create set to remove duplicates to avoid unnecessary resolution. - let dids_set: HashSet = dids.iter().cloned().collect(); - for did in dids_set { - futures.push(async move { - let doc = self.resolve(&did).await; - doc.map(|doc| (did, doc)) - }); - } - - let documents: HashMap = futures.try_collect().await?; - - Ok(documents) - } -} - -impl Resolver> { - /// Attach a new handler responsible for resolving DIDs of the given DID method. - /// - /// The `handler` is expected to be a closure taking an owned DID and asynchronously returning a DID Document - /// which can be converted to the type this [`Resolver`] is parametrized over. The `handler` is required to be - /// [`Clone`], [`Send`], [`Sync`] and `'static` hence all captured variables must satisfy these bounds. In this regard - /// the `move` keyword and (possibly) wrapping values in an [`Arc`](std::sync::Arc) may come in handy (see the example - /// below). - /// - /// NOTE: If there already exists a handler for this method then it will be replaced with the new handler. - /// In the case where one would like to have a "backup handler" for the same DID method, one can achieve this with - /// composition. - /// - /// # Example - /// ``` - /// # use identity_resolver::Resolver; - /// # use identity_did::CoreDID; - /// # use identity_document::document::CoreDocument; - /// - /// // A client that can resolve DIDs of our invented "foo" method. - /// struct Client; - /// - /// impl Client { - /// // Resolves some of the DIDs we are interested in. - /// async fn resolve(&self, _did: &CoreDID) -> std::result::Result { - /// todo!() - /// } - /// } - /// - /// // This way we can essentially produce (cheap) clones of our client. - /// let client = std::sync::Arc::new(Client {}); - /// - /// // Get a clone we can move into a handler. - /// let client_clone = client.clone(); - /// - /// // Construct a resolver that resolves documents of type `CoreDocument`. - /// let mut resolver = Resolver::::new(); - /// - /// // Now we want to attach a handler that uses the client to resolve DIDs whose method is "foo". - /// resolver.attach_handler("foo".to_owned(), move |did: CoreDID| { - /// // We want to resolve the did asynchronously, but since we do not know when it will be awaited we - /// // let the future take ownership of the client by moving a clone into the asynchronous block. - /// let future_client = client_clone.clone(); - /// async move { future_client.resolve(&did).await } - /// }); - /// ``` - pub fn attach_handler(&mut self, method: String, handler: F) - where - D: DID + Send + for<'r> TryFrom<&'r str, Error = DIDERR> + 'static, - DOCUMENT: 'static + Into, - F: Fn(D) -> Fut + 'static + Clone + Send + Sync, - Fut: Future> + Send, - E: Into>, - DIDERR: Into>, - { - let command = SendSyncCommand::new(handler); - self.command_map.insert(method, command); - } -} - -impl Resolver> { - /// Attach a new handler responsible for resolving DIDs of the given DID method. - /// - /// The `handler` is expected to be a closure taking an owned DID and asynchronously returning a DID Document - /// which can be converted to the type this [`Resolver`] is parametrized over. The `handler` is required to be - /// [`Clone`] and `'static` hence all captured variables must satisfy these bounds. In this regard the - /// `move` keyword and (possibly) wrapping values in an [`std::rc::Rc`] may come in handy (see the example below). - /// - /// NOTE: If there already exists a handler for this method then it will be replaced with the new handler. - /// In the case where one would like to have a "backup handler" for the same DID method, one can achieve this with - /// composition. - /// - /// # Example - /// ``` - /// # use identity_resolver::SingleThreadedResolver; - /// # use identity_did::CoreDID; - /// # use identity_document::document::CoreDocument; - /// - /// // A client that can resolve DIDs of our invented "foo" method. - /// struct Client; - /// - /// impl Client { - /// // Resolves some of the DIDs we are interested in. - /// async fn resolve(&self, _did: &CoreDID) -> std::result::Result { - /// todo!() - /// } - /// } - /// - /// // This way we can essentially produce (cheap) clones of our client. - /// let client = std::rc::Rc::new(Client {}); - /// - /// // Get a clone we can move into a handler. - /// let client_clone = client.clone(); - /// - /// // Construct a resolver that resolves documents of type `CoreDocument`. - /// let mut resolver = SingleThreadedResolver::::new(); - /// - /// // Now we want to attach a handler that uses the client to resolve DIDs whose method is "foo". - /// resolver.attach_handler("foo".to_owned(), move |did: CoreDID| { - /// // We want to resolve the did asynchronously, but since we do not know when it will be awaited we - /// // let the future take ownership of the client by moving a clone into the asynchronous block. - /// let future_client = client_clone.clone(); - /// async move { future_client.resolve(&did).await } - /// }); - /// ``` - pub fn attach_handler(&mut self, method: String, handler: F) - where - D: DID + for<'r> TryFrom<&'r str, Error = DIDERR> + 'static, - DOCUMENT: 'static + Into, - F: Fn(D) -> Fut + 'static + Clone, - Fut: Future>, - E: Into>, - DIDERR: Into>, - { - let command = SingleThreadedCommand::new(handler); - self.command_map.insert(method, command); - } -} - -#[cfg(feature = "iota")] -mod iota_handler { - use crate::ErrorCause; - - use super::Resolver; - use identity_document::document::CoreDocument; - use identity_iota_core::IotaDID; - use identity_iota_core::IotaDocument; - use identity_iota_core::IotaIdentityClientExt; - use std::collections::HashMap; - use std::sync::Arc; - - impl Resolver - where - DOC: From + AsRef + 'static, - { - /// Convenience method for attaching a new handler responsible for resolving IOTA DIDs. - /// - /// See also [`attach_handler`](Self::attach_handler). - pub fn attach_iota_handler(&mut self, client: CLI) - where - CLI: IotaIdentityClientExt + Send + Sync + 'static, - { - let arc_client: Arc = Arc::new(client); - - let handler = move |did: IotaDID| { - let future_client = arc_client.clone(); - async move { future_client.resolve_did(&did).await } - }; - - self.attach_handler(IotaDID::METHOD.to_owned(), handler); - } - - /// Convenience method for attaching multiple handlers responsible for resolving IOTA DIDs - /// on multiple networks. - /// - /// - /// # Arguments - /// - /// * `clients` - A collection of tuples where each tuple contains the name of the network name and its - /// corresponding client. - /// - /// # Examples - /// - /// ```ignore - /// // Assume `smr_client` and `iota_client` are instances IOTA clients `iota_sdk::client::Client`. - /// attach_multiple_iota_handlers(vec![("smr", smr_client), ("iota", iota_client)]); - /// ``` - /// - /// # See Also - /// - [`attach_handler`](Self::attach_handler). - /// - /// # Note - /// - /// - Using `attach_iota_handler` or `attach_handler` for the IOTA method would override all - /// previously added clients. - /// - This function does not validate the provided configuration. Ensure that the provided - /// network name corresponds with the client, possibly by using `client.network_name()`. - pub fn attach_multiple_iota_handlers(&mut self, clients: I) - where - CLI: IotaIdentityClientExt + Send + Sync + 'static, - I: IntoIterator, - { - let arc_clients = Arc::new(clients.into_iter().collect::>()); - - let handler = move |did: IotaDID| { - let future_client = arc_clients.clone(); - async move { - let did_network = did.network_str(); - let client: &CLI = - future_client - .get(did_network) - .ok_or(crate::Error::new(ErrorCause::UnsupportedNetwork( - did_network.to_string(), - )))?; - client - .resolve_did(&did) - .await - .map_err(|err| crate::Error::new(ErrorCause::HandlerError { source: Box::new(err) })) - } - }; - - self.attach_handler(IotaDID::METHOD.to_owned(), handler); - } - } -} - -impl Default for Resolver -where - CMD: for<'r> Command<'r, Result>, - DOC: AsRef, -{ - fn default() -> Self { - Self::new() - } -} - -impl std::fmt::Debug for Resolver -where - CMD: for<'r> Command<'r, Result>, - DOC: AsRef, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Resolver") - .field("command_map", &self.command_map) - .finish() - } -} - -#[cfg(test)] -mod tests { - use identity_iota_core::block::output::AliasId; - use identity_iota_core::block::output::AliasOutput; - use identity_iota_core::block::output::OutputId; - use identity_iota_core::block::protocol::ProtocolParameters; - use identity_iota_core::IotaDID; - use identity_iota_core::IotaDocument; - use identity_iota_core::IotaIdentityClient; - use identity_iota_core::IotaIdentityClientExt; - - use super::*; - - struct DummyClient(IotaDocument); - - #[async_trait::async_trait] - impl IotaIdentityClient for DummyClient { - async fn get_alias_output(&self, _id: AliasId) -> identity_iota_core::Result<(OutputId, AliasOutput)> { - unreachable!() - } - async fn get_protocol_parameters(&self) -> identity_iota_core::Result { - unreachable!() - } - } - - #[async_trait::async_trait] - impl IotaIdentityClientExt for DummyClient { - async fn resolve_did(&self, did: &IotaDID) -> identity_iota_core::Result { - if self.0.id().as_str() == did.as_str() { - Ok(self.0.clone()) - } else { - Err(identity_iota_core::Error::DIDResolutionError( - iota_sdk::client::error::Error::NoOutput(did.to_string()), - )) - } - } - } - - #[tokio::test] - async fn test_multiple_handlers() { - let did1 = - IotaDID::parse("did:iota:smr:0x0101010101010101010101010101010101010101010101010101010101010101").unwrap(); - let document = IotaDocument::new_with_id(did1.clone()); - let dummy_smr_client = DummyClient(document); - - let did2 = IotaDID::parse("did:iota:0x0101010101010101010101010101010101010101010101010101010101010101").unwrap(); - let document = IotaDocument::new_with_id(did2.clone()); - let dummy_iota_client = DummyClient(document); - - let mut resolver = Resolver::::new(); - resolver.attach_multiple_iota_handlers(vec![("iota", dummy_iota_client), ("smr", dummy_smr_client)]); - - let doc = resolver.resolve(&did1).await.unwrap(); - assert_eq!(doc.id(), &did1); - - let doc = resolver.resolve(&did2).await.unwrap(); - assert_eq!(doc.id(), &did2); - } -} diff --git a/identity_resolver/src/resolution/tests/mod.rs b/identity_resolver/src/resolution/tests/mod.rs deleted file mode 100644 index 082def4c42..0000000000 --- a/identity_resolver/src/resolution/tests/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020-2022 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use super::resolver::*; -mod resolution; -mod send_sync; diff --git a/identity_resolver/src/resolution/tests/resolution.rs b/identity_resolver/src/resolution/tests/resolution.rs deleted file mode 100644 index ce68fd4b9b..0000000000 --- a/identity_resolver/src/resolution/tests/resolution.rs +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2020-2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use std::collections::HashMap; -use std::error::Error; -use std::fmt::Debug; -use std::str::FromStr; - -use identity_did::BaseDIDUrl; -use identity_did::CoreDID; -use identity_did::Error as DIDError; -use identity_did::DID; -use identity_document::document::CoreDocument; -use identity_document::document::DocumentBuilder; - -use crate::Error as ResolverError; -use crate::ErrorCause; -use crate::Resolver; - -/// A very simple handler -async fn mock_handler(did: CoreDID) -> std::result::Result { - Ok(core_document(did)) -} - -/// Create a [`CoreDocument`] -fn core_document(did: CoreDID) -> CoreDocument { - DocumentBuilder::default().id(did).build().unwrap() -} - -/// A custom document type -#[derive(Debug, Clone)] -struct FooDocument(CoreDocument); -impl AsRef for FooDocument { - fn as_ref(&self) -> &CoreDocument { - &self.0 - } -} -impl From for FooDocument { - fn from(value: CoreDocument) -> Self { - Self(value) - } -} - -// =========================================================================== -// Missing handler for DID method failure tests -// =========================================================================== -#[tokio::test] -async fn missing_handler_errors() { - let method_name: String = "foo".to_owned(); - let bad_did: CoreDID = CoreDID::parse(format!("did:{method_name}:1234")).unwrap(); - let other_method: String = "bar".to_owned(); - let good_did: CoreDID = CoreDID::parse(format!("did:{other_method}:1234")).unwrap(); - - // configure `resolver` to resolve the "bar" method - let mut resolver_foo: Resolver = Resolver::new(); - let mut resolver_core: Resolver = Resolver::new(); - resolver_foo.attach_handler(other_method.clone(), mock_handler); - resolver_core.attach_handler(other_method, mock_handler); - - let err: ResolverError = resolver_foo.resolve(&bad_did).await.unwrap_err(); - let ErrorCause::UnsupportedMethodError { method } = err.into_error_cause() else { - unreachable!() - }; - assert_eq!(method_name, method); - - let err: ResolverError = resolver_core.resolve(&bad_did).await.unwrap_err(); - let ErrorCause::UnsupportedMethodError { method } = err.into_error_cause() else { - unreachable!() - }; - assert_eq!(method_name, method); - - assert!(resolver_foo.resolve(&good_did).await.is_ok()); - assert!(resolver_core.resolve(&good_did).await.is_ok()); - - let both_dids = [good_did, bad_did]; - let err: ResolverError = resolver_foo.resolve_multiple(&both_dids).await.unwrap_err(); - let ErrorCause::UnsupportedMethodError { method } = err.into_error_cause() else { - unreachable!() - }; - assert_eq!(method_name, method); - - let err: ResolverError = resolver_core.resolve_multiple(&both_dids).await.unwrap_err(); - let ErrorCause::UnsupportedMethodError { method } = err.into_error_cause() else { - unreachable!() - }; - assert_eq!(method_name, method); -} - -// =========================================================================== -// DID Parsing failure tests -// =========================================================================== - -// Implement the DID trait for a new type -#[derive(Hash, Ord, PartialOrd, Eq, PartialEq, Clone)] -struct FooDID(CoreDID); - -impl FooDID { - const METHOD_ID_LENGTH: usize = 5; - - fn try_from_core(did: CoreDID) -> std::result::Result { - Some(did) - .filter(|did| did.method() == "foo" && did.method_id().len() == FooDID::METHOD_ID_LENGTH) - .map(Self) - .ok_or(DIDError::InvalidMethodName) - } -} - -impl AsRef for FooDID { - fn as_ref(&self) -> &CoreDID { - &self.0 - } -} - -impl From for String { - fn from(did: FooDID) -> Self { - String::from(did.0) - } -} -impl From for CoreDID { - fn from(value: FooDID) -> Self { - value.0 - } -} - -impl TryFrom for FooDID { - type Error = DIDError; - fn try_from(value: CoreDID) -> Result { - Self::try_from_core(value) - } -} - -impl FromStr for FooDID { - type Err = DIDError; - fn from_str(s: &str) -> Result { - CoreDID::from_str(s).and_then(Self::try_from_core) - } -} - -impl TryFrom for FooDID { - type Error = DIDError; - fn try_from(value: BaseDIDUrl) -> Result { - CoreDID::try_from(value).and_then(Self::try_from_core) - } -} - -impl<'a> TryFrom<&'a str> for FooDID { - type Error = DIDError; - fn try_from(value: &'a str) -> Result { - CoreDID::try_from(value).and_then(Self::try_from_core) - } -} - -#[tokio::test] -async fn resolve_unparsable() { - let mut resolver_foo: Resolver = Resolver::new(); - let mut resolver_core: Resolver = Resolver::new(); - - // register a handler that wants `did` to be of type `FooDID`. - async fn handler(did: FooDID) -> std::result::Result { - mock_handler(did.as_ref().clone()).await - } - - resolver_foo.attach_handler("foo".to_owned(), handler); - resolver_core.attach_handler("foo".to_owned(), handler); - - let bad_did: CoreDID = CoreDID::parse("did:foo:1234").unwrap(); - // ensure that the DID we created does not satisfy the requirements of the "foo" method - assert!(bad_did.method_id().len() < FooDID::METHOD_ID_LENGTH); - - let good_did: FooDID = FooDID::try_from("did:foo:12345").unwrap(); - - let error_matcher = |err: ErrorCause| { - assert!(matches!( - err - .source() - .unwrap() - .downcast_ref::() - .unwrap_or_else(|| panic!("{:?}", &err)), - &DIDError::InvalidMethodName - )); - - match err { - ErrorCause::DIDParsingError { .. } => {} - _ => unreachable!(), - } - }; - - let err_cause: ErrorCause = resolver_foo.resolve(&bad_did).await.unwrap_err().into_error_cause(); - error_matcher(err_cause); - - let err_cause: ErrorCause = resolver_core.resolve(&bad_did).await.unwrap_err().into_error_cause(); - error_matcher(err_cause); - - assert!(resolver_foo.resolve(&good_did).await.is_ok()); - assert!(resolver_core.resolve(&good_did).await.is_ok()); -} - -// =========================================================================== -// Failing handler tests -// =========================================================================== - -#[tokio::test] -async fn handler_failure() { - #[derive(Debug, thiserror::Error)] - #[error("resolution failed")] - struct ResolutionError; - async fn failing_handler(_did: CoreDID) -> std::result::Result { - Err(ResolutionError) - } - - let mut resolver_foo: Resolver = Resolver::new(); - let mut resolver_core: Resolver = Resolver::new(); - resolver_foo.attach_handler("foo".to_owned(), failing_handler); - resolver_core.attach_handler("foo".to_owned(), failing_handler); - - let bad_did: CoreDID = CoreDID::parse("did:foo:1234").unwrap(); - let good_did: CoreDID = CoreDID::parse("did:bar:1234").unwrap(); - resolver_foo.attach_handler(good_did.method().to_owned(), mock_handler); - resolver_core.attach_handler(good_did.method().to_owned(), mock_handler); - - // to avoid boiler plate - let error_matcher = |err: ErrorCause| { - assert!(err.source().unwrap().downcast_ref::().is_some()); - match err { - ErrorCause::HandlerError { .. } => {} - _ => unreachable!(), - } - }; - - let err_cause: ErrorCause = resolver_foo.resolve(&bad_did).await.unwrap_err().into_error_cause(); - error_matcher(err_cause); - - let err_cause: ErrorCause = resolver_core.resolve(&bad_did).await.unwrap_err().into_error_cause(); - error_matcher(err_cause); - - assert!(resolver_foo.resolve(&good_did).await.is_ok()); - assert!(resolver_core.resolve(&good_did).await.is_ok()); -} - -// =========================================================================== -// Resolve Multiple. -// =========================================================================== - -#[tokio::test] -async fn resolve_multiple() { - let method_name: String = "foo".to_owned(); - - let did_1: CoreDID = CoreDID::parse(format!("did:{method_name}:1111")).unwrap(); - let did_2: CoreDID = CoreDID::parse(format!("did:{method_name}:2222")).unwrap(); - let did_3: CoreDID = CoreDID::parse(format!("did:{method_name}:3333")).unwrap(); - let did_1_clone: CoreDID = CoreDID::parse(format!("did:{method_name}:1111")).unwrap(); - - let mut resolver: Resolver = Resolver::new(); - resolver.attach_handler(method_name, mock_handler); - - // Resolve with duplicate `did_3`. - let resolved_dids: HashMap = resolver - .resolve_multiple(&[ - did_1.clone(), - did_2.clone(), - did_3.clone(), - did_1_clone.clone(), - did_3.clone(), - ]) - .await - .unwrap(); - - assert_eq!(resolved_dids.len(), 3); - assert_eq!(resolved_dids.get(&did_1).unwrap().id(), &did_1); - assert_eq!(resolved_dids.get(&did_2).unwrap().id(), &did_2); - assert_eq!(resolved_dids.get(&did_3).unwrap().id(), &did_3); - assert_eq!(resolved_dids.get(&did_1_clone).unwrap().id(), &did_1_clone); - - let dids: &[CoreDID] = &[]; - let resolved_dids: HashMap = resolver.resolve_multiple(dids).await.unwrap(); - assert_eq!(resolved_dids.len(), 0); - - let resolved_dids: HashMap = resolver.resolve_multiple(&[did_1.clone()]).await.unwrap(); - assert_eq!(resolved_dids.len(), 1); - assert_eq!(resolved_dids.get(&did_1).unwrap().id(), &did_1); -} diff --git a/identity_resolver/src/resolution/tests/send_sync.rs b/identity_resolver/src/resolution/tests/send_sync.rs deleted file mode 100644 index 99d8ef0fe4..0000000000 --- a/identity_resolver/src/resolution/tests/send_sync.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020-2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use super::*; - -use identity_did::DID; -use identity_document::document::CoreDocument; - -fn is_send(_t: T) {} -fn is_send_sync(_t: T) {} - -#[allow(dead_code)] -fn default_resolver_is_send_sync + Send + Sync + 'static>() { - let resolver = Resolver::::new(); - is_send_sync(resolver); -} - -#[allow(dead_code)] -fn resolver_methods_give_send_futures(did: D) -where - DOC: AsRef + Send + Sync + 'static, - D: DID + Send + Sync + 'static, -{ - let resolver = Resolver::::new(); - is_send(resolver.resolve(&did)); -} diff --git a/identity_resolver/src/resolver.rs b/identity_resolver/src/resolver.rs new file mode 100644 index 0000000000..daf600239e --- /dev/null +++ b/identity_resolver/src/resolver.rs @@ -0,0 +1,17 @@ +#![allow(async_fn_in_trait)] + +use crate::Result; + +pub trait Resolver { + type Target; + async fn resolve(&self, input: &I) -> Result; + async fn resolve_multiple(&self, inputs: impl AsRef<[I]>) -> Result> { + let mut results = Vec::::with_capacity(inputs.as_ref().len()); + for input in inputs.as_ref() { + let result = self.resolve(input).await?; + results.push(result); + } + + Ok(results) + } +} From 2af02da02414e8f4e5894f806e7f28d49ee92d4b Mon Sep 17 00:00:00 2001 From: Yasir Date: Fri, 21 Jun 2024 10:20:17 +0300 Subject: [PATCH 09/22] chore(grpc): enhance domain grpc services (#1381) --- bindings/grpc/proto/domain_linkage.proto | 79 ++++--- bindings/grpc/rustfmt.toml | 8 + bindings/grpc/src/services/domain_linkage.rs | 219 +++++++++++------- bindings/grpc/tests/api/domain_linkage.rs | 84 ++++--- bindings/grpc/tests/api/utils.rs | 5 +- .../.well-known/did-configuration.json | 2 +- examples/1_advanced/6_domain_linkage.rs | 4 +- 7 files changed, 253 insertions(+), 148 deletions(-) create mode 100644 bindings/grpc/rustfmt.toml diff --git a/bindings/grpc/proto/domain_linkage.proto b/bindings/grpc/proto/domain_linkage.proto index f2fe3426df..5edee5e18a 100644 --- a/bindings/grpc/proto/domain_linkage.proto +++ b/bindings/grpc/proto/domain_linkage.proto @@ -4,6 +4,52 @@ syntax = "proto3"; package domain_linkage; +message ValidateDidResponse { + string did = 1; + message Domains { + message ValidDomain { + string url = 1; + string credential = 2; + string service_id = 3; + } + + repeated ValidDomain valid = 1; + + message InvalidDomain { + string url = 1; + optional string credential = 2; + string service_id = 3; + string error = 4; + } + + repeated InvalidDomain invalid = 2; + } + Domains domains = 2; +} + +message ValidateDomainResponse { + string domain = 1; + message LinkedDids { + message ValidDid { + string did = 1; + string credential = 2; + string service_id = 3; + } + + repeated ValidDid valid = 1; + + message InvalidDid { + optional string did = 1; + optional string credential = 2; + optional string service_id = 3; + string error = 4; + } + + repeated InvalidDid invalid = 2; + } + LinkedDids linked_dids = 2; +} + message ValidateDomainRequest { // domain to validate string domain = 1; @@ -16,27 +62,6 @@ message ValidateDomainAgainstDidConfigurationRequest { string did_configuration = 2; } -message LinkedDidValidationStatus { - // validation succeeded or not, `error` property is added for `false` cases - bool valid = 1; - // credential from `linked_dids` as compact JWT domain linkage credential if it could be retrieved - optional string document = 2; - // an error message, that occurred when validated, omitted if valid - optional string error = 3; -} - -message ValidateDomainResponse { - // list of JWT domain linkage credential, uses the same order as the `did-configuration.json` file for domain - repeated LinkedDidValidationStatus linked_dids = 1; -} - -message LinkedDidEndpointValidationStatus { - // id of service endpoint entry - string id = 1; - // list of JWT domain linkage credential, uses the same order as the `did-configuration.json` file for domain - repeated LinkedDidValidationStatus service_endpoint = 2; -} - message ValidateDidRequest { // DID to validate string did = 1; @@ -49,15 +74,13 @@ message ValidateDidAgainstDidConfigurationsRequest { repeated ValidateDomainAgainstDidConfigurationRequest did_configurations = 2; } -message ValidateDidResponse { - // mapping of service entries from DID with validation status for endpoint URLs - repeated LinkedDidEndpointValidationStatus service = 1; -} - service DomainLinkage { rpc validate_domain(ValidateDomainRequest) returns (ValidateDomainResponse); - rpc validate_domain_against_did_configuration(ValidateDomainAgainstDidConfigurationRequest) returns (ValidateDomainResponse); + rpc validate_domain_against_did_configuration( + ValidateDomainAgainstDidConfigurationRequest) + returns (ValidateDomainResponse); rpc validate_did(ValidateDidRequest) returns (ValidateDidResponse); - rpc validate_did_against_did_configurations(ValidateDidAgainstDidConfigurationsRequest) returns (ValidateDidResponse); + rpc validate_did_against_did_configurations( + ValidateDidAgainstDidConfigurationsRequest) returns (ValidateDidResponse); } \ No newline at end of file diff --git a/bindings/grpc/rustfmt.toml b/bindings/grpc/rustfmt.toml new file mode 100644 index 0000000000..c0842c2114 --- /dev/null +++ b/bindings/grpc/rustfmt.toml @@ -0,0 +1,8 @@ +comment_width = 120 +format_code_in_doc_comments = true +max_width = 120 +normalize_comments = false +normalize_doc_attributes = false +tab_spaces = 2 +wrap_comments = true +imports_granularity = "Item" diff --git a/bindings/grpc/src/services/domain_linkage.rs b/bindings/grpc/src/services/domain_linkage.rs index 3c3935a413..bb8b214982 100644 --- a/bindings/grpc/src/services/domain_linkage.rs +++ b/bindings/grpc/src/services/domain_linkage.rs @@ -4,18 +4,20 @@ use std::collections::HashMap; use std::error::Error; -use domain_linkage::domain_linkage_server::DomainLinkage; -use domain_linkage::domain_linkage_server::DomainLinkageServer; -use domain_linkage::LinkedDidEndpointValidationStatus; -use domain_linkage::LinkedDidValidationStatus; -use domain_linkage::ValidateDidAgainstDidConfigurationsRequest; -use domain_linkage::ValidateDidRequest; -use domain_linkage::ValidateDidResponse; -use domain_linkage::ValidateDomainAgainstDidConfigurationRequest; -use domain_linkage::ValidateDomainRequest; -use domain_linkage::ValidateDomainResponse; -use futures::stream::FuturesOrdered; -use futures::TryStreamExt; +use _domain_linkage::domain_linkage_server::DomainLinkage; +use _domain_linkage::domain_linkage_server::DomainLinkageServer; +use _domain_linkage::validate_did_response::domains::InvalidDomain; +use _domain_linkage::validate_did_response::domains::ValidDomain; +use _domain_linkage::validate_did_response::Domains; +use _domain_linkage::validate_domain_response::linked_dids::InvalidDid; +use _domain_linkage::validate_domain_response::linked_dids::ValidDid; +use _domain_linkage::validate_domain_response::LinkedDids; +use _domain_linkage::ValidateDidAgainstDidConfigurationsRequest; +use _domain_linkage::ValidateDidRequest; +use _domain_linkage::ValidateDidResponse; +use _domain_linkage::ValidateDomainAgainstDidConfigurationRequest; +use _domain_linkage::ValidateDomainRequest; +use _domain_linkage::ValidateDomainResponse; use identity_eddsa_verifier::EdDSAJwsVerifier; use identity_iota::core::FromJson; use identity_iota::core::Url; @@ -36,8 +38,7 @@ use tonic::Response; use tonic::Status; use url::Origin; -#[allow(clippy::module_inception)] -mod domain_linkage { +mod _domain_linkage { tonic::include_proto!("domain_linkage"); } @@ -90,11 +91,15 @@ impl DomainValidationConfig { } /// Builds a validation status for a failed validation from an `Error`. -fn get_validation_failed_status(message: &str, err: &impl Error) -> LinkedDidValidationStatus { - LinkedDidValidationStatus { - valid: false, - document: None, - error: Some(format!("{}; {}", message, &err.to_string())), +fn get_linked_did_validation_failed_status(message: &str, err: &impl Error) -> LinkedDids { + LinkedDids { + valid: vec![], + invalid: vec![InvalidDid { + service_id: None, + credential: None, + did: None, + error: format!("{}: {}", message, err), + }], } } @@ -121,8 +126,7 @@ impl DomainLinkageService { &self, did: &IotaDID, did_configurations: Option>, - ) -> Result, DomainLinkageError> { - // fetch DID document for given DID + ) -> Result { let did_document = self .resolver .resolve(did) @@ -144,36 +148,66 @@ impl DomainLinkageService { None => HashMap::new(), }; - // check validation for all services and endpoints in them - let mut service_futures = FuturesOrdered::new(); + let mut futures = vec![]; + for service in services { - let service_id: CoreDID = did.clone().into(); + let service_id = service.id().to_string(); let domains: Vec = service.domains().into(); - let local_config_map = config_map.clone(); - service_futures.push_back(async move { - let mut domain_futures = FuturesOrdered::new(); - for domain in domains { - let config = local_config_map.get(&domain.origin()).map(|value| value.to_owned()); - domain_futures.push_back(self.validate_domains_with_optional_configuration( - domain.clone(), - Some(did.clone().into()), - config, - )); + for domain in domains { + let config = config_map.get(&domain.origin()).cloned(); + let service_id_clone = service_id.clone(); + futures.push({ + let domain = domain.clone(); + async move { + let result = self + .validate_domains_with_optional_configuration(&domain, Some(did.clone().into()), config) + .await; + + (service_id_clone, domain, result) + } + }); + } + } + + let results = futures::future::join_all(futures).await; + + let mut valid_domains = vec![]; + let mut invalid_domains = vec![]; + + for (service_id, domain, result) in results { + match result { + Ok(status) => { + status.valid.iter().for_each(|valid| { + valid_domains.push(ValidDomain { + service_id: service_id.to_string(), + url: domain.to_string(), + credential: valid.credential.clone(), + }); + }); + status.invalid.iter().for_each(|invalid| { + invalid_domains.push(InvalidDomain { + service_id: service_id.to_string(), + credential: invalid.credential.clone(), + url: domain.to_string(), + error: invalid.error.clone(), + }); + }); } - domain_futures - .try_collect::>>() - .await - .map(|value| LinkedDidEndpointValidationStatus { - id: service_id.to_string(), - service_endpoint: value.into_iter().flatten().collect(), - }) - }); + Err(err) => { + invalid_domains.push(InvalidDomain { + service_id: service_id.to_string(), + credential: None, + url: domain.to_string(), + error: err.to_string(), + }); + } + } } - let endpoint_validation_status = service_futures - .try_collect::>() - .await?; - Ok(endpoint_validation_status) + Ok(Domains { + valid: valid_domains, + invalid: invalid_domains, + }) } /// Validates domain linkage for given origin. @@ -186,10 +220,10 @@ impl DomainLinkageService { /// origin async fn validate_domains_with_optional_configuration( &self, - domain: Url, + domain: &Url, did: Option, config: Option, - ) -> Result, DomainLinkageError> { + ) -> Result { // get domain linkage config let domain_linkage_configuration: DomainLinkageConfiguration = if let Some(config_value) = config { config_value @@ -197,10 +231,10 @@ impl DomainLinkageService { match DomainLinkageConfiguration::fetch_configuration(domain.clone()).await { Ok(value) => value, Err(err) => { - return Ok(vec![get_validation_failed_status( + return Ok(get_linked_did_validation_failed_status( "could not get domain linkage config", &err, - )]); + )); } } }; @@ -212,10 +246,10 @@ impl DomainLinkageService { match domain_linkage_configuration.issuers() { Ok(value) => value, Err(err) => { - return Ok(vec![get_validation_failed_status( + return Ok(get_linked_did_validation_failed_status( "could not get issuers from domain linkage config credential", &err, - )]); + )); } } }; @@ -224,40 +258,51 @@ impl DomainLinkageService { let resolved = match self.resolver.resolve_multiple(&linked_dids).await { Ok(value) => value, Err(err) => { - return Ok(vec![get_validation_failed_status( + return Ok(get_linked_did_validation_failed_status( "could not resolve linked DIDs from domain linkage config", &err, - )]); + )); } }; + let mut valid_dids = vec![]; + let mut invalid_dids = vec![]; + // check linked DIDs separately - let errors: Vec> = resolved - .values() - .map(|issuer_did_doc| { - JwtDomainLinkageValidator::with_signature_verifier(EdDSAJwsVerifier::default()) + domain_linkage_configuration + .linked_dids() + .iter() + .zip(resolved.values()) + .for_each(|(credential, issuer_did_doc)| { + let id = issuer_did_doc.id().to_string(); + + if let Err(err) = JwtDomainLinkageValidator::with_signature_verifier(EdDSAJwsVerifier::default()) .validate_linkage( &issuer_did_doc, &domain_linkage_configuration, - &domain.clone(), + &domain, &JwtCredentialValidationOptions::default(), ) - .err() - .map(|err| err.to_string()) - }) - .collect(); + { + invalid_dids.push(InvalidDid { + service_id: Some(id), + credential: Some(credential.as_str().to_string()), + did: Some(issuer_did_doc.to_string()), + error: err.to_string(), + }); + } else { + valid_dids.push(ValidDid { + service_id: id, + did: issuer_did_doc.to_string(), + credential: credential.as_str().to_string(), + }); + } + }); - // collect resolved documents and their validation status into array following the order of `linked_dids` - let status_infos = domain_linkage_configuration - .linked_dids() - .iter() - .zip(errors.iter()) - .map(|(credential, error)| LinkedDidValidationStatus { - valid: error.is_none(), - document: Some(credential.as_str().to_string()), - error: error.clone(), - }) - .collect(); + let status_infos = LinkedDids { + valid: valid_dids, + invalid: invalid_dids, + }; Ok(status_infos) } @@ -282,12 +327,13 @@ impl DomainLinkage for DomainLinkageService { Url::parse(&request_data.domain).map_err(|err| DomainLinkageError::DomainParsing(err.to_string()))?; // get validation status for all issuer dids - let status_infos = self - .validate_domains_with_optional_configuration(domain, None, None) + let linked_dids = self + .validate_domains_with_optional_configuration(&domain, None, None) .await?; Ok(Response::new(ValidateDomainResponse { - linked_dids: status_infos, + domain: domain.to_string(), + linked_dids: Some(linked_dids), })) } @@ -306,18 +352,19 @@ impl DomainLinkage for DomainLinkageService { // parse given domain let domain: Url = Url::parse(&request_data.domain).map_err(|err| DomainLinkageError::DomainParsing(err.to_string()))?; + // parse config let config = DomainLinkageConfiguration::from_json(&request_data.did_configuration.to_string()).map_err(|err| { DomainLinkageError::DidConfigurationParsing(format!("could not parse given DID configuration; {}", &err)) })?; - // get validation status for all issuer dids - let status_infos = self - .validate_domains_with_optional_configuration(domain, None, Some(config)) + let linked_dids = self + .validate_domains_with_optional_configuration(&domain, None, Some(config)) .await?; Ok(Response::new(ValidateDomainResponse { - linked_dids: status_infos, + domain: request_data.domain.clone(), + linked_dids: Some(linked_dids), })) } @@ -332,10 +379,11 @@ impl DomainLinkage for DomainLinkageService { // fetch DID document for given DID let did: IotaDID = IotaDID::parse(req.into_inner().did).map_err(|e| Status::internal(e.to_string()))?; - let endpoint_validation_status = self.validate_did_with_optional_configurations(&did, None).await?; + let domains = self.validate_did_with_optional_configurations(&did, None).await?; let response = ValidateDidResponse { - service: endpoint_validation_status, + did: did.to_string(), + domains: Some(domains), }; Ok(Response::new(response)) @@ -360,12 +408,13 @@ impl DomainLinkage for DomainLinkageService { .map(DomainValidationConfig::try_parse) .collect::, DomainLinkageError>>()?; - let endpoint_validation_status = self + let domains = self .validate_did_with_optional_configurations(&did, Some(did_configurations)) .await?; let response = ValidateDidResponse { - service: endpoint_validation_status, + did: did.to_string(), + domains: Some(domains), }; Ok(Response::new(response)) diff --git a/bindings/grpc/tests/api/domain_linkage.rs b/bindings/grpc/tests/api/domain_linkage.rs index a79b732d58..4870c74a8d 100644 --- a/bindings/grpc/tests/api/domain_linkage.rs +++ b/bindings/grpc/tests/api/domain_linkage.rs @@ -1,7 +1,14 @@ // Copyright 2020-2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use _credentials::validate_did_response::Domains; +use _credentials::validate_domain_response::LinkedDids; + +use crate::domain_linkage::_credentials::validate_did_response::domains::InvalidDomain; +use crate::domain_linkage::_credentials::validate_did_response::domains::ValidDomain; +use crate::domain_linkage::_credentials::validate_domain_response::linked_dids::ValidDid; use identity_iota::core::Duration; +use identity_iota::core::FromJson; use identity_iota::core::Object; use identity_iota::core::OrderedSet; use identity_iota::core::Timestamp; @@ -13,13 +20,13 @@ use identity_iota::credential::Jwt; use identity_iota::credential::LinkedDomainService; use identity_iota::did::DIDUrl; use identity_iota::did::DID; +use identity_iota::iota::IotaDocument; use identity_storage::JwkDocumentExt; use identity_storage::JwsSignatureOptions; use identity_stronghold::StrongholdStorage; use crate::domain_linkage::_credentials::domain_linkage_client::DomainLinkageClient; -use crate::domain_linkage::_credentials::LinkedDidEndpointValidationStatus; -use crate::domain_linkage::_credentials::LinkedDidValidationStatus; + use crate::domain_linkage::_credentials::ValidateDidAgainstDidConfigurationsRequest; use crate::domain_linkage::_credentials::ValidateDidResponse; use crate::domain_linkage::_credentials::ValidateDomainAgainstDidConfigurationRequest; @@ -33,7 +40,7 @@ mod _credentials { } /// Prepares basically the same test setup as in test `examples/1_advanced/6_domain_linkage.rs`. -async fn prepare_test() -> anyhow::Result<(TestServer, Url, String, Jwt)> { +async fn prepare_test() -> anyhow::Result<(TestServer, Url, Url, String, Jwt)> { let stronghold = StrongholdStorage::new(make_stronghold()); let server = TestServer::new_with_stronghold(stronghold.clone()).await; let api_client = server.client(); @@ -42,9 +49,9 @@ async fn prepare_test() -> anyhow::Result<(TestServer, Url, String, Jwt)> { issuer.create_did(api_client).await?; let did = issuer .document() - .ok_or_else(|| anyhow::anyhow!("no DID document for issuer"))? - .id(); - let did_string = did.to_string(); + .ok_or_else(|| anyhow::anyhow!("no DID document for issuer"))?; + + let did = did.id().clone(); // ===================================================== // Create Linked Domain service // ===================================================== @@ -70,6 +77,8 @@ async fn prepare_test() -> anyhow::Result<(TestServer, Url, String, Jwt)> { .document() .ok_or_else(|| anyhow::anyhow!("no DID document for issuer"))?; + let did_string = updated_did_document.to_string(); + println!("DID document with linked domain service: {updated_did_document:#}"); // ===================================================== @@ -101,12 +110,12 @@ async fn prepare_test() -> anyhow::Result<(TestServer, Url, String, Jwt)> { ) .await?; - Ok((server, domain_1, did_string, jwt)) + Ok((server, domain_1, domain_2, did_string, jwt)) } #[tokio::test] async fn can_validate_domain() -> anyhow::Result<()> { - let (server, linked_domain, _, jwt) = prepare_test().await?; + let (server, linked_domain, _, did, jwt) = prepare_test().await?; let configuration_resource: DomainLinkageConfiguration = DomainLinkageConfiguration::new(vec![jwt.clone()]); let mut grpc_client = DomainLinkageClient::connect(server.endpoint()).await?; @@ -116,15 +125,20 @@ async fn can_validate_domain() -> anyhow::Result<()> { did_configuration: configuration_resource.to_string(), }) .await?; + let did_id = IotaDocument::from_json(&did)?.id().to_string(); assert_eq!( response.into_inner(), ValidateDomainResponse { - linked_dids: vec![LinkedDidValidationStatus { - valid: true, - document: Some(jwt.as_str().to_string()), - error: None, - }], + linked_dids: Some(LinkedDids { + invalid: vec![], + valid: vec![ValidDid { + service_id: did_id, + did: did.to_string().clone(), + credential: jwt.as_str().to_string(), + }] + }), + domain: linked_domain.to_string(), } ); @@ -133,13 +147,14 @@ async fn can_validate_domain() -> anyhow::Result<()> { #[tokio::test] async fn can_validate_did() -> anyhow::Result<()> { - let (server, linked_domain, issuer_did, jwt) = prepare_test().await?; + let (server, linked_domain, domain2, issuer_did, jwt) = prepare_test().await?; let configuration_resource: DomainLinkageConfiguration = DomainLinkageConfiguration::new(vec![jwt.clone()]); let mut grpc_client = DomainLinkageClient::connect(server.endpoint()).await?; + let did_id = IotaDocument::from_json(&issuer_did)?.id().to_string(); let response = grpc_client .validate_did_against_did_configurations(ValidateDidAgainstDidConfigurationsRequest { - did: issuer_did.clone(), + did: did_id.clone(), did_configurations: vec![ValidateDomainAgainstDidConfigurationRequest { domain: linked_domain.to_string(), did_configuration: configuration_resource.to_string(), @@ -147,26 +162,31 @@ async fn can_validate_did() -> anyhow::Result<()> { }) .await?; + let service_id = format!("{}#domain-linkage", did_id); + + let valid_domain = ValidDomain { + service_id: service_id.clone(), + url: linked_domain.to_string(), + credential: jwt.as_str().to_string(), + }; + + let error = format!("could not get domain linkage config: domain linkage error: error sending request for url ({}.well-known/did-configuration.json): error trying to connect: dns error: failed to lookup address information: nodename nor servname provided, or not known", domain2.to_string()); + + let invalid_domain = InvalidDomain { + service_id: service_id.clone(), + credential: None, + url: domain2.to_string(), + error, + }; + assert_eq!( response.into_inner(), ValidateDidResponse { - service: vec![ - LinkedDidEndpointValidationStatus { - id: issuer_did, - service_endpoint: vec![ - LinkedDidValidationStatus { - valid: true, - document: Some(jwt.as_str().to_string()), - error: None, - }, - LinkedDidValidationStatus { - valid: false, - document: None, - error: Some("could not get domain linkage config; domain linkage error: error sending request for url (https://bar.example.com/.well-known/did-configuration.json): error trying to connect: dns error: failed to lookup address information: nodename nor servname provided, or not known".to_string()), - } - ], - } - ] + did: did_id, + domains: Some(Domains { + invalid: vec![invalid_domain], + valid: vec![valid_domain], + }), } ); diff --git a/bindings/grpc/tests/api/utils.rs b/bindings/grpc/tests/api/utils.rs index 9c863bf3de..9b320bd154 100644 --- a/bindings/grpc/tests/api/utils.rs +++ b/bindings/grpc/tests/api/utils.rs @@ -6,6 +6,7 @@ use _utils::DataSigningRequest; use identity_iota::verification::jws::JwsAlgorithm; use identity_storage::JwkStorage; use identity_storage::KeyType; +use identity_stronghold::StrongholdKeyType; use identity_stronghold::StrongholdStorage; use crate::helpers::make_stronghold; @@ -28,7 +29,9 @@ async fn raw_data_signing_works() -> anyhow::Result<()> { .key_id; let expected_signature = { - let public_key_jwk = stronghold.get_public_key(&key_id).await?; + let public_key_jwk = stronghold + .get_public_key_with_type(&key_id, StrongholdKeyType::Ed25519) + .await?; stronghold.sign(&key_id, SAMPLE_SIGNING_DATA, &public_key_jwk).await? }; diff --git a/bindings/grpc/tooling/domain-linkage-test-server/.well-known/did-configuration.json b/bindings/grpc/tooling/domain-linkage-test-server/.well-known/did-configuration.json index 802f453e3e..579b9ee575 100644 --- a/bindings/grpc/tooling/domain-linkage-test-server/.well-known/did-configuration.json +++ b/bindings/grpc/tooling/domain-linkage-test-server/.well-known/did-configuration.json @@ -3,4 +3,4 @@ "linked_dids": [ "add your domain linkage credential here" ] -} \ No newline at end of file +} diff --git a/examples/1_advanced/6_domain_linkage.rs b/examples/1_advanced/6_domain_linkage.rs index 6e7a629110..03d0472a37 100644 --- a/examples/1_advanced/6_domain_linkage.rs +++ b/examples/1_advanced/6_domain_linkage.rs @@ -49,12 +49,14 @@ async fn main() -> anyhow::Result<()> { .with_primary_node(API_ENDPOINT, None)? .finish() .await?; + let stronghold_path = random_stronghold_path(); + println!("Using stronghold path: {stronghold_path:?}"); // Create a new secret manager backed by a Stronghold. let mut secret_manager: SecretManager = SecretManager::Stronghold( StrongholdSecretManager::builder() .password(Password::from("secure_password".to_owned())) - .build(random_stronghold_path())?, + .build(stronghold_path)?, ); // Create a DID for the entity that will issue the Domain Linkage Credential. From bb13b38f1a77c06be7b73142af79703c435124b2 Mon Sep 17 00:00:00 2001 From: wulfraem Date: Thu, 27 Jun 2024 18:08:04 +0200 Subject: [PATCH 10/22] Make base64 encoding target independent in `KeyIdMemStore` in wasm bindings (#1386) --- bindings/wasm/lib/key_id_storage.ts | 4 ++-- bindings/wasm/package-lock.json | 14 ++++++++++++++ bindings/wasm/package.json | 1 + .../src/key_id_storage/key_id_storage_error.rs | 2 +- identity_storage/src/storage/error.rs | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/bindings/wasm/lib/key_id_storage.ts b/bindings/wasm/lib/key_id_storage.ts index 1ceeb9eae2..0ed977a5c5 100644 --- a/bindings/wasm/lib/key_id_storage.ts +++ b/bindings/wasm/lib/key_id_storage.ts @@ -1,3 +1,4 @@ +import { encode as base64Encode } from "base64-arraybuffer"; import type { KeyIdStorage, MethodDigest } from "~identity_wasm"; export class KeyIdMemStore implements KeyIdStorage { @@ -48,6 +49,5 @@ export class KeyIdMemStore implements KeyIdStorage { */ function methodDigestToString(methodDigest: MethodDigest): string { let arrayBuffer = methodDigest.pack().buffer; - let buffer = Buffer.from(arrayBuffer); - return buffer.toString("base64"); + return base64Encode(arrayBuffer); } diff --git a/bindings/wasm/package-lock.json b/bindings/wasm/package-lock.json index ebdd96ae40..80c99f5bea 100644 --- a/bindings/wasm/package-lock.json +++ b/bindings/wasm/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@noble/ed25519": "^1.7.3", "@types/node-fetch": "^2.6.2", + "base64-arraybuffer": "^1.0.2", "node-fetch": "^2.6.7" }, "devDependencies": { @@ -1116,6 +1117,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -7721,6 +7730,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json index 9faa31edc8..2aef8087ba 100644 --- a/bindings/wasm/package.json +++ b/bindings/wasm/package.json @@ -75,6 +75,7 @@ "dependencies": { "@noble/ed25519": "^1.7.3", "@types/node-fetch": "^2.6.2", + "base64-arraybuffer": "^1.0.2", "node-fetch": "^2.6.7" }, "peerDependencies": { diff --git a/identity_storage/src/key_id_storage/key_id_storage_error.rs b/identity_storage/src/key_id_storage/key_id_storage_error.rs index 046b6cc5f8..d628585692 100644 --- a/identity_storage/src/key_id_storage/key_id_storage_error.rs +++ b/identity_storage/src/key_id_storage/key_id_storage_error.rs @@ -52,7 +52,7 @@ impl KeyIdStorageErrorKind { Self::KeyIdNotFound => "key id not found in storage", Self::Unavailable => "key id storage unavailable", Self::Unauthenticated => "authentication with the key id storage failed", - Self::Unspecified => "key storage operation failed", + Self::Unspecified => "key id storage operation failed", Self::RetryableIOFailure => "key id storage was unsuccessful because of an I/O failure", Self::SerializationError => "(de)serialization error", } diff --git a/identity_storage/src/storage/error.rs b/identity_storage/src/storage/error.rs index a5d8d11185..51af20ead0 100644 --- a/identity_storage/src/storage/error.rs +++ b/identity_storage/src/storage/error.rs @@ -13,7 +13,7 @@ pub enum JwkStorageDocumentError { #[error("storage operation failed: key storage error")] KeyStorageError(KeyStorageError), /// Caused by a failure in the key id storage. - #[error("storage operation failed: key id storage error")] + #[error("storage operation failed: key id storage error: {0}")] KeyIdStorageError(KeyIdStorageError), /// Caused by an attempt to add a method with a fragment that already exists. #[error("could not add method: the fragment already exists")] From b2906253d18bf6dc3da5c4e8d036fe6776d54b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Ha=C3=9F?= Date: Fri, 28 Jun 2024 12:28:32 +0200 Subject: [PATCH 11/22] Hotfix wasm-v1.3.1 (#1389) --- bindings/wasm/CHANGELOG.md | 13 +++++++++++-- bindings/wasm/Cargo.toml | 2 +- bindings/wasm/package-lock.json | 4 ++-- bindings/wasm/package.json | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/bindings/wasm/CHANGELOG.md b/bindings/wasm/CHANGELOG.md index 67378276e3..cd49c3874f 100644 --- a/bindings/wasm/CHANGELOG.md +++ b/bindings/wasm/CHANGELOG.md @@ -1,14 +1,23 @@ # Changelog +## [wasm-v1.3.1](https://github.com/iotaledger/identity.rs/tree/wasm-v1.3.1) (2024-06-27) + +[Full Changelog](https://github.com/iotaledger/identity.rs/compare/wasm-v1.3.0...wasm-v1.3.1) + +### Patch + +- Make base64 encoding target independent in `KeyIdMemStore` in wasm bindings [\#1386](https://github.com/iotaledger/identity.rs/pull/1386) + ## [wasm-v1.3.0](https://github.com/iotaledger/identity.rs/tree/wasm-v1.3.0) (2024-05-28) [Full Changelog](https://github.com/iotaledger/identity.rs/compare/wasm-v1.2.0...wasm-v1.3.0) ### Added -- Add ZK BBS+-based selectively disclosable credentials (JPT) [\#1355](https://github.com/iotaledger/identity.rs/pull/1355) -- Add EcDSA verifier [\#1353](https://github.com/iotaledger/identity.rs/pull/1353) + +- Add ZK BBS+-based selectively disclosable credentials \(JPT\) [\#1355](https://github.com/iotaledger/identity.rs/pull/1355) ### Patch + - Support for specification-compliant verification method type `JsonWebKey2020` [\#1367](https://github.com/iotaledger/identity.rs/pull/1367) ## [wasm-v1.2.0](https://github.com/iotaledger/identity.rs/tree/wasm-v1.2.0) (2024-03-27) diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 8648bd3f4e..9e264b3b6d 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identity_wasm" -version = "1.3.0" +version = "1.3.1" authors = ["IOTA Stiftung"] edition = "2021" homepage = "https://www.iota.org" diff --git a/bindings/wasm/package-lock.json b/bindings/wasm/package-lock.json index 80c99f5bea..6963519895 100644 --- a/bindings/wasm/package-lock.json +++ b/bindings/wasm/package-lock.json @@ -1,12 +1,12 @@ { "name": "@iota/identity-wasm", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@iota/identity-wasm", - "version": "1.3.0", + "version": "1.3.1", "license": "Apache-2.0", "dependencies": { "@noble/ed25519": "^1.7.3", diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json index 2aef8087ba..f542343d62 100644 --- a/bindings/wasm/package.json +++ b/bindings/wasm/package.json @@ -1,6 +1,6 @@ { "name": "@iota/identity-wasm", - "version": "1.3.0", + "version": "1.3.1", "description": "WASM bindings for IOTA Identity - A Self Sovereign Identity Framework implementing the DID and VC standards from W3C. To be used in Javascript/Typescript", "repository": { "type": "git", From c7040624cdf751aad562af3c6af3203c75ae993b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Ha=C3=9F?= Date: Fri, 12 Jul 2024 09:49:43 +0200 Subject: [PATCH 12/22] run cypress in docker (#1390) --- .github/workflows/build-and-test-grpc.yml | 2 +- .github/workflows/build-and-test.yml | 98 +- bindings/wasm/.dockerignore | 2 + bindings/wasm/cypress.config.ts | 12 + bindings/wasm/cypress/Dockerfile | 11 + bindings/wasm/package-lock.json | 1262 ++++++--------------- bindings/wasm/package.json | 14 +- 7 files changed, 469 insertions(+), 932 deletions(-) create mode 100644 bindings/wasm/.dockerignore create mode 100644 bindings/wasm/cypress/Dockerfile diff --git a/.github/workflows/build-and-test-grpc.yml b/.github/workflows/build-and-test-grpc.yml index 80311728c8..2a561bd952 100644 --- a/.github/workflows/build-and-test-grpc.yml +++ b/.github/workflows/build-and-test-grpc.yml @@ -38,4 +38,4 @@ jobs: context: . file: bindings/grpc/Dockerfile push: false - labels: iotaledger/identity-grpc:latest \ No newline at end of file + tags: iotaledger/identity-grpc:latest \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 206c534962..553774bb46 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -204,9 +204,105 @@ jobs: uses: './.github/actions/iota-sandbox/setup' - name: Run Wasm examples - run: npm run test:examples + run: npm run test:readme && npm run test:node working-directory: bindings/wasm - name: Tear down iota sandbox if: always() uses: './.github/actions/iota-sandbox/tear-down' + + test-wasm-firefox: + needs: build-wasm + if: ${{ needs.check-for-run-condition.outputs.should-run == 'true' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + include: + - os: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v1 + with: + node-version: 16.x + + - name: Install JS dependencies + run: npm ci + working-directory: bindings/wasm + + - name: Download bindings/wasm artifacts + uses: actions/download-artifact@v2 + with: + name: identity-wasm-bindings-build + path: bindings/wasm + + - name: Start iota sandbox + uses: './.github/actions/iota-sandbox/setup' + + - name: Build Docker image + uses: docker/build-push-action@v6.2.0 + with: + context: bindings/wasm/ + file: bindings/wasm/cypress/Dockerfile + push: false + tags: cypress-test:latest + load: true + + - name: Run cypress + run: docker run --network host cypress-test test:browser:firefox + + - name: Tear down iota sandbox + if: always() + uses: './.github/actions/iota-sandbox/tear-down' + + test-wasm-chrome: + needs: build-wasm + if: ${{ needs.check-for-run-condition.outputs.should-run == 'true' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + include: + - os: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v1 + with: + node-version: 16.x + + - name: Install JS dependencies + run: npm ci + working-directory: bindings/wasm + + - name: Download bindings/wasm artifacts + uses: actions/download-artifact@v2 + with: + name: identity-wasm-bindings-build + path: bindings/wasm + + - name: Start iota sandbox + uses: './.github/actions/iota-sandbox/setup' + + - name: Build Docker image + uses: docker/build-push-action@v6.2.0 + with: + context: bindings/wasm/ + file: bindings/wasm/cypress/Dockerfile + push: false + tags: cypress-test:latest + load: true + + - name: Run cypress + run: docker run --network host cypress-test test:browser:parallel:chrome + + - name: Tear down iota sandbox + if: always() + uses: './.github/actions/iota-sandbox/tear-down' diff --git a/bindings/wasm/.dockerignore b/bindings/wasm/.dockerignore new file mode 100644 index 0000000000..2c085d1d2f --- /dev/null +++ b/bindings/wasm/.dockerignore @@ -0,0 +1,2 @@ +node_modules +target diff --git a/bindings/wasm/cypress.config.ts b/bindings/wasm/cypress.config.ts index 1ad8692bba..f7cb0a6a1a 100644 --- a/bindings/wasm/cypress.config.ts +++ b/bindings/wasm/cypress.config.ts @@ -10,5 +10,17 @@ export default defineConfig({ }, e2e: { supportFile: false, + // Fix to make subtle crypto work in cypress firefox + // https://github.com/cypress-io/cypress/issues/18217 + setupNodeEvents(on, config) { + on("before:browser:launch", (browser, launchOptions) => { + if (browser.family === "firefox") { + launchOptions.preferences[ + "network.proxy.testing_localhost_is_secure_when_hijacked" + ] = true; + } + return launchOptions; + }); + }, }, }); diff --git a/bindings/wasm/cypress/Dockerfile b/bindings/wasm/cypress/Dockerfile new file mode 100644 index 0000000000..5ea3f7433b --- /dev/null +++ b/bindings/wasm/cypress/Dockerfile @@ -0,0 +1,11 @@ +FROM cypress/browsers:latest + +COPY ./ /e2e + +WORKDIR /e2e + +RUN npm ci + +RUN npm run build:examples:web + +ENTRYPOINT [ "npm", "run" ] \ No newline at end of file diff --git a/bindings/wasm/package-lock.json b/bindings/wasm/package-lock.json index 6963519895..37e102a1ce 100644 --- a/bindings/wasm/package-lock.json +++ b/bindings/wasm/package-lock.json @@ -18,10 +18,9 @@ "@transmute/did-key-ed25519": "0.3.0-unstable.9", "@types/mocha": "^9.1.0", "big-integer": "^1.6.51", - "concurrently": "^7.6.0", "copy-webpack-plugin": "^7.0.0", - "cypress": "^10.11.0", - "cypress-parallel": "^0.9.1", + "cypress": "^13.12.0", + "cypress-parallel": "^0.14.0", "dprint": "^0.33.0", "fs-extra": "^10.1.0", "jsdoc-to-markdown": "^7.1.1", @@ -57,7 +56,6 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, - "optional": true, "engines": { "node": ">=0.1.90" } @@ -75,9 +73,9 @@ } }, "node_modules/@cypress/request": { - "version": "2.88.10", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", - "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", @@ -93,9 +91,9 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.5.2", + "qs": "6.10.4", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", + "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" }, @@ -615,9 +613,9 @@ "dev": true }, "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "dev": true }, "node_modules/@types/unist": { @@ -627,9 +625,9 @@ "dev": true }, "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "optional": true, "dependencies": { @@ -1096,9 +1094,9 @@ } }, "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", "dev": true }, "node_modules/bail": { @@ -1313,9 +1311,9 @@ } }, "node_modules/cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", "dev": true, "engines": { "node": ">=6" @@ -1325,7 +1323,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "peer": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -1481,10 +1478,19 @@ } }, "node_modules/ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", - "dev": true + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, "node_modules/class-transformer": { "version": "0.5.1", @@ -1601,20 +1607,11 @@ "dev": true }, "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1715,9 +1712,9 @@ } }, "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, "engines": { "node": ">= 6" @@ -1747,33 +1744,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, "node_modules/config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", @@ -1845,30 +1815,29 @@ } }, "node_modules/cypress": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.11.0.tgz", - "integrity": "sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.12.0.tgz", + "integrity": "sha512-udzS2JilmI9ApO/UuqurEwOvThclin5ntz7K0BtnHBs+tg2Bl9QShLISXpSEMDv/u8b6mqdoAdyKeZiSqKWL8g==", "dev": true, "hasInstallScript": true, "dependencies": { - "@cypress/request": "^2.88.10", + "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", - "buffer": "^5.6.0", + "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", "cli-cursor": "^3.1.0", "cli-table3": "~0.6.1", - "commander": "^5.1.0", + "commander": "^6.2.1", "common-tags": "^1.8.0", "dayjs": "^1.10.4", - "debug": "^4.3.2", + "debug": "^4.3.4", "enquirer": "^2.3.6", "eventemitter2": "6.4.7", "execa": "4.1.0", @@ -1877,18 +1846,19 @@ "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", - "is-ci": "^3.0.0", + "is-ci": "^3.0.1", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", "lodash": "^4.17.21", "log-symbols": "^4.0.0", - "minimist": "^1.2.6", + "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", - "semver": "^7.3.2", + "semver": "^7.5.3", "supports-color": "^8.1.1", "tmp": "~0.2.1", "untildify": "^4.0.0", @@ -1898,18 +1868,18 @@ "cypress": "bin/cypress" }, "engines": { - "node": ">=12.0.0" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, "node_modules/cypress-multi-reporters": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.1.tgz", - "integrity": "sha512-FPeC0xWF1N6Myrwc2m7KC0xxlrtG8+x4hlsPFBDRWP8u/veR2x90pGaH3BuJfweV7xoQ4Zo85Qjhu3fgZGrBQQ==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.4.tgz", + "integrity": "sha512-3xU2t6pZjZy/ORHaCvci5OT1DAboS4UuMMM8NBAizeb2C9qmHt+cgAjXgurazkwkPRdO7ccK39M5ZaPCju0r6A==", "dev": true, "peer": true, "dependencies": { - "debug": "^4.1.1", - "lodash": "^4.17.15" + "debug": "^4.3.4", + "lodash": "^4.17.21" }, "engines": { "node": ">=6.0.0" @@ -1919,19 +1889,19 @@ } }, "node_modules/cypress-parallel": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.9.1.tgz", - "integrity": "sha512-7VSfFr8HEEN6zkgo6SkG7pPoHK7VakFhEH1jbM4+Ire/I+O2jNzyd1bRUA+O3V2DIMow64ECDJKf13YHBon+BQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.14.0.tgz", + "integrity": "sha512-Lsh28G70vxjL0cjR820BdaVQHnGc17Vvb+tYmjbRPmfC+XEzwvUzhcaD0E1zCztBSYhw+b1/1JLmW4Y0qE/EDA==", "dev": true, "dependencies": { + "@colors/colors": "^1.5.0", "cli-table3": "^0.6.0", - "colors": "^1.4.0", "cross-spawn": "^7.0.3", "fs-extra": "^10.0.0", "glob-escape": "^0.0.2", "is-npm": "^5.0.0", "lodash.camelcase": "^4.3.0", - "mocha": "^8.2.1", + "mocha": "~9.2.0", "yargs": "15.3.1" }, "bin": { @@ -1941,15 +1911,6 @@ "cypress-multi-reporters": "^1.5.0" } }, - "node_modules/cypress-parallel/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cypress-parallel/node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1959,42 +1920,15 @@ "node": ">=6" } }, - "node_modules/cypress-parallel/node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/cypress-parallel/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "node_modules/cypress-parallel/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, "node_modules/cypress-parallel/node_modules/decamelize": { @@ -2006,48 +1940,17 @@ "node": ">=0.10.0" } }, - "node_modules/cypress-parallel/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress-parallel/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "node_modules/cypress-parallel/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cypress-parallel/node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node": ">=8" } }, "node_modules/cypress-parallel/node_modules/locate-path": { @@ -2062,110 +1965,6 @@ "node": ">=8" } }, - "node_modules/cypress-parallel/node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress-parallel/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cypress-parallel/node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/cypress-parallel/node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/cypress-parallel/node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress-parallel/node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/cypress-parallel/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2193,24 +1992,6 @@ "node": ">=8" } }, - "node_modules/cypress-parallel/node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/cypress-parallel/node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", - "dev": true - }, "node_modules/cypress-parallel/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -2225,6 +2006,12 @@ "node": ">=8" } }, + "node_modules/cypress-parallel/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "node_modules/cypress-parallel/node_modules/yargs": { "version": "15.3.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", @@ -2247,37 +2034,7 @@ "node": ">=8" } }, - "node_modules/cypress-parallel/node_modules/yargs/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/cypress-parallel/node_modules/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress-parallel/node_modules/yargs/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/cypress-parallel/node_modules/yargs/node_modules/yargs-parser": { + "node_modules/cypress-parallel/node_modules/yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", @@ -2290,12 +2047,6 @@ "node": ">=6" } }, - "node_modules/cypress/node_modules/@types/node": { - "version": "14.18.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.29.tgz", - "integrity": "sha512-LhF+9fbIX4iPzhsRLpK5H7iPdvW8L4IwGciXQIOEcuF62+9nw/VQVsOViAOOGxY3OlOKGLFv0sWwJXdwQeTn6A==", - "dev": true - }, "node_modules/cypress/node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -2332,23 +2083,10 @@ "node": ">= 6" } }, - "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "dev": true, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/dayjs": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", - "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==", + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", "dev": true }, "node_modules/debug": { @@ -2538,12 +2276,13 @@ } }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -2981,8 +2720,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "peer": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/get-caller-file": { "version": "2.0.5", @@ -2997,7 +2735,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "peer": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -3090,9 +2827,9 @@ "peer": true }, "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, "dependencies": { "ini": "2.0.0" @@ -3164,7 +2901,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "peer": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -3185,7 +2921,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3197,7 +2932,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -4601,10 +4335,13 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { "version": "3.3.4", @@ -4903,7 +4640,6 @@ "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5089,6 +4825,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", @@ -5121,14 +4866,26 @@ } }, "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5319,6 +5076,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "node_modules/requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", @@ -5352,26 +5115,11 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5528,17 +5276,10 @@ "node": ">=8" } }, - "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "peer": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -5627,16 +5368,10 @@ "source-map": "^0.6.0" } }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true - }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", @@ -5944,10 +5679,13 @@ "peer": true }, "node_modules/throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/through": { "version": "2.3.8", @@ -5956,15 +5694,12 @@ "dev": true }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/to-regex-range": { @@ -5980,16 +5715,27 @@ } }, "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "node": ">=0.8" + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/tr46": { @@ -5997,15 +5743,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/trough": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", @@ -6376,7 +6113,17 @@ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "punycode": "^2.1.0" + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, "node_modules/uuid": { @@ -6581,63 +6328,11 @@ } }, "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6715,24 +6410,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", @@ -6766,15 +6443,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -6818,8 +6486,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true + "dev": true }, "@cspotcode/source-map-support": { "version": "0.8.1", @@ -6831,9 +6498,9 @@ } }, "@cypress/request": { - "version": "2.88.10", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", - "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -6849,9 +6516,9 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.5.2", + "qs": "6.10.4", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", + "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" }, @@ -7315,9 +6982,9 @@ "dev": true }, "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "dev": true }, "@types/unist": { @@ -7327,9 +6994,9 @@ "dev": true }, "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "optional": true, "requires": { @@ -7713,9 +7380,9 @@ "dev": true }, "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", "dev": true }, "bail": { @@ -7860,16 +7527,15 @@ } }, "cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", "dev": true }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "peer": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -7972,9 +7638,9 @@ "peer": true }, "ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true }, "class-transformer": { @@ -8066,15 +7732,9 @@ "dev": true }, "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "combined-stream": { @@ -8159,9 +7819,9 @@ } }, "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true }, "common-sequence": { @@ -8182,23 +7842,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" - } - }, "config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", @@ -8256,29 +7899,28 @@ } }, "cypress": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.11.0.tgz", - "integrity": "sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.12.0.tgz", + "integrity": "sha512-udzS2JilmI9ApO/UuqurEwOvThclin5ntz7K0BtnHBs+tg2Bl9QShLISXpSEMDv/u8b6mqdoAdyKeZiSqKWL8g==", "dev": true, "requires": { - "@cypress/request": "^2.88.10", + "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", - "buffer": "^5.6.0", + "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", "cli-cursor": "^3.1.0", "cli-table3": "~0.6.1", - "commander": "^5.1.0", + "commander": "^6.2.1", "common-tags": "^1.8.0", "dayjs": "^1.10.4", - "debug": "^4.3.2", + "debug": "^4.3.4", "enquirer": "^2.3.6", "eventemitter2": "6.4.7", "execa": "4.1.0", @@ -8287,30 +7929,25 @@ "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", - "is-ci": "^3.0.0", + "is-ci": "^3.0.1", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", "lodash": "^4.17.21", "log-symbols": "^4.0.0", - "minimist": "^1.2.6", + "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", - "semver": "^7.3.2", + "semver": "^7.5.3", "supports-color": "^8.1.1", "tmp": "~0.2.1", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, "dependencies": { - "@types/node": { - "version": "14.18.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.29.tgz", - "integrity": "sha512-LhF+9fbIX4iPzhsRLpK5H7iPdvW8L4IwGciXQIOEcuF62+9nw/VQVsOViAOOGxY3OlOKGLFv0sWwJXdwQeTn6A==", - "dev": true - }, "fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -8326,68 +7963,48 @@ } }, "cypress-multi-reporters": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.1.tgz", - "integrity": "sha512-FPeC0xWF1N6Myrwc2m7KC0xxlrtG8+x4hlsPFBDRWP8u/veR2x90pGaH3BuJfweV7xoQ4Zo85Qjhu3fgZGrBQQ==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.4.tgz", + "integrity": "sha512-3xU2t6pZjZy/ORHaCvci5OT1DAboS4UuMMM8NBAizeb2C9qmHt+cgAjXgurazkwkPRdO7ccK39M5ZaPCju0r6A==", "dev": true, "peer": true, "requires": { - "debug": "^4.1.1", - "lodash": "^4.17.15" + "debug": "^4.3.4", + "lodash": "^4.17.21" } }, "cypress-parallel": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.9.1.tgz", - "integrity": "sha512-7VSfFr8HEEN6zkgo6SkG7pPoHK7VakFhEH1jbM4+Ire/I+O2jNzyd1bRUA+O3V2DIMow64ECDJKf13YHBon+BQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.14.0.tgz", + "integrity": "sha512-Lsh28G70vxjL0cjR820BdaVQHnGc17Vvb+tYmjbRPmfC+XEzwvUzhcaD0E1zCztBSYhw+b1/1JLmW4Y0qE/EDA==", "dev": true, "requires": { + "@colors/colors": "^1.5.0", "cli-table3": "^0.6.0", - "colors": "^1.4.0", "cross-spawn": "^7.0.3", "fs-extra": "^10.0.0", "glob-escape": "^0.0.2", "is-npm": "^5.0.0", "lodash.camelcase": "^4.3.0", - "mocha": "^8.2.1", + "mocha": "~9.2.0", "yargs": "15.3.1" }, "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "ms": "2.1.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, "decamelize": { @@ -8396,33 +8013,14 @@ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "argparse": "^2.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "locate-path": { @@ -8434,86 +8032,6 @@ "p-locate": "^4.1.0" } }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "requires": { - "chalk": "^4.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - } - } - }, - "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", - "dev": true - }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -8532,21 +8050,6 @@ "p-limit": "^2.2.0" } }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", - "dev": true - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -8558,6 +8061,12 @@ "strip-ansi": "^6.0.0" } }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "yargs": { "version": "15.3.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", @@ -8575,45 +8084,16 @@ "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.1" - }, - "dependencies": { - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -8633,16 +8113,10 @@ "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", "dev": true }, - "date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "dev": true - }, "dayjs": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", - "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==", + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", "dev": true }, "debug": { @@ -8786,12 +8260,13 @@ } }, "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "requires": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" } }, "entities": { @@ -9116,8 +8591,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "peer": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-caller-file": { "version": "2.0.5", @@ -9129,7 +8603,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "peer": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -9201,9 +8674,9 @@ "peer": true }, "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, "requires": { "ini": "2.0.0" @@ -9252,7 +8725,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "peer": true, "requires": { "function-bind": "^1.1.1" } @@ -9266,14 +8738,12 @@ "has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "peer": true + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "peer": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "he": { "version": "1.2.0", @@ -10195,9 +9665,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, "minipass": { @@ -10421,8 +9891,7 @@ "object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "peer": true + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "object-to-spawn-args": { "version": "2.0.1", @@ -10548,6 +10017,12 @@ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, "proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", @@ -10577,9 +10052,18 @@ "dev": true }, "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, "queue-microtask": { @@ -10725,6 +10209,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", @@ -10751,20 +10241,11 @@ "dev": true }, "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10868,17 +10349,10 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "peer": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -10948,16 +10422,10 @@ "source-map": "^0.6.0" } }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true - }, "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -11188,9 +10656,9 @@ "peer": true }, "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", "dev": true }, "through": { @@ -11200,13 +10668,10 @@ "dev": true }, "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true }, "to-regex-range": { "version": "5.0.1", @@ -11218,13 +10683,23 @@ } }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + } } }, "tr46": { @@ -11232,12 +10707,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, "trough": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", @@ -11492,6 +10961,16 @@ "punycode": "^2.1.0" } }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -11640,53 +11119,11 @@ } }, "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -11751,29 +11188,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "dependencies": { - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, "yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json index f542343d62..8740706220 100644 --- a/bindings/wasm/package.json +++ b/bindings/wasm/package.json @@ -19,11 +19,14 @@ "build:examples:web": "tsc --project ./examples/tsconfig.web.json && node ./build/replace_paths ./examples/tsconfig.web.json ./examples/dist resolve", "build": "npm run build:web && npm run build:nodejs && npm run build:docs", "example:node": "ts-node --project tsconfig.node.json -r tsconfig-paths/register ./examples/src/main.ts", - "test": "npm run test:unit:node && npm run test:examples", - "test:examples": "npm run test:readme && concurrently -g --timings \"npm run test:node\" \"npm run test:browser:parallel\"", + "test": "npm run test:unit:node && npm run test:readme && npm run test:node && test:browser:parallel", "test:node": "ts-mocha -r tsconfig-paths/register -p tsconfig.node.json ./examples/src/tests/*.ts --parallel --jobs 4 --retries 3 --timeout 180000 --exit", - "test:browser:parallel": "npm run build:examples:web && cypress-parallel -s test:browser -t 4 -d cypress/e2e -a '\"--quiet\"'", + "test:browser:parallel": "cypress-parallel -s test:browser -t 4 -d cypress/e2e -a '\"--quiet\"'", + "test:browser:parallel:firefox": "cypress-parallel -s test:browser:firefox -t 4 -d cypress/e2e -a '\"--quiet\"'", + "test:browser:parallel:chrome": "cypress-parallel -s test:browser:chrome -t 4 -d cypress/e2e -a '\"--quiet\"'", "test:browser": "cypress run --headless", + "test:browser:firefox": "cypress run --headless --browser firefox", + "test:browser:chrome": "cypress run --headless --browser chrome", "test:readme": "mocha ./tests/txm_readme.js --retries 3 --timeout 180000 --exit", "test:readme:rust": "mocha ./tests/txm_readme_rust.js --retries 3 --timeout 360000 --exit", "test:unit:node": "ts-mocha -p tsconfig.node.json ./tests/*.ts --parallel --exit", @@ -57,10 +60,9 @@ "@transmute/did-key-ed25519": "0.3.0-unstable.9", "@types/mocha": "^9.1.0", "big-integer": "^1.6.51", - "concurrently": "^7.6.0", "copy-webpack-plugin": "^7.0.0", - "cypress": "^10.11.0", - "cypress-parallel": "^0.9.1", + "cypress": "^13.12.0", + "cypress-parallel": "^0.14.0", "dprint": "^0.33.0", "fs-extra": "^10.1.0", "jsdoc-to-markdown": "^7.1.1", From 2ebacb877b5b192585376321d71f3cac74604d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Ha=C3=9F?= Date: Wed, 28 Aug 2024 16:56:56 +0200 Subject: [PATCH 13/22] fix sandbox teardown (#1401) --- .github/actions/iota-sandbox/tear-down/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/iota-sandbox/tear-down/action.yml b/.github/actions/iota-sandbox/tear-down/action.yml index 8a0da1906e..c8e6225d0b 100644 --- a/.github/actions/iota-sandbox/tear-down/action.yml +++ b/.github/actions/iota-sandbox/tear-down/action.yml @@ -7,6 +7,6 @@ runs: shell: bash run: | cd iota-sandbox/sandbox - docker-compose down + docker compose down cd ../.. sudo rm -rf iota-sandbox From 13f9987ce01aec667f1292f4622f9f315515bb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Ha=C3=9F?= Date: Fri, 30 Aug 2024 09:43:13 +0200 Subject: [PATCH 14/22] Reenable legacy Firefox CDP support (#1403) --- .github/workflows/build-and-test.yml | 2 +- bindings/wasm/cypress.config.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 553774bb46..e24c9a171d 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -253,7 +253,7 @@ jobs: load: true - name: Run cypress - run: docker run --network host cypress-test test:browser:firefox + run: docker run --network host cypress-test test:browser:parallel:firefox - name: Tear down iota sandbox if: always() diff --git a/bindings/wasm/cypress.config.ts b/bindings/wasm/cypress.config.ts index f7cb0a6a1a..c59929872a 100644 --- a/bindings/wasm/cypress.config.ts +++ b/bindings/wasm/cypress.config.ts @@ -10,14 +10,20 @@ export default defineConfig({ }, e2e: { supportFile: false, - // Fix to make subtle crypto work in cypress firefox - // https://github.com/cypress-io/cypress/issues/18217 setupNodeEvents(on, config) { on("before:browser:launch", (browser, launchOptions) => { if (browser.family === "firefox") { + // Fix to make subtle crypto work in cypress firefox + // https://github.com/cypress-io/cypress/issues/18217 launchOptions.preferences[ "network.proxy.testing_localhost_is_secure_when_hijacked" ] = true; + // Temporary fix to allow cypress to control Firefox via CDP + // https://github.com/cypress-io/cypress/issues/29713 + // https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/ + launchOptions.preferences[ + "remote.active-protocols" + ] = 3; } return launchOptions; }); From 842f483c1aab7760a2e0bddad515b932ecbed7ba Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Mon, 2 Sep 2024 13:01:22 +0200 Subject: [PATCH 15/22] Add feature to support custom `now_utc` implementations (#1397) * Add feature to support custom `now_utc` implementations This PR adds a feature to `identity_core` to allow specifying a custom function to get the current time (`Timestamp::now_utc`). The feature is disabled by default. Closes #1391. * Formatting * Fix wrong comment * chore: clippy fixes and fmt * chore: clippy fixes and fmt * Allow compilation for target wasm32-unknown-unknown without js-sys Also removes the unused dependency on `iota-crypto` (which also had a dependency on `js-sys` through the `random` feature). * chore(ci): Fix CI actions; add random feature to iota crypto --------- Co-authored-by: Yasir --- .github/workflows/build-and-test.yml | 11 ++- identity_core/Cargo.toml | 11 ++- identity_core/src/common/ordered_set.rs | 2 +- identity_core/src/common/timestamp.rs | 16 +++- identity_core/src/custom_time.rs | 88 +++++++++++++++++++ identity_core/src/lib.rs | 7 +- identity_core/tests/custom_time.rs | 18 ++++ .../src/credential/jwt_serialization.rs | 2 +- .../domain_linkage_validator.rs | 6 +- .../revocation/status_list_2021/credential.rs | 2 +- .../jwt_presentation_validator.rs | 8 +- .../src/validator/sd_jwt/validator.rs | 6 +- .../src/document/core_document.rs | 4 +- identity_jose/src/jwu/serde.rs | 3 +- identity_jose/src/tests/rfc8037.rs | 24 +++-- identity_resolver/src/resolution/resolver.rs | 8 +- identity_storage/Cargo.toml | 13 ++- identity_stronghold/Cargo.toml | 17 ++-- 18 files changed, 193 insertions(+), 53 deletions(-) create mode 100644 identity_core/src/custom_time.rs create mode 100644 identity_core/tests/custom_time.rs diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index e24c9a171d..8919e81020 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -127,14 +127,17 @@ jobs: # Build the library, tests, and examples without running them to avoid recompilation in the run tests step - name: Build with all features - run: cargo build --workspace --tests --examples --all-features --release + run: cargo build --workspace --tests --examples --release - name: Start iota sandbox if: matrix.os == 'ubuntu-latest' uses: './.github/actions/iota-sandbox/setup' - - name: Run tests - run: cargo test --workspace --all-features --release + - name: Run tests excluding `custom_time` feature + run: cargo test --workspace --release + + - name: Run tests with `custom_time` feature + run: cargo test --test custom_time --features="custom_time" - name: Run Rust examples # run examples only on ubuntu for now @@ -157,7 +160,7 @@ jobs: - name: Tear down iota sandbox if: matrix.os == 'ubuntu-latest' && always() uses: './.github/actions/iota-sandbox/tear-down' - + - name: Stop sccache uses: './.github/actions/rust/sccache/stop-sccache' with: diff --git a/identity_core/Cargo.toml b/identity_core/Cargo.toml index 0f7a8a34eb..f8aa615b28 100644 --- a/identity_core/Cargo.toml +++ b/identity_core/Cargo.toml @@ -12,7 +12,6 @@ rust-version.workspace = true description = "The core traits and types for the identity-rs library." [dependencies] -iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "random", "sha", "x25519", "std"] } multibase = { version = "0.9", default-features = false, features = ["std"] } serde = { workspace = true, features = ["std"] } serde_json = { workspace = true, features = ["std"] } @@ -22,7 +21,7 @@ time = { version = "0.3.23", default-features = false, features = ["std", "serde url = { version = "2.4", default-features = false, features = ["serde"] } zeroize = { version = "1.6", default-features = false } -[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] +[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(feature = "custom_time")))'.dependencies] js-sys = { version = "0.3.55", default-features = false } [dev-dependencies] @@ -38,3 +37,11 @@ rustdoc-args = ["--cfg", "docsrs"] [lints] workspace = true + +[features] +# Enables a macro to provide a custom time (Timestamp::now_utc) implementation, see src/custom_time.rs +custom_time = [] + +[[test]] +name = "custom_time" +required-features = ["custom_time"] diff --git a/identity_core/src/common/ordered_set.rs b/identity_core/src/common/ordered_set.rs index b3650490ef..885342409b 100644 --- a/identity_core/src/common/ordered_set.rs +++ b/identity_core/src/common/ordered_set.rs @@ -488,7 +488,7 @@ mod tests { /// Produces a strategy for generating an ordered set together with two values according to the following algorithm: /// 1. Call `f` to get a pair of sets (x,y). /// 2. Toss a coin to decide whether to pick an element from x at random, or from y (if the chosen set is empty - /// Default is called). 3. Repeat step 2 and let the two outcomes be denoted a and b. + /// Default is called). 3. Repeat step 2 and let the two outcomes be denoted a and b. /// 4. Toss a coin to decide whether to swap the keys of a and b. /// 5. return (x,a,b) fn set_with_values(f: F) -> impl Strategy, T, T)> diff --git a/identity_core/src/common/timestamp.rs b/identity_core/src/common/timestamp.rs index 8de1832409..4f03db2cea 100644 --- a/identity_core/src/common/timestamp.rs +++ b/identity_core/src/common/timestamp.rs @@ -42,7 +42,10 @@ impl Timestamp { /// fractional seconds truncated. /// /// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production). - #[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))] + #[cfg(all( + not(all(target_arch = "wasm32", not(target_os = "wasi"))), + not(feature = "custom_time") + ))] pub fn now_utc() -> Self { Self(truncate_fractional_seconds(OffsetDateTime::now_utc())) } @@ -51,7 +54,7 @@ impl Timestamp { /// fractional seconds truncated. /// /// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production). - #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))] + #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(feature = "custom_time")))] pub fn now_utc() -> Self { let milliseconds_since_unix_epoch: i64 = js_sys::Date::now() as i64; let seconds: i64 = milliseconds_since_unix_epoch / 1000; @@ -59,6 +62,15 @@ impl Timestamp { Self::from_unix(seconds).expect("Timestamp failed to convert system datetime") } + /// Creates a new `Timestamp` with the current date and time, normalized to UTC+00:00 with + /// fractional seconds truncated. + /// + /// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production). + #[cfg(feature = "custom_time")] + pub fn now_utc() -> Self { + crate::custom_time::now_utc_custom() + } + /// Returns the `Timestamp` as an [RFC 3339](https://tools.ietf.org/html/rfc3339) `String`. pub fn to_rfc3339(&self) -> String { // expect is okay, constructors ensure RFC 3339 compatible timestamps. diff --git a/identity_core/src/custom_time.rs b/identity_core/src/custom_time.rs new file mode 100644 index 0000000000..ef509a19de --- /dev/null +++ b/identity_core/src/custom_time.rs @@ -0,0 +1,88 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! An implementation of `now_utc` which calls out to an externally defined function. +use crate::common::Timestamp; + +/// Register a function to be invoked by `identity_core` in order to get a [Timestamp] representing +/// "now". +/// +/// ## Writing a custom `now_utc` implementation +/// +/// The function to register must have the same signature as +/// [`Timestamp::now_utc`](Timestamp::now_utc). The function can be defined +/// wherever you want, either in root crate or a dependent crate. +/// +/// For example, if we wanted a `static_now_utc` crate containing an +/// implementation that always returns the same timestamp, we would first depend on `identity_core` +/// (for the [`Timestamp`] type) in `static_now_utc/Cargo.toml`: +/// ```toml +/// [dependencies] +/// identity_core = "1" +/// ``` +/// Note that the crate containing this function does **not** need to enable the +/// `"custom_time"` Cargo feature. +/// +/// Next, in `static_now_utc/src/lib.rs`, we define our function: +/// ```rust +/// use identity_core::common::Timestamp; +/// +/// // Some fixed timestamp +/// const MY_FIXED_TIMESTAMP: i64 = 1724402964; +/// pub fn static_now_utc() -> Timestamp { +/// Timestamp::from_unix(MY_FIXED_TIMESTAMP).unwrap() +/// } +/// ``` +/// +/// ## Registering a custom `now_utc` implementation +/// +/// Functions can only be registered in the root binary crate. Attempting to +/// register a function in a non-root crate will result in a linker error. +/// This is similar to +/// [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) or +/// [`#[global_allocator]`](https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/global-allocators.html), +/// where helper crates define handlers/allocators but only the binary crate +/// actually _uses_ the functionality. +/// +/// To register the function, we first depend on `static_now_utc` _and_ +/// `identity_core` in `Cargo.toml`: +/// ```toml +/// [dependencies] +/// static_now_utc = "0.1" +/// identity_core = { version = "1", features = ["custom_time"] } +/// ``` +/// +/// Then, we register the function in `src/main.rs`: +/// ```rust +/// # mod static_now_utc { pub fn static_now_utc() -> Timestamp { unimplemented!() } } +/// +/// use identity_core::register_custom_now_utc; +/// use static_now_utc::static_now_utc; +/// +/// register_custom_now_utc!(static_now_utc); +/// ``` +/// +/// Now any user of `now_utc` (direct or indirect) on this target will use the +/// registered function. +#[macro_export] +macro_rules! register_custom_now_utc { + ($path:path) => { + const __GET_TIME_INTERNAL: () = { + // We use Rust ABI to be safe against potential panics in the passed function. + #[no_mangle] + unsafe fn __now_utc_custom() -> Timestamp { + // Make sure the passed function has the type of `now_utc_custom` + type F = fn() -> Timestamp; + let f: F = $path; + f() + } + }; + }; +} + +pub(crate) fn now_utc_custom() -> Timestamp { + extern "Rust" { + fn __now_utc_custom() -> Timestamp; + } + unsafe { __now_utc_custom() } +} diff --git a/identity_core/src/lib.rs b/identity_core/src/lib.rs index b915fcdeba..0e439441e4 100644 --- a/identity_core/src/lib.rs +++ b/identity_core/src/lib.rs @@ -1,7 +1,6 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -#![forbid(unsafe_code)] #![doc = include_str!("./../README.md")] #![allow(clippy::upper_case_acronyms)] #![warn( @@ -19,9 +18,15 @@ #[doc(inline)] pub use serde_json::json; +#[forbid(unsafe_code)] pub mod common; +#[forbid(unsafe_code)] pub mod convert; +#[forbid(unsafe_code)] pub mod error; +#[cfg(feature = "custom_time")] +pub mod custom_time; + pub use self::error::Error; pub use self::error::Result; diff --git a/identity_core/tests/custom_time.rs b/identity_core/tests/custom_time.rs new file mode 100644 index 0000000000..9c700d523e --- /dev/null +++ b/identity_core/tests/custom_time.rs @@ -0,0 +1,18 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use identity_core::common::Timestamp; +use identity_core::register_custom_now_utc; + +const STATIC_TIME: i64 = 1724402964; // 2024-08-23T11:33:30+00:00 +pub fn static_now_utc() -> Timestamp { + Timestamp::from_unix(STATIC_TIME).unwrap() +} + +register_custom_now_utc!(static_now_utc); + +#[test] +fn should_use_registered_static_time() { + let timestamp = Timestamp::now_utc(); + assert_eq!(timestamp.to_unix(), STATIC_TIME) +} diff --git a/identity_credential/src/credential/jwt_serialization.rs b/identity_credential/src/credential/jwt_serialization.rs index 6ce3c60b67..3f2a33f0a7 100644 --- a/identity_credential/src/credential/jwt_serialization.rs +++ b/identity_credential/src/credential/jwt_serialization.rs @@ -32,7 +32,7 @@ use crate::Result; /// This type is opinionated in the following ways: /// 1. Serialization tries to duplicate as little as possible between the required registered claims and the `vc` entry. /// 2. Only allows serializing/deserializing claims "exp, iss, nbf &/or iat, jti, sub and vc". Other custom properties -/// must be set in the `vc` entry. +/// must be set in the `vc` entry. #[derive(Serialize, Deserialize)] pub(crate) struct CredentialJwtClaims<'credential, T = Object> where diff --git a/identity_credential/src/domain_linkage/domain_linkage_validator.rs b/identity_credential/src/domain_linkage/domain_linkage_validator.rs index 24969c1c65..be67c96832 100644 --- a/identity_credential/src/domain_linkage/domain_linkage_validator.rs +++ b/identity_credential/src/domain_linkage/domain_linkage_validator.rs @@ -38,15 +38,15 @@ impl JwtDomainLinkageValidator { /// Validates the linkage between a domain and a DID. /// [`DomainLinkageConfiguration`] is validated according to [DID Configuration Resource Verification](https://identity.foundation/.well-known/resources/did-configuration/#did-configuration-resource-verification). /// - /// * `issuer`: DID Document of the linked DID. Issuer of the Domain Linkage Credential included - /// in the Domain Linkage Configuration. + /// * `issuer`: DID Document of the linked DID. Issuer of the Domain Linkage Credential included in the Domain Linkage + /// Configuration. /// * `configuration`: Domain Linkage Configuration fetched from the domain at "/.well-known/did-configuration.json". /// * `domain`: domain from which the Domain Linkage Configuration has been fetched. /// * `validation_options`: Further validation options to be applied on the Domain Linkage Credential. /// /// # Note: /// - Only the [JSON Web Token Proof Format](https://identity.foundation/.well-known/resources/did-configuration/#json-web-token-proof-format) - /// is supported. + /// is supported. /// - Only the Credential issued by `issuer` is verified. /// /// # Errors diff --git a/identity_credential/src/revocation/status_list_2021/credential.rs b/identity_credential/src/revocation/status_list_2021/credential.rs index 4402283e1a..ed96643cb7 100644 --- a/identity_credential/src/revocation/status_list_2021/credential.rs +++ b/identity_credential/src/revocation/status_list_2021/credential.rs @@ -123,7 +123,7 @@ impl StatusList2021Credential { /// /// ## Note: /// - A revoked credential cannot ever be unrevoked and will lead to a - /// [`StatusList2021CredentialError::UnreversibleRevocation`]. + /// [`StatusList2021CredentialError::UnreversibleRevocation`]. /// - Trying to set `revoked_or_suspended` to `false` for an already valid credential will have no impact. pub fn set_credential_status( &mut self, diff --git a/identity_credential/src/validator/jwt_presentation_validation/jwt_presentation_validator.rs b/identity_credential/src/validator/jwt_presentation_validation/jwt_presentation_validator.rs index a02b2cf56a..d6d97fcf6e 100644 --- a/identity_credential/src/validator/jwt_presentation_validation/jwt_presentation_validator.rs +++ b/identity_credential/src/validator/jwt_presentation_validation/jwt_presentation_validator.rs @@ -47,11 +47,11 @@ where /// # Warning /// /// * This method does NOT validate the constituent credentials and therefore also not the relationship between the - /// credentials' subjects and the presentation holder. This can be done with - /// [`JwtCredentialValidationOptions`](crate::validator::JwtCredentialValidationOptions). + /// credentials' subjects and the presentation holder. This can be done with + /// [`JwtCredentialValidationOptions`](crate::validator::JwtCredentialValidationOptions). /// * The lack of an error returned from this method is in of itself not enough to conclude that the presentation can - /// be trusted. This section contains more information on additional checks that should be carried out before and - /// after calling this method. + /// be trusted. This section contains more information on additional checks that should be carried out before and + /// after calling this method. /// /// ## The state of the supplied DID Documents. /// diff --git a/identity_credential/src/validator/sd_jwt/validator.rs b/identity_credential/src/validator/sd_jwt/validator.rs index 0eedf13bf5..e01985fa01 100644 --- a/identity_credential/src/validator/sd_jwt/validator.rs +++ b/identity_credential/src/validator/sd_jwt/validator.rs @@ -53,10 +53,10 @@ impl SdJwtCredentialValidator { /// /// # Warning /// * The key binding JWT is not validated. If needed, it must be validated separately using - /// `SdJwtValidator::validate_key_binding_jwt`. + /// `SdJwtValidator::validate_key_binding_jwt`. /// * The lack of an error returned from this method is in of itself not enough to conclude that the credential can be - /// trusted. This section contains more information on additional checks that should be carried out before and after - /// calling this method. + /// trusted. This section contains more information on additional checks that should be carried out before and after + /// calling this method. /// /// ## The state of the issuer's DID Document /// The caller must ensure that `issuer` represents an up-to-date DID Document. diff --git a/identity_document/src/document/core_document.rs b/identity_document/src/document/core_document.rs index 1b226f9585..2f6bcd593f 100644 --- a/identity_document/src/document/core_document.rs +++ b/identity_document/src/document/core_document.rs @@ -938,8 +938,8 @@ impl CoreDocument { /// Regardless of which options are passed the following conditions must be met in order for a verification attempt to /// take place. /// - The JWS must be encoded according to the JWS compact serialization. - /// - The `kid` value in the protected header must be an identifier of a verification method in this DID document, - /// or set explicitly in the `options`. + /// - The `kid` value in the protected header must be an identifier of a verification method in this DID document, or + /// set explicitly in the `options`. // // NOTE: This is tested in `identity_storage` and `identity_credential`. pub fn verify_jws<'jws, T: JwsVerifier>( diff --git a/identity_jose/src/jwu/serde.rs b/identity_jose/src/jwu/serde.rs index cd80a1c949..e875da0e10 100644 --- a/identity_jose/src/jwu/serde.rs +++ b/identity_jose/src/jwu/serde.rs @@ -57,8 +57,7 @@ pub(crate) fn validate_jws_headers(protected: Option<&JwsHeader>, unprotected: O /// Validates that the "crit" parameter satisfies the following requirements: /// 1. It is integrity protected. /// 2. It is not encoded as an empty list. -/// 3. It does not contain any header parameters defined by the -/// JOSE JWS/JWA specifications. +/// 3. It does not contain any header parameters defined by the JOSE JWS/JWA specifications. /// 4. It's values are contained in the given `permitted` array. /// 5. All values in "crit" are present in at least one of the `protected` or `unprotected` headers. /// diff --git a/identity_jose/src/tests/rfc8037.rs b/identity_jose/src/tests/rfc8037.rs index aada7a7369..d83f22eb89 100644 --- a/identity_jose/src/tests/rfc8037.rs +++ b/identity_jose/src/tests/rfc8037.rs @@ -50,20 +50,18 @@ fn test_rfc8037_ed25519() { .and_then(|decoded| decoded.verify(&jws_verifier, &public)) .unwrap(); - #[cfg(feature = "eddsa")] - { - let jws_signature_verifier = JwsVerifierFn::from(|input: VerificationInput, key: &Jwk| match input.alg { - JwsAlgorithm::EdDSA => ed25519::verify(input, key), - other => unimplemented!("{other}"), - }); + let jws_signature_verifier = JwsVerifierFn::from(|input: VerificationInput, key: &Jwk| match input.alg { + JwsAlgorithm::EdDSA => ed25519::verify(input, key), + other => unimplemented!("{other}"), + }); + + let decoder = Decoder::new(); + let token_with_default = decoder + .decode_compact_serialization(jws.as_bytes(), None) + .and_then(|decoded| decoded.verify(&jws_signature_verifier, &public)) + .unwrap(); - let decoder = Decoder::new(); - let token_with_default = decoder - .decode_compact_serialization(jws.as_bytes(), None) - .and_then(|decoded| decoded.verify(&jws_signature_verifier, &public)) - .unwrap(); - assert_eq!(token, token_with_default); - } + assert_eq!(token, token_with_default); assert_eq!(token.protected, header); assert_eq!(token.claims, tv.payload.as_bytes()); } diff --git a/identity_resolver/src/resolution/resolver.rs b/identity_resolver/src/resolution/resolver.rs index b8ceffbc7f..eff86351be 100644 --- a/identity_resolver/src/resolution/resolver.rs +++ b/identity_resolver/src/resolution/resolver.rs @@ -301,10 +301,10 @@ mod iota_handler { /// /// # Note /// - /// - Using `attach_iota_handler` or `attach_handler` for the IOTA method would override all - /// previously added clients. - /// - This function does not validate the provided configuration. Ensure that the provided - /// network name corresponds with the client, possibly by using `client.network_name()`. + /// - Using `attach_iota_handler` or `attach_handler` for the IOTA method would override all previously added + /// clients. + /// - This function does not validate the provided configuration. Ensure that the provided network name corresponds + /// with the client, possibly by using `client.network_name()`. pub fn attach_multiple_iota_handlers(&mut self, clients: I) where CLI: IotaIdentityClientExt + Send + Sync + 'static, diff --git a/identity_storage/Cargo.toml b/identity_storage/Cargo.toml index 08a0d68d7d..5b2ff0c8f6 100644 --- a/identity_storage/Cargo.toml +++ b/identity_storage/Cargo.toml @@ -21,11 +21,11 @@ identity_credential = { version = "=1.3.1", path = "../identity_credential", def identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } identity_iota_core = { version = "=1.3.1", path = "../identity_iota_core", default-features = false, optional = true } -identity_verification = { version = "=1.3.1", path = "../identity_verification", default_features = false } -iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"], optional = true } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } +iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "random"], optional = true } json-proof-token = { workspace = true, optional = true } rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true } -seahash = { version = "4.1.0", default_features = false } +seahash = { version = "4.1.0", default-features = false } serde.workspace = true serde_json.workspace = true thiserror.workspace = true @@ -47,7 +47,12 @@ send-sync-storage = [] # Implements the JwkStorageDocumentExt trait for IotaDocument iota-document = ["dep:identity_iota_core"] # Enables JSON Proof Token & BBS+ related features -jpt-bbs-plus = ["identity_credential/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"] +jpt-bbs-plus = [ + "identity_credential/jpt-bbs-plus", + "dep:zkryptium", + "dep:bls12_381_plus", + "dep:json-proof-token", +] [lints] workspace = true diff --git a/identity_stronghold/Cargo.toml b/identity_stronghold/Cargo.toml index 56ae126bdc..10d58da369 100644 --- a/identity_stronghold/Cargo.toml +++ b/identity_stronghold/Cargo.toml @@ -14,22 +14,22 @@ description = "Secure JWK storage with Stronghold for IOTA Identity" [dependencies] async-trait = { version = "0.1.64", default-features = false } bls12_381_plus = { workspace = true, optional = true } -identity_storage = { version = "=1.3.1", path = "../identity_storage", default_features = false } -identity_verification = { version = "=1.3.1", path = "../identity_verification", default_features = false } +identity_storage = { version = "=1.3.1", path = "../identity_storage", default-features = false } +identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"] } iota-sdk = { version = "1.1.5", default-features = false, features = ["client", "stronghold"] } iota_stronghold = { version = "2.1.0", default-features = false } json-proof-token = { workspace = true, optional = true } rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"] } tokio = { version = "1.29.0", default-features = false, features = ["macros", "sync"] } -zeroize = { version = "1.6.0", default_features = false } +zeroize = { version = "1.6.0", default-features = false } zkryptium = { workspace = true, optional = true } [dev-dependencies] anyhow = "1.0.82" bls12_381_plus = { workspace = true } -identity_did = { version = "=1.3.1", path = "../identity_did", default_features = false } -identity_storage = { version = "=1.3.1", path = "../identity_storage", default_features = false, features = ["jpt-bbs-plus"] } +identity_did = { version = "=1.3.1", path = "../identity_did", default-features = false } +identity_storage = { version = "=1.3.1", path = "../identity_storage", default-features = false, features = ["jpt-bbs-plus"] } json-proof-token = { workspace = true } tokio = { version = "1.29.0", default-features = false, features = ["macros", "sync", "rt"] } zkryptium = { workspace = true } @@ -38,7 +38,12 @@ zkryptium = { workspace = true } default = [] # Enables `Send` + `Sync` bounds for the trait implementations on `StrongholdStorage`. send-sync-storage = ["identity_storage/send-sync-storage"] -bbs-plus = ["identity_storage/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"] +bbs-plus = [ + "identity_storage/jpt-bbs-plus", + "dep:zkryptium", + "dep:bls12_381_plus", + "dep:json-proof-token", +] [lints] workspace = true From b355b47bd1fd796bfc4f978785f1206218a34aa8 Mon Sep 17 00:00:00 2001 From: wulfraem Date: Mon, 2 Sep 2024 16:22:49 +0200 Subject: [PATCH 16/22] Make `bls12_381_plus` dependency more flexible again (#1393) * update `bls12_381_plus` dependency - making version range more flexible again * fix clippy warning * fix clippy warning * fix clippy warnings * remove undefined feature check * bump depdendency version for `iota-crypto` * bump dependency version of bls12_381_plus in wasm bindings * update sandbox ci action to use 'docker compose' instead of 'docker-compose' * update step name to match latest updates --- .github/workflows/build-and-test.yml | 2 +- Cargo.toml | 2 +- bindings/wasm/Cargo.toml | 2 +- identity_credential/Cargo.toml | 2 +- identity_eddsa_verifier/Cargo.toml | 2 +- identity_iota_core/Cargo.toml | 2 +- identity_jose/Cargo.toml | 4 ++-- identity_jose/src/tests/rfc8037.rs | 5 +++-- identity_storage/Cargo.toml | 2 +- identity_stronghold/Cargo.toml | 2 +- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 8919e81020..ba3b7ef0b1 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -126,7 +126,7 @@ jobs: run: cargo clean # Build the library, tests, and examples without running them to avoid recompilation in the run tests step - - name: Build with all features + - name: Build with default features run: cargo build --workspace --tests --examples --release - name: Start iota sandbox diff --git a/Cargo.toml b/Cargo.toml index 0b349651b5..7dfcbcadd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ members = [ exclude = ["bindings/wasm", "bindings/grpc"] [workspace.dependencies] -bls12_381_plus = { version = "=0.8.15" } +bls12_381_plus = { version = "0.8.17" } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } thiserror = { version = "1.0", default-features = false } strum = { version = "0.25", default-features = false, features = ["std", "derive"] } diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 9e264b3b6d..1acaf0ce96 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] async-trait = { version = "0.1", default-features = false } -bls12_381_plus = "=0.8.15" +bls12_381_plus = "0.8.17" console_error_panic_hook = { version = "0.1" } futures = { version = "0.3" } identity_eddsa_verifier = { path = "../../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } diff --git a/identity_credential/Cargo.toml b/identity_credential/Cargo.toml index 2a4b11d09c..aaba6c974e 100644 --- a/identity_credential/Cargo.toml +++ b/identity_credential/Cargo.toml @@ -39,7 +39,7 @@ zkryptium = { workspace = true, optional = true } [dev-dependencies] anyhow = "1.0.62" identity_eddsa_verifier = { path = "../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } -iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "std", "random"] } +iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519", "std", "random"] } proptest = { version = "1.4.0", default-features = false, features = ["std"] } tokio = { version = "1.35.0", default-features = false, features = ["rt-multi-thread", "macros"] } diff --git a/identity_eddsa_verifier/Cargo.toml b/identity_eddsa_verifier/Cargo.toml index eedd1d652e..97308beebf 100644 --- a/identity_eddsa_verifier/Cargo.toml +++ b/identity_eddsa_verifier/Cargo.toml @@ -13,7 +13,7 @@ description = "JWS EdDSA signature verification for IOTA Identity" [dependencies] identity_jose = { version = "=1.3.1", path = "../identity_jose", default-features = false } -iota-crypto = { version = "0.23", default-features = false, features = ["std"] } +iota-crypto = { version = "0.23.2", default-features = false, features = ["std"] } [features] ed25519 = ["iota-crypto/ed25519"] diff --git a/identity_iota_core/Cargo.toml b/identity_iota_core/Cargo.toml index 0ddb2bd6b9..f44a3ca27c 100644 --- a/identity_iota_core/Cargo.toml +++ b/identity_iota_core/Cargo.toml @@ -31,7 +31,7 @@ thiserror.workspace = true [dev-dependencies] anyhow = { version = "1.0.57" } -iota-crypto = { version = "0.23", default-features = false, features = ["bip39", "bip39-en"] } +iota-crypto = { version = "0.23.2", default-features = false, features = ["bip39", "bip39-en"] } proptest = { version = "1.0.0", default-features = false, features = ["std"] } tokio = { version = "1.29.0", default-features = false, features = ["rt-multi-thread", "macros"] } diff --git a/identity_jose/Cargo.toml b/identity_jose/Cargo.toml index 32d3824a9a..da8ddba3d2 100644 --- a/identity_jose/Cargo.toml +++ b/identity_jose/Cargo.toml @@ -14,7 +14,7 @@ description = "A library for JOSE (JSON Object Signing and Encryption)" [dependencies] bls12_381_plus.workspace = true identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } -iota-crypto = { version = "0.23", default-features = false, features = ["std", "sha"] } +iota-crypto = { version = "0.23.2", default-features = false, features = ["std", "sha"] } json-proof-token.workspace = true serde.workspace = true serde_json = { version = "1.0", default-features = false, features = ["std"] } @@ -24,7 +24,7 @@ zeroize = { version = "1.6", default-features = false, features = ["std", "zeroi [dev-dependencies] anyhow = "1" -iota-crypto = { version = "0.23", features = ["ed25519", "random", "hmac"] } +iota-crypto = { version = "0.23.2", features = ["ed25519", "random", "hmac"] } p256 = { version = "0.12.0", default-features = false, features = ["std", "ecdsa", "ecdsa-core"] } signature = { version = "2", default-features = false } diff --git a/identity_jose/src/tests/rfc8037.rs b/identity_jose/src/tests/rfc8037.rs index d83f22eb89..27bb755979 100644 --- a/identity_jose/src/tests/rfc8037.rs +++ b/identity_jose/src/tests/rfc8037.rs @@ -50,6 +50,9 @@ fn test_rfc8037_ed25519() { .and_then(|decoded| decoded.verify(&jws_verifier, &public)) .unwrap(); + assert_eq!(token.protected, header); + assert_eq!(token.claims, tv.payload.as_bytes()); + let jws_signature_verifier = JwsVerifierFn::from(|input: VerificationInput, key: &Jwk| match input.alg { JwsAlgorithm::EdDSA => ed25519::verify(input, key), other => unimplemented!("{other}"), @@ -62,7 +65,5 @@ fn test_rfc8037_ed25519() { .unwrap(); assert_eq!(token, token_with_default); - assert_eq!(token.protected, header); - assert_eq!(token.claims, tv.payload.as_bytes()); } } diff --git a/identity_storage/Cargo.toml b/identity_storage/Cargo.toml index 5b2ff0c8f6..fbbe93b346 100644 --- a/identity_storage/Cargo.toml +++ b/identity_storage/Cargo.toml @@ -22,7 +22,7 @@ identity_did = { version = "=1.3.1", path = "../identity_did", default-features identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false } identity_iota_core = { version = "=1.3.1", path = "../identity_iota_core", default-features = false, optional = true } identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } -iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "random"], optional = true } +iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519", "random"], optional = true } json-proof-token = { workspace = true, optional = true } rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true } seahash = { version = "4.1.0", default-features = false } diff --git a/identity_stronghold/Cargo.toml b/identity_stronghold/Cargo.toml index 10d58da369..d6b0825cba 100644 --- a/identity_stronghold/Cargo.toml +++ b/identity_stronghold/Cargo.toml @@ -16,7 +16,7 @@ async-trait = { version = "0.1.64", default-features = false } bls12_381_plus = { workspace = true, optional = true } identity_storage = { version = "=1.3.1", path = "../identity_storage", default-features = false } identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } -iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"] } +iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519"] } iota-sdk = { version = "1.1.5", default-features = false, features = ["client", "stronghold"] } iota_stronghold = { version = "2.1.0", default-features = false } json-proof-token = { workspace = true, optional = true } From 84f1b7e133933f58504e387e84b7eae9a6298bff Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Wed, 4 Sep 2024 10:02:55 +0200 Subject: [PATCH 17/22] Mark `js-sys` as optional for identity_core (#1405) * Mark `js-sys` as optional for identity_core In #1397 my intention was to make the `js-sys` dependency mutually exclusive with the feature `custom_time`. As it turns out, it's not that simple and mixing target specific dependencies with feature specific dependencies does not actually work. See [here](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies) and [here](https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features). So this removes the broken feature reference in the dependency declaration and instead marks it as `optional`. Also, the feature `custom_time` takes precedence over `js-sys` so these do not actually conflict and one _could_ enable both. * Make js-sys a default feature * Fix defaults switch * Don't expose `js-sys` feature Co-authored-by: Yasir --------- Co-authored-by: Yasir --- identity_core/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/identity_core/Cargo.toml b/identity_core/Cargo.toml index f8aa615b28..239383c2f6 100644 --- a/identity_core/Cargo.toml +++ b/identity_core/Cargo.toml @@ -21,8 +21,8 @@ time = { version = "0.3.23", default-features = false, features = ["std", "serde url = { version = "2.4", default-features = false, features = ["serde"] } zeroize = { version = "1.6", default-features = false } -[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(feature = "custom_time")))'.dependencies] -js-sys = { version = "0.3.55", default-features = false } +[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] +js-sys = { version = "0.3.55", default-features = false, optional = true } [dev-dependencies] proptest = { version = "1.0.0" } @@ -39,6 +39,7 @@ rustdoc-args = ["--cfg", "docsrs"] workspace = true [features] +default = ["dep:js-sys"] # Enables a macro to provide a custom time (Timestamp::now_utc) implementation, see src/custom_time.rs custom_time = [] From 02a08574a698bb2b571abe10d910608397d3943e Mon Sep 17 00:00:00 2001 From: Enrico Marconi <31142849+UMR1352@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:46:38 +0200 Subject: [PATCH 18/22] Add support for `did:jwk` resolution (#1404) * did:jwk implementation & resolution * did:jwk WASM bindings * wasm did jwk test * cargo fmt * add missing license header * Update identity_did/src/did_jwk.rs Co-authored-by: wulfraem * Update identity_did/src/did_jwk.rs Co-authored-by: wulfraem --------- Co-authored-by: wulfraem --- bindings/wasm/docs/api-reference.md | 347 ++++++++++++------ .../examples/src/0_basic/2_resolve_did.ts | 27 +- bindings/wasm/src/did/did_jwk.rs | 105 ++++++ bindings/wasm/src/did/mod.rs | 2 + bindings/wasm/src/did/wasm_core_document.rs | 7 + identity_did/Cargo.toml | 1 + identity_did/src/did_jwk.rs | 123 +++++++ identity_did/src/lib.rs | 2 + .../src/document/core_document.rs | 47 +++ .../src/document/iota_document.rs | 9 + identity_resolver/src/resolution/resolver.rs | 28 ++ .../src/verification_method/method.rs | 9 + 12 files changed, 602 insertions(+), 105 deletions(-) create mode 100644 bindings/wasm/src/did/did_jwk.rs create mode 100644 identity_did/src/did_jwk.rs diff --git a/bindings/wasm/docs/api-reference.md b/bindings/wasm/docs/api-reference.md index db03dc07ec..6dd0837a69 100644 --- a/bindings/wasm/docs/api-reference.md +++ b/bindings/wasm/docs/api-reference.md @@ -14,6 +14,9 @@ if the object is being concurrently modified.

CustomMethodData

A custom verification method data format.

+
DIDJwk
+

did:jwk DID.

+
DIDUrl

A method agnostic DID Url.

@@ -254,29 +257,6 @@ working with storage backed DID documents.

PresentationProofAlgorithm
-
ProofAlgorithm
-
-
StatusCheck
-

Controls validation behaviour when checking whether or not a credential has been revoked by its -credentialStatus.

-
-
Strict
-

Validate the status if supported, reject any unsupported -credentialStatus types.

-

Only RevocationBitmap2022 is currently supported.

-

This is the default.

-
-
SkipUnsupported
-

Validate the status if supported, skip any unsupported -credentialStatus types.

-
-
SkipAll
-

Skip all status checks.

-
-
SerializationType
-
-
MethodRelationship
-
SubjectHolderRelationship

Declares how credential subjects must relate to the presentation holder.

See also the Subject-Holder Relationship section of the specification.

@@ -291,11 +271,8 @@ This variant is the default.

Any

The holder is not required to have any kind of relationship to any credential subject.

-
CredentialStatus
+
ProofAlgorithm
-
StatusPurpose
-

Purpose of a StatusList2021.

-
StateMetadataEncoding
FailFast
@@ -307,12 +284,6 @@ This variant is the default.

FirstError

Return after the first error occurs.

-
PayloadType
-
-
MethodRelationship
-
-
CredentialStatus
-
StatusCheck

Controls validation behaviour when checking whether or not a credential has been revoked by its credentialStatus.

@@ -330,11 +301,28 @@ This variant is the default.

SkipAll

Skip all status checks.

+
SerializationType
+
+
PayloadType
+
+
StatusPurpose
+

Purpose of a StatusList2021.

+
+
MethodRelationship
+
+
CredentialStatus
+
## Functions
+
encodeB64(data)string
+

Encode the given bytes in url-safe base64.

+
+
decodeB64(data)Uint8Array
+

Decode the given url-safe base64-encoded slice into its raw bytes.

+
verifyEd25519(alg, signingInput, decodedSignature, publicKey)

Verify a JWS signature secured with the EdDSA algorithm and curve Ed25519.

This function is useful when one is composing a IJwsVerifier that delegates @@ -346,15 +334,6 @@ prior to calling the function.

start()

Initializes the console error panic hook for better error messages

-
encodeB64(data)string
-

Encode the given bytes in url-safe base64.

-
-
decodeB64(data)Uint8Array
-

Decode the given url-safe base64-encoded slice into its raw bytes.

-
-
start()
-

Initializes the console error panic hook for better error messages

-
@@ -592,6 +571,7 @@ if the object is being concurrently modified. * [.createPresentationJwt(storage, fragment, presentation, signature_options, presentation_options)](#CoreDocument+createPresentationJwt) ⇒ [Promise.<Jwt>](#Jwt) * _static_ * [.fromJSON(json)](#CoreDocument.fromJSON) ⇒ [CoreDocument](#CoreDocument) + * [.expandDIDJwk(did)](#CoreDocument.expandDIDJwk) ⇒ [CoreDocument](#CoreDocument) @@ -1030,6 +1010,17 @@ Deserializes an instance from a plain JS representation. | --- | --- | | json | any | + + +### CoreDocument.expandDIDJwk(did) ⇒ [CoreDocument](#CoreDocument) +Creates a [CoreDocument](#CoreDocument) from the given [DIDJwk](#DIDJwk). + +**Kind**: static method of [CoreDocument](#CoreDocument) + +| Param | Type | +| --- | --- | +| did | [DIDJwk](#DIDJwk) | + ## Credential @@ -1282,6 +1273,136 @@ Deserializes an instance from a JSON object. | --- | --- | | json | any | + + +## DIDJwk +`did:jwk` DID. + +**Kind**: global class + +* [DIDJwk](#DIDJwk) + * [new DIDJwk(did)](#new_DIDJwk_new) + * _instance_ + * [.jwk()](#DIDJwk+jwk) ⇒ [Jwk](#Jwk) + * [.scheme()](#DIDJwk+scheme) ⇒ string + * [.authority()](#DIDJwk+authority) ⇒ string + * [.method()](#DIDJwk+method) ⇒ string + * [.methodId()](#DIDJwk+methodId) ⇒ string + * [.toString()](#DIDJwk+toString) ⇒ string + * [.toCoreDid()](#DIDJwk+toCoreDid) ⇒ [CoreDID](#CoreDID) + * [.toJSON()](#DIDJwk+toJSON) ⇒ any + * [.clone()](#DIDJwk+clone) ⇒ [DIDJwk](#DIDJwk) + * _static_ + * [.parse(input)](#DIDJwk.parse) ⇒ [DIDJwk](#DIDJwk) + * [.fromJSON(json)](#DIDJwk.fromJSON) ⇒ [DIDJwk](#DIDJwk) + + + +### new DIDJwk(did) +Creates a new [DIDJwk](#DIDJwk) from a [CoreDID](#CoreDID). + +### Errors +Throws an error if the given did is not a valid `did:jwk` DID. + + +| Param | Type | +| --- | --- | +| did | [CoreDID](#CoreDID) \| IToCoreDID | + + + +### didJwk.jwk() ⇒ [Jwk](#Jwk) +Returns the JSON WEB KEY (JWK) encoded inside this `did:jwk`. + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.scheme() ⇒ string +Returns the [CoreDID](#CoreDID) scheme. + +E.g. +- `"did:example:12345678" -> "did"` +- `"did:iota:smr:12345678" -> "did"` + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.authority() ⇒ string +Returns the [CoreDID](#CoreDID) authority: the method name and method-id. + +E.g. +- `"did:example:12345678" -> "example:12345678"` +- `"did:iota:smr:12345678" -> "iota:smr:12345678"` + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.method() ⇒ string +Returns the [CoreDID](#CoreDID) method name. + +E.g. +- `"did:example:12345678" -> "example"` +- `"did:iota:smr:12345678" -> "iota"` + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.methodId() ⇒ string +Returns the [CoreDID](#CoreDID) method-specific ID. + +E.g. +- `"did:example:12345678" -> "12345678"` +- `"did:iota:smr:12345678" -> "smr:12345678"` + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.toString() ⇒ string +Returns the [CoreDID](#CoreDID) as a string. + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.toCoreDid() ⇒ [CoreDID](#CoreDID) +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.toJSON() ⇒ any +Serializes this to a JSON object. + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### didJwk.clone() ⇒ [DIDJwk](#DIDJwk) +Deep clones the object. + +**Kind**: instance method of [DIDJwk](#DIDJwk) + + +### DIDJwk.parse(input) ⇒ [DIDJwk](#DIDJwk) +Parses a [DIDJwk](#DIDJwk) from the given `input`. + +### Errors + +Throws an error if the input is not a valid [DIDJwk](#DIDJwk). + +**Kind**: static method of [DIDJwk](#DIDJwk) + +| Param | Type | +| --- | --- | +| input | string | + + + +### DIDJwk.fromJSON(json) ⇒ [DIDJwk](#DIDJwk) +Deserializes an instance from a JSON object. + +**Kind**: static method of [DIDJwk](#DIDJwk) + +| Param | Type | +| --- | --- | +| json | any | + ## DIDUrl @@ -3224,7 +3345,7 @@ Utility functions for validating JPT credentials. ### JptCredentialValidatorUtils.extractIssuer(credential) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a [`Credential`](`Credential`) as a DID. +Utility for extracting the issuer field of a [Credential](#Credential) as a DID. # Errors Fails if the issuer field is not a valid DID. @@ -5450,7 +5571,8 @@ Supported verification method types. * _static_ * [.Ed25519VerificationKey2018()](#MethodType.Ed25519VerificationKey2018) ⇒ [MethodType](#MethodType) * [.X25519KeyAgreementKey2019()](#MethodType.X25519KeyAgreementKey2019) ⇒ [MethodType](#MethodType) - * [.JsonWebKey()](#MethodType.JsonWebKey) ⇒ [MethodType](#MethodType) + * ~~[.JsonWebKey()](#MethodType.JsonWebKey)~~ + * [.JsonWebKey2020()](#MethodType.JsonWebKey2020) ⇒ [MethodType](#MethodType) * [.custom(type_)](#MethodType.custom) ⇒ [MethodType](#MethodType) * [.fromJSON(json)](#MethodType.fromJSON) ⇒ [MethodType](#MethodType) @@ -5482,7 +5604,13 @@ Deep clones the object. **Kind**: static method of [MethodType](#MethodType) -### MethodType.JsonWebKey() ⇒ [MethodType](#MethodType) +### ~~MethodType.JsonWebKey()~~ +***Deprecated*** + +**Kind**: static method of [MethodType](#MethodType) + + +### MethodType.JsonWebKey2020() ⇒ [MethodType](#MethodType) A verification method for use with JWT verification as prescribed by the [Jwk](#Jwk) in the `publicKeyJwk` entry. @@ -7529,46 +7657,9 @@ Deserializes an instance from a JSON object. | --- | --- | | json | any | + -**Kind**: global variable - - -## StatusCheck -Controls validation behaviour when checking whether or not a credential has been revoked by its -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status). - -**Kind**: global variable - - -## Strict -Validate the status if supported, reject any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -Only `RevocationBitmap2022` is currently supported. - -This is the default. - -**Kind**: global variable - - -## SkipUnsupported -Validate the status if supported, skip any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -**Kind**: global variable - - -## SkipAll -Skip all status checks. - -**Kind**: global variable - - -## SerializationType -**Kind**: global variable - - -## MethodRelationship +## PresentationProofAlgorithm **Kind**: global variable @@ -7596,7 +7687,10 @@ The holder must match the subject only for credentials where the [`nonTransferab ## Any The holder is not required to have any kind of relationship to any credential subject. -## StateMetadataEncoding +**Kind**: global variable + + +## ProofAlgorithm **Kind**: global variable @@ -7620,36 +7714,59 @@ Return all errors that occur during validation. Return after the first error occurs. **Kind**: global variable + + +## StatusCheck +Controls validation behaviour when checking whether or not a credential has been revoked by its +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status). **Kind**: global variable - + -## verifyEd25519(alg, signingInput, decodedSignature, publicKey) -Verify a JWS signature secured with the `EdDSA` algorithm and curve `Ed25519`. +## Strict +Validate the status if supported, reject any unsupported +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. -This function is useful when one is composing a `IJwsVerifier` that delegates -`EdDSA` verification with curve `Ed25519` to this function. +Only `RevocationBitmap2022` is currently supported. -# Warning +This is the default. -This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this -prior to calling the function. +**Kind**: global variable + -**Kind**: global function +## SkipUnsupported +Validate the status if supported, skip any unsupported +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. -| Param | Type | -| --- | --- | -| alg | JwsAlgorithm | -| signingInput | Uint8Array | -| decodedSignature | Uint8Array | -| publicKey | [Jwk](#Jwk) | +**Kind**: global variable + - +## SkipAll +Skip all status checks. -## start() -Initializes the console error panic hook for better error messages +**Kind**: global variable + -**Kind**: global function +## SerializationType +**Kind**: global variable + + +## PayloadType +**Kind**: global variable + + +## StatusPurpose +Purpose of a [StatusList2021](#StatusList2021). + +**Kind**: global variable + + +## MethodRelationship +**Kind**: global variable + + +## CredentialStatus +**Kind**: global variable ## encodeB64(data) ⇒ string @@ -7672,6 +7789,28 @@ Decode the given url-safe base64-encoded slice into its raw bytes. | --- | --- | | data | Uint8Array | + + +## verifyEd25519(alg, signingInput, decodedSignature, publicKey) +Verify a JWS signature secured with the `EdDSA` algorithm and curve `Ed25519`. + +This function is useful when one is composing a `IJwsVerifier` that delegates +`EdDSA` verification with curve `Ed25519` to this function. + +# Warning + +This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this +prior to calling the function. + +**Kind**: global function + +| Param | Type | +| --- | --- | +| alg | JwsAlgorithm | +| signingInput | Uint8Array | +| decodedSignature | Uint8Array | +| publicKey | [Jwk](#Jwk) | + ## start() diff --git a/bindings/wasm/examples/src/0_basic/2_resolve_did.ts b/bindings/wasm/examples/src/0_basic/2_resolve_did.ts index 58bc205b6a..ce8ea7c3e1 100644 --- a/bindings/wasm/examples/src/0_basic/2_resolve_did.ts +++ b/bindings/wasm/examples/src/0_basic/2_resolve_did.ts @@ -1,10 +1,23 @@ // Copyright 2020-2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { IotaDocument, IotaIdentityClient, JwkMemStore, KeyIdMemStore, Storage } from "@iota/identity-wasm/node"; +import { + CoreDocument, + DIDJwk, + IotaDocument, + IotaIdentityClient, + IToCoreDocument, + JwkMemStore, + KeyIdMemStore, + Resolver, + Storage, +} from "@iota/identity-wasm/node"; import { AliasOutput, Client, MnemonicSecretManager, Utils } from "@iota/sdk-wasm/node"; import { API_ENDPOINT, createDid } from "../util"; +const DID_JWK: string = + "did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9"; + /** Demonstrates how to resolve an existing DID in an Alias Output. */ export async function resolveIdentity() { const client = new Client({ @@ -34,4 +47,16 @@ export async function resolveIdentity() { // We can also resolve the Alias Output directly. const aliasOutput: AliasOutput = await didClient.resolveDidOutput(did); console.log("The Alias Output holds " + aliasOutput.getAmount() + " tokens"); + + // did:jwk can be resolved as well. + const handlers = new Map Promise>(); + handlers.set("jwk", didJwkHandler); + const resolver = new Resolver({ handlers }); + const did_jwk_resolved_doc = await resolver.resolve(DID_JWK); + console.log(`DID ${DID_JWK} resolves to:\n ${JSON.stringify(did_jwk_resolved_doc, null, 2)}`); } + +const didJwkHandler = async (did: string) => { + let did_jwk = DIDJwk.parse(did); + return CoreDocument.expandDIDJwk(did_jwk); +}; diff --git a/bindings/wasm/src/did/did_jwk.rs b/bindings/wasm/src/did/did_jwk.rs new file mode 100644 index 0000000000..15ce291eca --- /dev/null +++ b/bindings/wasm/src/did/did_jwk.rs @@ -0,0 +1,105 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use identity_iota::did::DIDJwk; +use identity_iota::did::DID as _; +use wasm_bindgen::prelude::*; + +use super::wasm_core_did::get_core_did_clone; +use super::IToCoreDID; +use super::WasmCoreDID; +use crate::error::Result; +use crate::error::WasmResult; +use crate::jose::WasmJwk; + +/// `did:jwk` DID. +#[wasm_bindgen(js_name = DIDJwk)] +pub struct WasmDIDJwk(pub(crate) DIDJwk); + +#[wasm_bindgen(js_class = DIDJwk)] +impl WasmDIDJwk { + #[wasm_bindgen(constructor)] + /// Creates a new {@link DIDJwk} from a {@link CoreDID}. + /// + /// ### Errors + /// Throws an error if the given did is not a valid `did:jwk` DID. + pub fn new(did: IToCoreDID) -> Result { + let did = get_core_did_clone(&did).0; + DIDJwk::try_from(did).wasm_result().map(Self) + } + /// Parses a {@link DIDJwk} from the given `input`. + /// + /// ### Errors + /// + /// Throws an error if the input is not a valid {@link DIDJwk}. + #[wasm_bindgen] + pub fn parse(input: &str) -> Result { + DIDJwk::parse(input).wasm_result().map(Self) + } + + /// Returns the JSON WEB KEY (JWK) encoded inside this `did:jwk`. + #[wasm_bindgen] + pub fn jwk(&self) -> WasmJwk { + self.0.jwk().into() + } + + // =========================================================================== + // DID trait + // =========================================================================== + + /// Returns the {@link CoreDID} scheme. + /// + /// E.g. + /// - `"did:example:12345678" -> "did"` + /// - `"did:iota:smr:12345678" -> "did"` + #[wasm_bindgen] + pub fn scheme(&self) -> String { + self.0.scheme().to_owned() + } + + /// Returns the {@link CoreDID} authority: the method name and method-id. + /// + /// E.g. + /// - `"did:example:12345678" -> "example:12345678"` + /// - `"did:iota:smr:12345678" -> "iota:smr:12345678"` + #[wasm_bindgen] + pub fn authority(&self) -> String { + self.0.authority().to_owned() + } + + /// Returns the {@link CoreDID} method name. + /// + /// E.g. + /// - `"did:example:12345678" -> "example"` + /// - `"did:iota:smr:12345678" -> "iota"` + #[wasm_bindgen] + pub fn method(&self) -> String { + self.0.method().to_owned() + } + + /// Returns the {@link CoreDID} method-specific ID. + /// + /// E.g. + /// - `"did:example:12345678" -> "12345678"` + /// - `"did:iota:smr:12345678" -> "smr:12345678"` + #[wasm_bindgen(js_name = methodId)] + pub fn method_id(&self) -> String { + self.0.method_id().to_owned() + } + + /// Returns the {@link CoreDID} as a string. + #[allow(clippy::inherent_to_string)] + #[wasm_bindgen(js_name = toString)] + pub fn to_string(&self) -> String { + self.0.to_string() + } + + // Only intended to be called internally. + #[wasm_bindgen(js_name = toCoreDid, skip_typescript)] + pub fn to_core_did(&self) -> WasmCoreDID { + WasmCoreDID(self.0.clone().into()) + } +} + +impl_wasm_json!(WasmDIDJwk, DIDJwk); +impl_wasm_clone!(WasmDIDJwk, DIDJwk); diff --git a/bindings/wasm/src/did/mod.rs b/bindings/wasm/src/did/mod.rs index b89db3edbf..ae2e89bc0c 100644 --- a/bindings/wasm/src/did/mod.rs +++ b/bindings/wasm/src/did/mod.rs @@ -1,6 +1,7 @@ // Copyright 2020-2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +mod did_jwk; mod jws_verification_options; mod service; mod wasm_core_did; @@ -19,5 +20,6 @@ pub use self::wasm_core_document::PromiseJws; pub use self::wasm_core_document::PromiseJwt; pub use self::wasm_core_document::WasmCoreDocument; pub use self::wasm_did_url::WasmDIDUrl; +pub use did_jwk::*; pub use self::jws_verification_options::*; diff --git a/bindings/wasm/src/did/wasm_core_document.rs b/bindings/wasm/src/did/wasm_core_document.rs index 0fe08e6675..2a7d896ac8 100644 --- a/bindings/wasm/src/did/wasm_core_document.rs +++ b/bindings/wasm/src/did/wasm_core_document.rs @@ -24,6 +24,7 @@ use crate::credential::WasmJwt; use crate::credential::WasmPresentation; use crate::did::service::WasmService; use crate::did::wasm_did_url::WasmDIDUrl; +use crate::did::WasmDIDJwk; use crate::error::Result; use crate::error::WasmResult; use crate::jose::WasmDecodedJws; @@ -765,6 +766,12 @@ impl WasmCoreDocument { }); Ok(promise.unchecked_into()) } + + /// Creates a {@link CoreDocument} from the given {@link DIDJwk}. + #[wasm_bindgen(js_name = expandDIDJwk)] + pub fn expand_did_jwk(did: WasmDIDJwk) -> Result { + CoreDocument::expand_did_jwk(did.0).wasm_result().map(Self::from) + } } #[wasm_bindgen] diff --git a/identity_did/Cargo.toml b/identity_did/Cargo.toml index 5b4e85069c..18b32330ca 100644 --- a/identity_did/Cargo.toml +++ b/identity_did/Cargo.toml @@ -14,6 +14,7 @@ description = "Agnostic implementation of the Decentralized Identifiers (DID) st 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.3.1", path = "../identity_core" } +identity_jose = { version = "=1.3.1", path = "../identity_jose" } serde.workspace = true strum.workspace = true thiserror.workspace = true diff --git a/identity_did/src/did_jwk.rs b/identity_did/src/did_jwk.rs new file mode 100644 index 0000000000..5ebd61021c --- /dev/null +++ b/identity_did/src/did_jwk.rs @@ -0,0 +1,123 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use std::fmt::Debug; +use std::fmt::Display; +use std::str::FromStr; + +use identity_jose::jwk::Jwk; +use identity_jose::jwu::decode_b64_json; + +use crate::CoreDID; +use crate::Error; +use crate::DID; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize)] +#[repr(transparent)] +#[serde(into = "CoreDID", try_from = "CoreDID")] +/// A type representing a `did:jwk` DID. +pub struct DIDJwk(CoreDID); + +impl DIDJwk { + /// [`DIDJwk`]'s method. + pub const METHOD: &'static str = "jwk"; + + /// Tries to parse a [`DIDJwk`] from a string. + pub fn parse(s: &str) -> Result { + s.parse() + } + + /// Returns the JWK encoded inside this did:jwk. + pub fn jwk(&self) -> Jwk { + decode_b64_json(self.method_id()).expect("did:jwk encodes a valid JWK") + } +} + +impl AsRef for DIDJwk { + fn as_ref(&self) -> &CoreDID { + &self.0 + } +} + +impl From for CoreDID { + fn from(value: DIDJwk) -> Self { + value.0 + } +} + +impl<'a> TryFrom<&'a str> for DIDJwk { + type Error = Error; + fn try_from(value: &'a str) -> Result { + value.parse() + } +} + +impl Display for DIDJwk { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl FromStr for DIDJwk { + type Err = Error; + fn from_str(s: &str) -> Result { + s.parse::().and_then(TryFrom::try_from) + } +} + +impl From for String { + fn from(value: DIDJwk) -> Self { + value.to_string() + } +} + +impl TryFrom for DIDJwk { + type Error = Error; + fn try_from(value: CoreDID) -> Result { + let Self::METHOD = value.method() else { + return Err(Error::InvalidMethodName); + }; + decode_b64_json::(value.method_id()) + .map(|_| Self(value)) + .map_err(|_| Error::InvalidMethodId) + } +} + +#[cfg(test)] +mod tests { + use identity_core::convert::FromJson; + + use super::*; + + #[test] + fn test_valid_deserialization() -> Result<(), Error> { + "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9".parse::()?; + "did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImFjYklRaXVNczNpOF91c3pFakoydHBUdFJNNEVVM3l6OTFQSDZDZEgyVjAiLCJ5IjoiX0tjeUxqOXZXTXB0bm1LdG00NkdxRHo4d2Y3NEk1TEtncmwyR3pIM25TRSJ9".parse::()?; + + Ok(()) + } + + #[test] + fn test_jwk() { + let did = DIDJwk::parse("did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9").unwrap(); + let target_jwk = Jwk::from_json_value(serde_json::json!({ + "kty":"OKP","crv":"X25519","use":"enc","x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08" + })) + .unwrap(); + + assert_eq!(did.jwk(), target_jwk); + } + + #[test] + fn test_invalid_deserialization() { + assert!( + "did:iota:0xf4d6f08f5a1b80dd578da7dc1b49c886d580acd4cf7d48119dfeb82b538ad88a" + .parse::() + .is_err() + ); + assert!("did:jwk:".parse::().is_err()); + assert!("did:jwk:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + .parse::() + .is_err()); + } +} diff --git a/identity_did/src/lib.rs b/identity_did/src/lib.rs index 9289419211..62c846847e 100644 --- a/identity_did/src/lib.rs +++ b/identity_did/src/lib.rs @@ -18,6 +18,7 @@ #[allow(clippy::module_inception)] mod did; +mod did_jwk; mod did_url; mod error; @@ -26,4 +27,5 @@ pub use crate::did_url::RelativeDIDUrl; pub use ::did_url_parser::DID as BaseDIDUrl; pub use did::CoreDID; pub use did::DID; +pub use did_jwk::*; pub use error::Error; diff --git a/identity_document/src/document/core_document.rs b/identity_document/src/document/core_document.rs index 2f6bcd593f..2747f7fae6 100644 --- a/identity_document/src/document/core_document.rs +++ b/identity_document/src/document/core_document.rs @@ -7,6 +7,7 @@ use core::fmt::Formatter; use std::collections::HashMap; use std::convert::Infallible; +use identity_did::DIDJwk; use identity_verification::jose::jwk::Jwk; use identity_verification::jose::jws::DecodedJws; use identity_verification::jose::jws::Decoder; @@ -984,6 +985,23 @@ impl CoreDocument { } } +impl CoreDocument { + /// Creates a [`CoreDocument`] from a did:jwk DID. + pub fn expand_did_jwk(did_jwk: DIDJwk) -> Result { + let verification_method = VerificationMethod::try_from(did_jwk.clone()).map_err(Error::InvalidKeyMaterial)?; + let verification_method_id = verification_method.id().clone(); + + DocumentBuilder::default() + .id(did_jwk.into()) + .verification_method(verification_method) + .assertion_method(verification_method_id.clone()) + .authentication(verification_method_id.clone()) + .capability_invocation(verification_method_id.clone()) + .capability_delegation(verification_method_id.clone()) + .build() + } +} + #[cfg(test)] mod tests { use identity_core::convert::FromJson; @@ -1682,4 +1700,33 @@ mod tests { verifier(json); } } + + #[test] + fn test_did_jwk_expansion() { + let did_jwk = "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9" + .parse::() + .unwrap(); + let target_doc = serde_json::from_value(serde_json::json!({ + "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9", + "verificationMethod": [ + { + "id": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0", + "type": "JsonWebKey2020", + "controller": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9", + "publicKeyJwk": { + "kty":"OKP", + "crv":"X25519", + "use":"enc", + "x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08" + } + } + ], + "assertionMethod": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"], + "authentication": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"], + "capabilityInvocation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"], + "capabilityDelegation": ["did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9#0"] + })).unwrap(); + + assert_eq!(CoreDocument::expand_did_jwk(did_jwk).unwrap(), target_doc); + } } diff --git a/identity_iota_core/src/document/iota_document.rs b/identity_iota_core/src/document/iota_document.rs index 7ae60381d7..bd3404045c 100644 --- a/identity_iota_core/src/document/iota_document.rs +++ b/identity_iota_core/src/document/iota_document.rs @@ -555,6 +555,15 @@ impl From for CoreDocument { } } +impl From for IotaDocument { + fn from(value: CoreDocument) -> Self { + IotaDocument { + document: value, + metadata: IotaDocumentMetadata::default(), + } + } +} + impl TryFrom<(CoreDocument, IotaDocumentMetadata)> for IotaDocument { type Error = Error; /// Converts the tuple into an [`IotaDocument`] if the given [`CoreDocument`] has an identifier satisfying the diff --git a/identity_resolver/src/resolution/resolver.rs b/identity_resolver/src/resolution/resolver.rs index eff86351be..228a65582b 100644 --- a/identity_resolver/src/resolution/resolver.rs +++ b/identity_resolver/src/resolution/resolver.rs @@ -4,6 +4,7 @@ use core::future::Future; use futures::stream::FuturesUnordered; use futures::TryStreamExt; +use identity_did::DIDJwk; use identity_did::DID; use std::collections::HashSet; @@ -247,6 +248,22 @@ impl Resolver> { } } +impl + 'static> Resolver> { + /// Attaches a handler capable of resolving `did:jwk` DIDs. + pub fn attach_did_jwk_handler(&mut self) { + let handler = |did_jwk: DIDJwk| async move { CoreDocument::expand_did_jwk(did_jwk) }; + self.attach_handler(DIDJwk::METHOD.to_string(), handler) + } +} + +impl + 'static> Resolver> { + /// Attaches a handler capable of resolving `did:jwk` DIDs. + pub fn attach_did_jwk_handler(&mut self) { + let handler = |did_jwk: DIDJwk| async move { CoreDocument::expand_did_jwk(did_jwk) }; + self.attach_handler(DIDJwk::METHOD.to_string(), handler) + } +} + #[cfg(feature = "iota")] mod iota_handler { use crate::ErrorCause; @@ -414,4 +431,15 @@ mod tests { let doc = resolver.resolve(&did2).await.unwrap(); assert_eq!(doc.id(), &did2); } + + #[tokio::test] + async fn test_did_jwk_resolution() { + let mut resolver = Resolver::::new(); + resolver.attach_did_jwk_handler(); + + let did_jwk = "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJYMjU1MTkiLCJ1c2UiOiJlbmMiLCJ4IjoiM3A3YmZYdDl3YlRUVzJIQzdPUTFOei1EUThoYmVHZE5yZngtRkctSUswOCJ9".parse::().unwrap(); + + let doc = resolver.resolve(&did_jwk).await.unwrap(); + assert_eq!(doc.id(), did_jwk.as_ref()); + } } diff --git a/identity_verification/src/verification_method/method.rs b/identity_verification/src/verification_method/method.rs index 65c838639f..084956c3a9 100644 --- a/identity_verification/src/verification_method/method.rs +++ b/identity_verification/src/verification_method/method.rs @@ -5,6 +5,7 @@ use core::fmt::Display; use core::fmt::Formatter; use std::borrow::Cow; +use identity_did::DIDJwk; use identity_jose::jwk::Jwk; use serde::de; use serde::Deserialize; @@ -247,6 +248,14 @@ impl KeyComparable for VerificationMethod { } } +impl TryFrom for VerificationMethod { + type Error = Error; + fn try_from(did: DIDJwk) -> Result { + let jwk = did.jwk(); + Self::new_from_jwk(did, jwk, Some("0")) + } +} + // Horrible workaround for a tracked serde issue https://github.com/serde-rs/serde/issues/2200. Serde doesn't "consume" // the input when deserializing flattened enums (MethodData in this case) causing duplication of data (in this case // it ends up in the properties object). This workaround simply removes the duplication. From deecc7ec76bda4aa5c92fe1b502799662d1fbc73 Mon Sep 17 00:00:00 2001 From: Daniel Mader Date: Thu, 5 Sep 2024 11:47:12 +0200 Subject: [PATCH 19/22] Linked Verifiable Presentations (#1398) * feat: implement `Service` for Linked Verifiable Presentations * feat: add example for Linked Verifiable Presentations * cargo clippy, fmt, code * cargo clippy + fmt * fix linked vp example * wasm bindings * Update bindings/wasm/src/credential/linked_verifiable_presentation_service.rs Co-authored-by: wulfraem * cargo fmt --------- Co-authored-by: Enrico Marconi Co-authored-by: Enrico Marconi <31142849+UMR1352@users.noreply.github.com> Co-authored-by: wulfraem --- .../linked_verifiable_presentation_service.rs | 109 +++++++++ bindings/wasm/src/credential/mod.rs | 2 + .../11_linked_verifiable_presentation.rs | 195 +++++++++++++++++ examples/Cargo.toml | 6 +- examples/README.md | 26 +-- .../linked_verifiable_presentation_service.rs | 207 ++++++++++++++++++ identity_credential/src/credential/mod.rs | 2 + identity_credential/src/error.rs | 3 + 8 files changed, 536 insertions(+), 14 deletions(-) create mode 100644 bindings/wasm/src/credential/linked_verifiable_presentation_service.rs create mode 100644 examples/1_advanced/11_linked_verifiable_presentation.rs create mode 100644 identity_credential/src/credential/linked_verifiable_presentation_service.rs diff --git a/bindings/wasm/src/credential/linked_verifiable_presentation_service.rs b/bindings/wasm/src/credential/linked_verifiable_presentation_service.rs new file mode 100644 index 0000000000..1033316cc7 --- /dev/null +++ b/bindings/wasm/src/credential/linked_verifiable_presentation_service.rs @@ -0,0 +1,109 @@ +// Copyright 2020-2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use crate::common::ArrayString; +use crate::did::WasmService; +use crate::error::Result; +use crate::error::WasmResult; +use identity_iota::core::Object; +use identity_iota::core::OneOrSet; +use identity_iota::core::Url; +use identity_iota::credential::LinkedVerifiablePresentationService; +use identity_iota::did::DIDUrl; +use identity_iota::document::Service; +use proc_typescript::typescript; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; + +#[wasm_bindgen(js_name = LinkedVerifiablePresentationService, inspectable)] +pub struct WasmLinkedVerifiablePresentationService(LinkedVerifiablePresentationService); + +/// A service wrapper for a [Linked Verifiable Presentation Service Endpoint](https://identity.foundation/linked-vp/#linked-verifiable-presentation-service-endpoint). +#[wasm_bindgen(js_class = LinkedVerifiablePresentationService)] +impl WasmLinkedVerifiablePresentationService { + /// Constructs a new {@link LinkedVerifiablePresentationService} that wraps a spec compliant [Linked Verifiable Presentation Service Endpoint](https://identity.foundation/linked-vp/#linked-verifiable-presentation-service-endpoint). + #[wasm_bindgen(constructor)] + pub fn new(options: ILinkedVerifiablePresentationService) -> Result { + let ILinkedVerifiablePresentationServiceHelper { + id, + linked_vp, + properties, + } = options + .into_serde::() + .wasm_result()?; + Ok(Self( + LinkedVerifiablePresentationService::new(id, linked_vp, properties).wasm_result()?, + )) + } + + /// Returns the domains contained in the Linked Verifiable Presentation Service. + #[wasm_bindgen(js_name = verifiablePresentationUrls)] + pub fn vp_urls(&self) -> ArrayString { + self + .0 + .verifiable_presentation_urls() + .iter() + .map(|url| url.to_string()) + .map(JsValue::from) + .collect::() + .unchecked_into::() + } + + /// Returns the inner service which can be added to a DID Document. + #[wasm_bindgen(js_name = toService)] + pub fn to_service(&self) -> WasmService { + let service: Service = self.0.clone().into(); + WasmService(service) + } + + /// Creates a new {@link LinkedVerifiablePresentationService} from a {@link Service}. + /// + /// # Error + /// + /// Errors if `service` is not a valid Linked Verifiable Presentation Service. + #[wasm_bindgen(js_name = fromService)] + pub fn from_service(service: &WasmService) -> Result { + Ok(Self( + LinkedVerifiablePresentationService::try_from(service.0.clone()).wasm_result()?, + )) + } + + /// Returns `true` if a {@link Service} is a valid Linked Verifiable Presentation Service. + #[wasm_bindgen(js_name = isValid)] + pub fn is_valid(service: &WasmService) -> bool { + LinkedVerifiablePresentationService::check_structure(&service.0).is_ok() + } +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "ILinkedVerifiablePresentationService")] + pub type ILinkedVerifiablePresentationService; +} + +/// Fields for constructing a new {@link LinkedVerifiablePresentationService}. +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +#[typescript(name = "ILinkedVerifiablePresentationService", readonly, optional)] +struct ILinkedVerifiablePresentationServiceHelper { + /// Service id. + #[typescript(optional = false, type = "DIDUrl")] + id: DIDUrl, + /// A unique URI that may be used to identify the {@link Credential}. + #[typescript(optional = false, type = "string | string[]")] + linked_vp: OneOrSet, + /// Miscellaneous properties. + #[serde(flatten)] + #[typescript(optional = false, name = "[properties: string]", type = "unknown")] + properties: Object, +} + +impl_wasm_clone!( + WasmLinkedVerifiablePresentationService, + LinkedVerifiablePresentationService +); +impl_wasm_json!( + WasmLinkedVerifiablePresentationService, + LinkedVerifiablePresentationService +); diff --git a/bindings/wasm/src/credential/mod.rs b/bindings/wasm/src/credential/mod.rs index 033a8cefd6..408f302f11 100644 --- a/bindings/wasm/src/credential/mod.rs +++ b/bindings/wasm/src/credential/mod.rs @@ -13,6 +13,7 @@ pub use self::jws::WasmJws; pub use self::jwt::WasmJwt; pub use self::jwt_credential_validation::*; pub use self::jwt_presentation_validation::*; +pub use self::linked_verifiable_presentation_service::*; pub use self::options::WasmFailFast; pub use self::options::WasmSubjectHolderRelationship; pub use self::presentation::*; @@ -33,6 +34,7 @@ mod jwt; mod jwt_credential_validation; mod jwt_presentation_validation; mod linked_domain_service; +mod linked_verifiable_presentation_service; mod options; mod presentation; mod proof; diff --git a/examples/1_advanced/11_linked_verifiable_presentation.rs b/examples/1_advanced/11_linked_verifiable_presentation.rs new file mode 100644 index 0000000000..550bad3d41 --- /dev/null +++ b/examples/1_advanced/11_linked_verifiable_presentation.rs @@ -0,0 +1,195 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Context; +use examples::create_did; +use examples::random_stronghold_path; +use examples::MemStorage; +use examples::API_ENDPOINT; +use identity_eddsa_verifier::EdDSAJwsVerifier; +use identity_iota::core::FromJson; +use identity_iota::core::Object; +use identity_iota::core::OrderedSet; +use identity_iota::core::Url; +use identity_iota::credential::CompoundJwtPresentationValidationError; +use identity_iota::credential::CredentialBuilder; +use identity_iota::credential::DecodedJwtPresentation; +use identity_iota::credential::Jwt; +use identity_iota::credential::JwtPresentationOptions; +use identity_iota::credential::JwtPresentationValidationOptions; +use identity_iota::credential::JwtPresentationValidator; +use identity_iota::credential::JwtPresentationValidatorUtils; +use identity_iota::credential::LinkedVerifiablePresentationService; +use identity_iota::credential::PresentationBuilder; +use identity_iota::credential::Subject; +use identity_iota::did::CoreDID; +use identity_iota::did::DIDUrl; +use identity_iota::did::DID; +use identity_iota::document::verifiable::JwsVerificationOptions; +use identity_iota::iota::IotaClientExt; +use identity_iota::iota::IotaDID; +use identity_iota::iota::IotaDocument; +use identity_iota::iota::IotaIdentityClientExt; +use identity_iota::resolver::Resolver; +use identity_iota::storage::JwkDocumentExt; +use identity_iota::storage::JwkMemStore; +use identity_iota::storage::JwsSignatureOptions; +use identity_iota::storage::KeyIdMemstore; +use iota_sdk::client::secret::stronghold::StrongholdSecretManager; +use iota_sdk::client::secret::SecretManager; +use iota_sdk::client::Client; +use iota_sdk::client::Password; +use iota_sdk::types::block::address::Address; +use iota_sdk::types::block::output::AliasOutput; +use iota_sdk::types::block::output::AliasOutputBuilder; +use iota_sdk::types::block::output::RentStructure; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // Create a new client to interact with the IOTA ledger. + let client: Client = Client::builder() + .with_primary_node(API_ENDPOINT, None)? + .finish() + .await?; + let stronghold_path = random_stronghold_path(); + + println!("Using stronghold path: {stronghold_path:?}"); + // Create a new secret manager backed by a Stronghold. + let mut secret_manager: SecretManager = SecretManager::Stronghold( + StrongholdSecretManager::builder() + .password(Password::from("secure_password".to_owned())) + .build(stronghold_path)?, + ); + + // Create a DID for the entity that will be the holder of the Verifiable Presentation. + let storage: MemStorage = MemStorage::new(JwkMemStore::new(), KeyIdMemstore::new()); + let (_, mut did_document, fragment): (Address, IotaDocument, String) = + create_did(&client, &mut secret_manager, &storage).await?; + let did: IotaDID = did_document.id().clone(); + + // ===================================================== + // Create Linked Verifiable Presentation service + // ===================================================== + + // The DID should link to the following VPs. + let verifiable_presentation_url_1: Url = Url::parse("https://foo.example.com/verifiable-presentation.jwt")?; + let verifiable_presentation_url_2: Url = Url::parse("https://bar.example.com/verifiable-presentation.jsonld")?; + + let mut verifiable_presentation_urls: OrderedSet = OrderedSet::new(); + verifiable_presentation_urls.append(verifiable_presentation_url_1.clone()); + verifiable_presentation_urls.append(verifiable_presentation_url_2.clone()); + + // Create a Linked Verifiable Presentation Service to enable the discovery of the linked VPs through the DID Document. + // This is optional since it is not a hard requirement by the specs. + let service_url: DIDUrl = did.clone().join("#linked-vp")?; + let linked_verifiable_presentation_service = + LinkedVerifiablePresentationService::new(service_url, verifiable_presentation_urls, Object::new())?; + did_document.insert_service(linked_verifiable_presentation_service.into())?; + let updated_did_document: IotaDocument = publish_document(client.clone(), secret_manager, did_document).await?; + + println!("DID document with linked verifiable presentation service: {updated_did_document:#}"); + + // ===================================================== + // Verification + // ===================================================== + + // Init a resolver for resolving DID Documents. + let mut resolver: Resolver = Resolver::new(); + resolver.attach_iota_handler(client.clone()); + + // Resolve the DID Document of the DID that issued the credential. + let did_document: IotaDocument = resolver.resolve(&did).await?; + + // Get the Linked Verifiable Presentation Services from the DID Document. + let linked_verifiable_presentation_services: Vec = did_document + .service() + .iter() + .cloned() + .filter_map(|service| LinkedVerifiablePresentationService::try_from(service).ok()) + .collect(); + assert_eq!(linked_verifiable_presentation_services.len(), 1); + + // Get the VPs included in the service. + let _verifiable_presentation_urls: &[Url] = linked_verifiable_presentation_services + .first() + .ok_or_else(|| anyhow::anyhow!("expected verifiable presentation urls"))? + .verifiable_presentation_urls(); + + // Fetch the verifiable presentation from the URL (for example using `reqwest`). + // But since the URLs do not point to actual online resource, we will simply create an example JWT. + let presentation_jwt: Jwt = make_vp_jwt(&did_document, &storage, &fragment).await?; + + // Resolve the holder's document. + let holder_did: CoreDID = JwtPresentationValidatorUtils::extract_holder(&presentation_jwt)?; + let holder: IotaDocument = resolver.resolve(&holder_did).await?; + + // Validate linked presentation. Note that this doesn't validate the included credentials. + let presentation_verifier_options: JwsVerificationOptions = JwsVerificationOptions::default(); + let presentation_validation_options = + JwtPresentationValidationOptions::default().presentation_verifier_options(presentation_verifier_options); + let validation_result: Result, CompoundJwtPresentationValidationError> = + JwtPresentationValidator::with_signature_verifier(EdDSAJwsVerifier::default()).validate( + &presentation_jwt, + &holder, + &presentation_validation_options, + ); + + assert!(validation_result.is_ok()); + + Ok(()) +} + +async fn publish_document( + client: Client, + secret_manager: SecretManager, + document: IotaDocument, +) -> anyhow::Result { + // Resolve the latest output and update it with the given document. + let alias_output: AliasOutput = client.update_did_output(document.clone()).await?; + + // Because the size of the DID document increased, we have to increase the allocated storage deposit. + // This increases the deposit amount to the new minimum. + let rent_structure: RentStructure = client.get_rent_structure().await?; + let alias_output: AliasOutput = AliasOutputBuilder::from(&alias_output) + .with_minimum_storage_deposit(rent_structure) + .finish()?; + + // Publish the updated Alias Output. + Ok(client.publish_did_output(&secret_manager, alias_output).await?) +} + +async fn make_vp_jwt(did_doc: &IotaDocument, storage: &MemStorage, fragment: &str) -> anyhow::Result { + // first we create a credential encoding it as jwt + let credential = CredentialBuilder::new(Object::default()) + .id(Url::parse("https://example.edu/credentials/3732")?) + .issuer(Url::parse(did_doc.id().as_str())?) + .type_("UniversityDegreeCredential") + .subject(Subject::from_json_value(serde_json::json!({ + "id": did_doc.id().as_str(), + "name": "Alice", + "degree": { + "type": "BachelorDegree", + "name": "Bachelor of Science and Arts", + }, + "GPA": "4.0", + }))?) + .build()?; + let credential = did_doc + .create_credential_jwt(&credential, storage, fragment, &JwsSignatureOptions::default(), None) + .await?; + // then we create a presentation including the just created JWT encoded credential. + let presentation = PresentationBuilder::new(Url::parse(did_doc.id().as_str())?, Object::default()) + .credential(credential) + .build()?; + // we encode the presentation as JWT + did_doc + .create_presentation_jwt( + &presentation, + storage, + fragment, + &JwsSignatureOptions::default(), + &JwtPresentationOptions::default(), + ) + .await + .context("jwt presentation failed") +} diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 9fe5984123..9866115ad3 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -9,7 +9,7 @@ publish = false anyhow = "1.0.62" bls12_381_plus.workspace = true identity_eddsa_verifier = { path = "../identity_eddsa_verifier", default-features = false } -identity_iota = { path = "../identity_iota", default-features = false, features = ["iota-client", "client", "memstore", "domain-linkage", "revocation-bitmap", "status-list-2021", "jpt-bbs-plus"] } +identity_iota = { path = "../identity_iota", default-features = false, features = ["iota-client", "client", "memstore", "domain-linkage", "revocation-bitmap", "status-list-2021", "jpt-bbs-plus", "resolver"] } identity_stronghold = { path = "../identity_stronghold", default-features = false, features = ["bbs-plus"] } iota-sdk = { version = "1.0", default-features = false, features = ["tls", "client", "stronghold"] } json-proof-token.workspace = true @@ -101,3 +101,7 @@ name = "9_zkp" [[example]] path = "1_advanced/10_zkp_revocation.rs" name = "10_zkp_revocation" + +[[example]] +path = "1_advanced/11_linked_verifiable_presentation.rs" +name = "11_linked_verifiable_presentation" diff --git a/examples/README.md b/examples/README.md index 2076f8b4b2..8ea9ab2145 100644 --- a/examples/README.md +++ b/examples/README.md @@ -18,13 +18,12 @@ cargo run --release --example 0_create_did ### Note: Running the examples with the release flag will be significantly faster due to stronghold performance issues in debug mode. - ## Basic Examples The following basic CRUD (Create, Read, Update, Delete) examples are available: | Name | Information | -|:--------------------------------------------------|:-------------------------------------------------------------------------------------| +| :------------------------------------------------ | :----------------------------------------------------------------------------------- | | [0_create_did](./0_basic/0_create_did.rs) | Demonstrates how to create a DID Document and publish it in a new Alias Output. | | [1_update_did](./0_basic/1_update_did.rs) | Demonstrates how to update a DID document in an existing Alias Output. | | [2_resolve_did](./0_basic/2_resolve_did.rs) | Demonstrates how to resolve an existing DID in an Alias Output. | @@ -38,14 +37,15 @@ The following basic CRUD (Create, Read, Update, Delete) examples are available: The following advanced examples are available: -| Name | Information | -|:-----------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------| -| [0_did_controls_did](./1_advanced/0_did_controls_did.rs) | Demonstrates how an identity can control another identity. | -| [1_did_issues_nft](./1_advanced/1_did_issues_nft.rs) | Demonstrates how an identity can issue and own NFTs, and how observers can verify the issuer of the NFT. | -| [2_nft_owns_did](./1_advanced/2_nft_owns_did.rs) | Demonstrates how an identity can be owned by NFTs, and how observers can verify that relationship. | -| [3_did_issues_tokens](./1_advanced/3_did_issues_tokens.rs) | Demonstrates how an identity can issue and control a Token Foundry and its tokens. | -| [4_alias_output_history](./1_advanced/4_alias_output_history.rs) | Demonstrates fetching the history of an Alias Output. | -| [5_custom_resolution](./1_advanced/5_custom_resolution.rs) | Demonstrates how to set up a resolver using custom handlers. | -| [6_domain_linkage](./1_advanced/6_domain_linkage) | Demonstrates how to link a domain and a DID and verify the linkage. | -| [7_sd_jwt](./1_advanced/7_sd_jwt) | Demonstrates how to create and verify selective disclosure verifiable credentials. | -| [8_status_list_2021](./1_advanced/8_status_list_2021.rs) | Demonstrates how to revoke a credential using `StatusList2021`. | +| Name | Information | +| :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- | +| [0_did_controls_did](./1_advanced/0_did_controls_did.rs) | Demonstrates how an identity can control another identity. | +| [1_did_issues_nft](./1_advanced/1_did_issues_nft.rs) | Demonstrates how an identity can issue and own NFTs, and how observers can verify the issuer of the NFT. | +| [2_nft_owns_did](./1_advanced/2_nft_owns_did.rs) | Demonstrates how an identity can be owned by NFTs, and how observers can verify that relationship. | +| [3_did_issues_tokens](./1_advanced/3_did_issues_tokens.rs) | Demonstrates how an identity can issue and control a Token Foundry and its tokens. | +| [4_alias_output_history](./1_advanced/4_alias_output_history.rs) | Demonstrates fetching the history of an Alias Output. | +| [5_custom_resolution](./1_advanced/5_custom_resolution.rs) | Demonstrates how to set up a resolver using custom handlers. | +| [6_domain_linkage](./1_advanced/6_domain_linkage) | Demonstrates how to link a domain and a DID and verify the linkage. | +| [7_sd_jwt](./1_advanced/7_sd_jwt) | Demonstrates how to create and verify selective disclosure verifiable credentials. | +| [8_status_list_2021](./1_advanced/8_status_list_2021.rs) | Demonstrates how to revoke a credential using `StatusList2021`. | +| [11_linked_verifiable_presentation](./1_advanced/11_linked_verifiable_presentation.rs) | Demonstrates how to link a public Verifiable Presentation to an identity and how it can be verified. | diff --git a/identity_credential/src/credential/linked_verifiable_presentation_service.rs b/identity_credential/src/credential/linked_verifiable_presentation_service.rs new file mode 100644 index 0000000000..20e34e0a97 --- /dev/null +++ b/identity_credential/src/credential/linked_verifiable_presentation_service.rs @@ -0,0 +1,207 @@ +// Copyright 2020-2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use identity_core::common::Object; +use identity_core::common::OrderedSet; +use identity_core::common::Url; +use identity_did::DIDUrl; +use identity_document::service::Service; +use identity_document::service::ServiceBuilder; +use identity_document::service::ServiceEndpoint; +use serde::Deserialize; +use serde::Serialize; + +use crate::error::Result; +use crate::Error; +use crate::Error::LinkedVerifiablePresentationError; + +/// A service wrapper for a [Linked Verifiable Presentation Service Endpoint](https://identity.foundation/linked-vp/#linked-verifiable-presentation-service-endpoint). +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(try_from = "Service", into = "Service")] +pub struct LinkedVerifiablePresentationService(Service); + +impl TryFrom for LinkedVerifiablePresentationService { + type Error = Error; + + fn try_from(service: Service) -> std::result::Result { + LinkedVerifiablePresentationService::check_structure(&service)?; + Ok(LinkedVerifiablePresentationService(service)) + } +} + +impl From for Service { + fn from(service: LinkedVerifiablePresentationService) -> Self { + service.0 + } +} + +impl LinkedVerifiablePresentationService { + pub(crate) fn linked_verifiable_presentation_service_type() -> &'static str { + "LinkedVerifiablePresentation" + } + + /// Constructs a new `LinkedVerifiablePresentationService` that wraps a spec compliant + /// [Linked Verifiable Presentation Service Endpoint](https://identity.foundation/linked-vp/#linked-verifiable-presentation-service-endpoint). + pub fn new( + did_url: DIDUrl, + verifiable_presentation_urls: impl Into>, + properties: Object, + ) -> Result { + let verifiable_presentation_urls: OrderedSet = verifiable_presentation_urls.into(); + let builder: ServiceBuilder = Service::builder(properties) + .id(did_url) + .type_(Self::linked_verifiable_presentation_service_type()); + if verifiable_presentation_urls.len() == 1 { + let vp_url = verifiable_presentation_urls + .into_iter() + .next() + .expect("element 0 exists"); + let service = builder + .service_endpoint(vp_url) + .build() + .map_err(|err| LinkedVerifiablePresentationError(Box::new(err)))?; + Ok(Self(service)) + } else { + let service = builder + .service_endpoint(ServiceEndpoint::Set(verifiable_presentation_urls)) + .build() + .map_err(|err| LinkedVerifiablePresentationError(Box::new(err)))?; + Ok(Self(service)) + } + } + + /// Checks the semantic structure of a Linked Verifiable Presentation Service. + /// + /// Note: `{"type": ["LinkedVerifiablePresentation"]}` might be serialized the same way as `{"type": + /// "LinkedVerifiablePresentation"}` which passes the semantic check. + pub fn check_structure(service: &Service) -> Result<()> { + if service.type_().len() != 1 { + return Err(LinkedVerifiablePresentationError("invalid service type".into())); + } + + let service_type = service + .type_() + .get(0) + .ok_or_else(|| LinkedVerifiablePresentationError("missing service type".into()))?; + + if service_type != Self::linked_verifiable_presentation_service_type() { + return Err(LinkedVerifiablePresentationError( + format!( + "expected `{}` service type", + Self::linked_verifiable_presentation_service_type() + ) + .into(), + )); + } + + match service.service_endpoint() { + ServiceEndpoint::One(_) => Ok(()), + ServiceEndpoint::Set(_) => Ok(()), + ServiceEndpoint::Map(_) => Err(LinkedVerifiablePresentationError( + "service endpoints must be either a string or a set".into(), + )), + } + } + + /// Returns the Verifiable Presentations contained in the Linked Verifiable Presentation Service. + pub fn verifiable_presentation_urls(&self) -> &[Url] { + match self.0.service_endpoint() { + ServiceEndpoint::One(endpoint) => std::slice::from_ref(endpoint), + ServiceEndpoint::Set(endpoints) => endpoints.as_slice(), + ServiceEndpoint::Map(_) => { + unreachable!("the service endpoint is never a map per the `LinkedVerifiablePresentationService` type invariant") + } + } + } + + /// Returns a reference to the `Service` id. + pub fn id(&self) -> &DIDUrl { + self.0.id() + } +} + +#[cfg(test)] +mod tests { + use crate::credential::linked_verifiable_presentation_service::LinkedVerifiablePresentationService; + use identity_core::common::Object; + use identity_core::common::OrderedSet; + use identity_core::common::Url; + use identity_core::convert::FromJson; + use identity_did::DIDUrl; + use identity_document::service::Service; + use serde_json::json; + + #[test] + fn test_create_service_single_vp() { + let mut linked_vps: OrderedSet = OrderedSet::new(); + linked_vps.append(Url::parse("https://foo.example-1.com").unwrap()); + + let service: LinkedVerifiablePresentationService = LinkedVerifiablePresentationService::new( + DIDUrl::parse("did:example:123#foo").unwrap(), + linked_vps, + Object::new(), + ) + .unwrap(); + + let service_from_json: Service = Service::from_json_value(json!({ + "id": "did:example:123#foo", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": "https://foo.example-1.com" + })) + .unwrap(); + assert_eq!(Service::from(service), service_from_json); + } + + #[test] + fn test_create_service_multiple_vps() { + let url_1 = "https://foo.example-1.com"; + let url_2 = "https://bar.example-2.com"; + let mut linked_vps = OrderedSet::new(); + linked_vps.append(Url::parse(url_1).unwrap()); + linked_vps.append(Url::parse(url_2).unwrap()); + + let service: LinkedVerifiablePresentationService = LinkedVerifiablePresentationService::new( + DIDUrl::parse("did:example:123#foo").unwrap(), + linked_vps, + Object::new(), + ) + .unwrap(); + + let service_from_json: Service = Service::from_json_value(json!({ + "id":"did:example:123#foo", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": [url_1, url_2] + })) + .unwrap(); + assert_eq!(Service::from(service), service_from_json); + } + + #[test] + fn test_valid_single_vp() { + let service: Service = Service::from_json_value(json!({ + "id": "did:example:123#foo", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": "https://foo.example-1.com" + })) + .unwrap(); + let service: LinkedVerifiablePresentationService = LinkedVerifiablePresentationService::try_from(service).unwrap(); + let linked_vps: Vec = vec![Url::parse("https://foo.example-1.com").unwrap()]; + assert_eq!(service.verifiable_presentation_urls(), linked_vps); + } + + #[test] + fn test_valid_multiple_vps() { + let service: Service = Service::from_json_value(json!({ + "id": "did:example:123#foo", + "type": "LinkedVerifiablePresentation", + "serviceEndpoint": ["https://foo.example-1.com", "https://foo.example-2.com"] + })) + .unwrap(); + let service: LinkedVerifiablePresentationService = LinkedVerifiablePresentationService::try_from(service).unwrap(); + let linked_vps: Vec = vec![ + Url::parse("https://foo.example-1.com").unwrap(), + Url::parse("https://foo.example-2.com").unwrap(), + ]; + assert_eq!(service.verifiable_presentation_urls(), linked_vps); + } +} diff --git a/identity_credential/src/credential/mod.rs b/identity_credential/src/credential/mod.rs index 72f3b5d7a8..07b15f4eba 100644 --- a/identity_credential/src/credential/mod.rs +++ b/identity_credential/src/credential/mod.rs @@ -17,6 +17,7 @@ mod jws; mod jwt; mod jwt_serialization; mod linked_domain_service; +mod linked_verifiable_presentation_service; mod policy; mod proof; mod refresh; @@ -37,6 +38,7 @@ pub use self::jwp_credential_options::JwpCredentialOptions; pub use self::jws::Jws; pub use self::jwt::Jwt; pub use self::linked_domain_service::LinkedDomainService; +pub use self::linked_verifiable_presentation_service::LinkedVerifiablePresentationService; pub use self::policy::Policy; pub use self::proof::Proof; pub use self::refresh::RefreshService; diff --git a/identity_credential/src/error.rs b/identity_credential/src/error.rs index 468370e460..1c814c3899 100644 --- a/identity_credential/src/error.rs +++ b/identity_credential/src/error.rs @@ -37,6 +37,9 @@ pub enum Error { /// Caused when constructing an invalid `LinkedDomainService` or `DomainLinkageConfiguration`. #[error("domain linkage error: {0}")] DomainLinkageError(#[source] Box), + /// Caused when constructing an invalid `LinkedVerifiablePresentationService`. + #[error("linked verifiable presentation error: {0}")] + LinkedVerifiablePresentationError(#[source] Box), /// Caused when attempting to encode a `Credential` containing multiple subjects as a JWT. #[error("could not create JWT claim set from verifiable credential: more than one subject")] MoreThanOneSubjectInJwt, From ba36609f395a49f3c496db7c8a2f7e3981df8bad Mon Sep 17 00:00:00 2001 From: Enrico Marconi <31142849+UMR1352@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:11:55 +0200 Subject: [PATCH 20/22] Add WASM bindings for EcDSA JWS Verifier (#1396) * wasm bindings for ecdsa verifier * make signature verifier optional, defaulting to a compound verifier * update comments on new default wasm jws verifier * cargo fmt * dprint fmt --- bindings/wasm/Cargo.toml | 1 + bindings/wasm/docs/api-reference.md | 288 ++++++++++-------- .../credential/domain_linkage_validator.rs | 6 +- .../jwt_credential_validator.rs | 6 +- .../sd_jwt_validator.rs | 6 +- .../jwt_presentation_validator.rs | 6 +- bindings/wasm/src/did/wasm_core_document.rs | 7 +- bindings/wasm/src/iota/iota_document.rs | 7 +- .../src/verification/custom_verification.rs | 51 ++-- .../wasm/src/verification/jws_verifier.rs | 41 +++ 10 files changed, 260 insertions(+), 159 deletions(-) diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 1acaf0ce96..b3017d8dc8 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -20,6 +20,7 @@ async-trait = { version = "0.1", default-features = false } bls12_381_plus = "0.8.17" console_error_panic_hook = { version = "0.1" } futures = { version = "0.3" } +identity_ecdsa_verifier = { path = "../../identity_ecdsa_verifier", default-features = false, features = ["es256", "es256k"] } identity_eddsa_verifier = { path = "../../identity_eddsa_verifier", default-features = false, features = ["ed25519"] } js-sys = { version = "0.3.61" } json-proof-token = "0.3.4" diff --git a/bindings/wasm/docs/api-reference.md b/bindings/wasm/docs/api-reference.md index 6dd0837a69..25fdf6ba04 100644 --- a/bindings/wasm/docs/api-reference.md +++ b/bindings/wasm/docs/api-reference.md @@ -55,6 +55,10 @@ See: Duration

A span of time.

+
EcDSAJwsVerifier
+

An implementor of IJwsVerifier that can handle the +EcDSA algorithm.

+
EdDSAJwsVerifier

An implementor of IJwsVerifier that can handle the EdDSA algorithm.

@@ -255,8 +259,23 @@ working with storage backed DID documents.

## Members
-
PresentationProofAlgorithm
-
+
StatusCheck
+

Controls validation behaviour when checking whether or not a credential has been revoked by its +credentialStatus.

+
+
Strict
+

Validate the status if supported, reject any unsupported +credentialStatus types.

+

Only RevocationBitmap2022 is currently supported.

+

This is the default.

+
+
SkipUnsupported
+

Validate the status if supported, skip any unsupported +credentialStatus types.

+
+
SkipAll
+

Skip all status checks.

+
SubjectHolderRelationship

Declares how credential subjects must relate to the presentation holder.

See also the Subject-Holder Relationship section of the specification.

@@ -271,9 +290,14 @@ This variant is the default.

Any

The holder is not required to have any kind of relationship to any credential subject.

+
PresentationProofAlgorithm
+
+
StatusPurpose
+

Purpose of a StatusList2021.

+
ProofAlgorithm
-
StateMetadataEncoding
+
CredentialStatus
FailFast

Declares when validation should return if an error occurs.

@@ -284,34 +308,14 @@ This variant is the default.

FirstError

Return after the first error occurs.

-
StatusCheck
-

Controls validation behaviour when checking whether or not a credential has been revoked by its -credentialStatus.

-
-
Strict
-

Validate the status if supported, reject any unsupported -credentialStatus types.

-

Only RevocationBitmap2022 is currently supported.

-

This is the default.

-
-
SkipUnsupported
-

Validate the status if supported, skip any unsupported -credentialStatus types.

-
-
SkipAll
-

Skip all status checks.

-
+
StateMetadataEncoding
+
SerializationType
PayloadType
-
StatusPurpose
-

Purpose of a StatusList2021.

-
MethodRelationship
-
CredentialStatus
-
## Functions @@ -334,6 +338,12 @@ prior to calling the function.

start()

Initializes the console error panic hook for better error messages

+
encodeB64(data)string
+

Encode the given bytes in url-safe base64.

+
+
decodeB64(data)Uint8Array
+

Decode the given url-safe base64-encoded slice into its raw bytes.

+
@@ -557,7 +567,7 @@ if the object is being concurrently modified. * [.resolveMethod(query, [scope])](#CoreDocument+resolveMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined * [.attachMethodRelationship(didUrl, relationship)](#CoreDocument+attachMethodRelationship) ⇒ boolean * [.detachMethodRelationship(didUrl, relationship)](#CoreDocument+detachMethodRelationship) ⇒ boolean - * [.verifyJws(jws, options, signatureVerifier, [detachedPayload])](#CoreDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) + * [.verifyJws(jws, options, [signatureVerifier], [detachedPayload])](#CoreDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) * [.revokeCredentials(serviceQuery, indices)](#CoreDocument+revokeCredentials) * [.unrevokeCredentials(serviceQuery, indices)](#CoreDocument+unrevokeCredentials) * [.clone()](#CoreDocument+clone) ⇒ [CoreDocument](#CoreDocument) @@ -832,7 +842,7 @@ Detaches the given relationship from the given method, if the method exists. -### coreDocument.verifyJws(jws, options, signatureVerifier, [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) +### coreDocument.verifyJws(jws, options, [signatureVerifier], [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of verifying EdDSA signatures. @@ -849,7 +859,7 @@ or set explicitly in the `options`. | --- | --- | | jws | [Jws](#Jws) | | options | [JwsVerificationOptions](#JwsVerificationOptions) | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | | [detachedPayload] | string \| undefined | @@ -2034,6 +2044,43 @@ Deserializes an instance from a JSON object. | --- | --- | | json | any | + + +## EcDSAJwsVerifier +An implementor of `IJwsVerifier` that can handle the +`EcDSA` algorithm. + +**Kind**: global class + +* [EcDSAJwsVerifier](#EcDSAJwsVerifier) + * [new EcDSAJwsVerifier()](#new_EcDSAJwsVerifier_new) + * [.verify(alg, signingInput, decodedSignature, publicKey)](#EcDSAJwsVerifier+verify) + + + +### new EcDSAJwsVerifier() +Constructs an EcDSAJwsVerifier. + + + +### ecDSAJwsVerifier.verify(alg, signingInput, decodedSignature, publicKey) +Verify a JWS signature secured with the `EcDSA` algorithm. +Only the `ES256` and `ES256K` curves are supported for now. + +# Warning + +This function does not check the `alg` property in the protected header. Callers are expected to assert this +prior to calling the function. + +**Kind**: instance method of [EcDSAJwsVerifier](#EcDSAJwsVerifier) + +| Param | Type | +| --- | --- | +| alg | JwsAlgorithm | +| signingInput | Uint8Array | +| decodedSignature | Uint8Array | +| publicKey | [Jwk](#Jwk) | + ## EdDSAJwsVerifier @@ -2315,7 +2362,7 @@ if the object is being concurrently modified. * [.resolveMethod(query, [scope])](#IotaDocument+resolveMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined * [.attachMethodRelationship(didUrl, relationship)](#IotaDocument+attachMethodRelationship) ⇒ boolean * [.detachMethodRelationship(didUrl, relationship)](#IotaDocument+detachMethodRelationship) ⇒ boolean - * [.verifyJws(jws, options, signatureVerifier, [detachedPayload])](#IotaDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) + * [.verifyJws(jws, options, [signatureVerifier], [detachedPayload])](#IotaDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) * [.pack()](#IotaDocument+pack) ⇒ Uint8Array * [.packWithEncoding(encoding)](#IotaDocument+packWithEncoding) ⇒ Uint8Array * [.metadata()](#IotaDocument+metadata) ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) @@ -2556,7 +2603,7 @@ Detaches the given relationship from the given method, if the method exists. -### iotaDocument.verifyJws(jws, options, signatureVerifier, [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) +### iotaDocument.verifyJws(jws, options, [signatureVerifier], [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of verifying EdDSA signatures. @@ -2572,7 +2619,7 @@ take place. | --- | --- | | jws | [Jws](#Jws) | | options | [JwsVerificationOptions](#JwsVerificationOptions) | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | | [detachedPayload] | string \| undefined | @@ -4653,7 +4700,7 @@ A type for decoding and validating [Credential](#Credential). **Kind**: global class * [JwtCredentialValidator](#JwtCredentialValidator) - * [new JwtCredentialValidator(signatureVerifier)](#new_JwtCredentialValidator_new) + * [new JwtCredentialValidator([signatureVerifier])](#new_JwtCredentialValidator_new) * _instance_ * [.validate(credential_jwt, issuer, options, fail_fast)](#JwtCredentialValidator+validate) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) * [.verifySignature(credential, trustedIssuers, options)](#JwtCredentialValidator+verifySignature) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) @@ -4668,7 +4715,7 @@ A type for decoding and validating [Credential](#Credential). -### new JwtCredentialValidator(signatureVerifier) +### new JwtCredentialValidator([signatureVerifier]) Creates a new [JwtCredentialValidator](#JwtCredentialValidator). If a `signatureVerifier` is provided it will be used when verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` algorithm will be used. @@ -4676,7 +4723,7 @@ algorithm will be used. | Param | Type | | --- | --- | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | @@ -4847,21 +4894,21 @@ A validator for a Domain Linkage Configuration and Credentials. **Kind**: global class * [JwtDomainLinkageValidator](#JwtDomainLinkageValidator) - * [new JwtDomainLinkageValidator(signatureVerifier)](#new_JwtDomainLinkageValidator_new) + * [new JwtDomainLinkageValidator([signatureVerifier])](#new_JwtDomainLinkageValidator_new) * [.validateLinkage(issuer, configuration, domain, options)](#JwtDomainLinkageValidator+validateLinkage) * [.validateCredential(issuer, credentialJwt, domain, options)](#JwtDomainLinkageValidator+validateCredential) -### new JwtDomainLinkageValidator(signatureVerifier) +### new JwtDomainLinkageValidator([signatureVerifier]) Creates a new [JwtDomainLinkageValidator](#JwtDomainLinkageValidator). If a `signatureVerifier` is provided it will be used when -verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` -algorithm will be used. +verifying decoded JWS signatures, otherwise the default which is capable of handling the `EdDSA`, `ES256`, `ES256K` +algorithms will be used. | Param | Type | | --- | --- | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | @@ -5011,7 +5058,7 @@ Deserializes an instance from a JSON object. **Kind**: global class * [JwtPresentationValidator](#JwtPresentationValidator) - * [new JwtPresentationValidator(signatureVerifier)](#new_JwtPresentationValidator_new) + * [new JwtPresentationValidator([signatureVerifier])](#new_JwtPresentationValidator_new) * _instance_ * [.validate(presentationJwt, holder, validation_options)](#JwtPresentationValidator+validate) ⇒ [DecodedJwtPresentation](#DecodedJwtPresentation) * _static_ @@ -5020,7 +5067,7 @@ Deserializes an instance from a JSON object. -### new JwtPresentationValidator(signatureVerifier) +### new JwtPresentationValidator([signatureVerifier]) Creates a new [JwtPresentationValidator](#JwtPresentationValidator). If a `signatureVerifier` is provided it will be used when verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` algorithm will be used. @@ -5028,7 +5075,7 @@ algorithm will be used. | Param | Type | | --- | --- | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | @@ -6536,14 +6583,14 @@ A type for decoding and validating [Credential](#Credential). **Kind**: global class * [SdJwtCredentialValidator](#SdJwtCredentialValidator) - * [new SdJwtCredentialValidator(signatureVerifier)](#new_SdJwtCredentialValidator_new) + * [new SdJwtCredentialValidator([signatureVerifier])](#new_SdJwtCredentialValidator_new) * [.validateCredential(sd_jwt, issuer, options, fail_fast)](#SdJwtCredentialValidator+validateCredential) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) * [.verifySignature(credential, trustedIssuers, options)](#SdJwtCredentialValidator+verifySignature) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) * [.validateKeyBindingJwt(sdJwt, holder, options)](#SdJwtCredentialValidator+validateKeyBindingJwt) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) -### new SdJwtCredentialValidator(signatureVerifier) +### new SdJwtCredentialValidator([signatureVerifier]) Creates a new `SdJwtCredentialValidator`. If a `signatureVerifier` is provided it will be used when verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` algorithm will be used. @@ -6551,7 +6598,7 @@ algorithm will be used. | Param | Type | | --- | --- | -| signatureVerifier | IJwsVerifier | +| [signatureVerifier] | IJwsVerifier \| undefined | @@ -7657,9 +7704,36 @@ Deserializes an instance from a JSON object. | --- | --- | | json | any | - + + +## StatusCheck +Controls validation behaviour when checking whether or not a credential has been revoked by its +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status). + +**Kind**: global variable + + +## Strict +Validate the status if supported, reject any unsupported +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. + +Only `RevocationBitmap2022` is currently supported. + +This is the default. + +**Kind**: global variable + + +## SkipUnsupported +Validate the status if supported, skip any unsupported +[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. + +**Kind**: global variable + + +## SkipAll +Skip all status checks. -## PresentationProofAlgorithm **Kind**: global variable @@ -7668,33 +7742,42 @@ Declares how credential subjects must relate to the presentation holder. See also the [Subject-Holder Relationship](https://www.w3.org/TR/vc-data-model/#subject-holder-relationships) section of the specification. +## CredentialStatus **Kind**: global variable - + -## AlwaysSubject -The holder must always match the subject on all credentials, regardless of their [`nonTransferable`](https://www.w3.org/TR/vc-data-model/#nontransferable-property) property. -This variant is the default. +## encodeB64(data) ⇒ string +Encode the given bytes in url-safe base64. -**Kind**: global variable - +**Kind**: global function + +| Param | Type | +| --- | --- | +| data | Uint8Array | + + + +## decodeB64(data) ⇒ Uint8Array +Decode the given url-safe base64-encoded slice into its raw bytes. -## SubjectOnNonTransferable -The holder must match the subject only for credentials where the [`nonTransferable`](https://www.w3.org/TR/vc-data-model/#nontransferable-property) property is `true`. +**Kind**: global variable + +## PresentationProofAlgorithm **Kind**: global variable - + -## Any -The holder is not required to have any kind of relationship to any credential subject. +## StatusPurpose +Purpose of a [StatusList2021](#StatusList2021). **Kind**: global variable ## ProofAlgorithm **Kind**: global variable - + -## StateMetadataEncoding +## CredentialStatus **Kind**: global variable @@ -7714,36 +7797,9 @@ Return all errors that occur during validation. Return after the first error occurs. **Kind**: global variable - - -## StatusCheck -Controls validation behaviour when checking whether or not a credential has been revoked by its -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status). - -**Kind**: global variable - - -## Strict -Validate the status if supported, reject any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -Only `RevocationBitmap2022` is currently supported. - -This is the default. - -**Kind**: global variable - - -## SkipUnsupported -Validate the status if supported, skip any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -**Kind**: global variable - - -## SkipAll -Skip all status checks. + +## StateMetadataEncoding **Kind**: global variable @@ -7752,43 +7808,11 @@ Skip all status checks. ## PayloadType -**Kind**: global variable - - -## StatusPurpose -Purpose of a [StatusList2021](#StatusList2021). - **Kind**: global variable ## MethodRelationship **Kind**: global variable - - -## CredentialStatus -**Kind**: global variable - - -## encodeB64(data) ⇒ string -Encode the given bytes in url-safe base64. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| data | Uint8Array | - - - -## decodeB64(data) ⇒ Uint8Array -Decode the given url-safe base64-encoded slice into its raw bytes. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| data | Uint8Array | - ## verifyEd25519(alg, signingInput, decodedSignature, publicKey) @@ -7817,3 +7841,25 @@ prior to calling the function. Initializes the console error panic hook for better error messages **Kind**: global function + + +## encodeB64(data) ⇒ string +Encode the given bytes in url-safe base64. + +**Kind**: global function + +| Param | Type | +| --- | --- | +| data | Uint8Array | + + + +## decodeB64(data) ⇒ Uint8Array +Decode the given url-safe base64-encoded slice into its raw bytes. + +**Kind**: global function + +| Param | Type | +| --- | --- | +| data | Uint8Array | + diff --git a/bindings/wasm/src/credential/domain_linkage_validator.rs b/bindings/wasm/src/credential/domain_linkage_validator.rs index a38639d853..37674e21b7 100644 --- a/bindings/wasm/src/credential/domain_linkage_validator.rs +++ b/bindings/wasm/src/credential/domain_linkage_validator.rs @@ -24,11 +24,11 @@ pub struct WasmJwtDomainLinkageValidator { #[wasm_bindgen(js_class = JwtDomainLinkageValidator)] impl WasmJwtDomainLinkageValidator { /// Creates a new {@link JwtDomainLinkageValidator}. If a `signatureVerifier` is provided it will be used when - /// verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` - /// algorithm will be used. + /// verifying decoded JWS signatures, otherwise a default verifier capable of handling the `EdDSA`, `ES256`, `ES256K` + /// algorithms will be used. #[wasm_bindgen(constructor)] #[allow(non_snake_case)] - pub fn new(signatureVerifier: IJwsVerifier) -> WasmJwtDomainLinkageValidator { + pub fn new(signatureVerifier: Option) -> WasmJwtDomainLinkageValidator { let signature_verifier = WasmJwsVerifier::new(signatureVerifier); WasmJwtDomainLinkageValidator { validator: JwtDomainLinkageValidator::with_signature_verifier(signature_verifier), diff --git a/bindings/wasm/src/credential/jwt_credential_validation/jwt_credential_validator.rs b/bindings/wasm/src/credential/jwt_credential_validation/jwt_credential_validator.rs index 9434a6d521..b6a26c35d5 100644 --- a/bindings/wasm/src/credential/jwt_credential_validation/jwt_credential_validator.rs +++ b/bindings/wasm/src/credential/jwt_credential_validation/jwt_credential_validator.rs @@ -37,11 +37,11 @@ pub struct WasmJwtCredentialValidator(JwtCredentialValidator); #[wasm_bindgen(js_class = JwtCredentialValidator)] impl WasmJwtCredentialValidator { /// Creates a new {@link JwtCredentialValidator}. If a `signatureVerifier` is provided it will be used when - /// verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` - /// algorithm will be used. + /// verifying decoded JWS signatures, otherwise a default verifier capable of handling the `EdDSA`, `ES256`, `ES256K` + /// algorithms will be used. #[wasm_bindgen(constructor)] #[allow(non_snake_case)] - pub fn new(signatureVerifier: IJwsVerifier) -> WasmJwtCredentialValidator { + pub fn new(signatureVerifier: Option) -> WasmJwtCredentialValidator { let signature_verifier = WasmJwsVerifier::new(signatureVerifier); WasmJwtCredentialValidator(JwtCredentialValidator::with_signature_verifier(signature_verifier)) } diff --git a/bindings/wasm/src/credential/jwt_credential_validation/sd_jwt_validator.rs b/bindings/wasm/src/credential/jwt_credential_validation/sd_jwt_validator.rs index 812b25414b..a8342c9aec 100644 --- a/bindings/wasm/src/credential/jwt_credential_validation/sd_jwt_validator.rs +++ b/bindings/wasm/src/credential/jwt_credential_validation/sd_jwt_validator.rs @@ -29,11 +29,11 @@ pub struct WasmSdJwtCredentialValidator(SdJwtCredentialValidator WasmSdJwtCredentialValidator { + pub fn new(signatureVerifier: Option) -> WasmSdJwtCredentialValidator { let signature_verifier = WasmJwsVerifier::new(signatureVerifier); WasmSdJwtCredentialValidator(SdJwtCredentialValidator::with_signature_verifier( signature_verifier, diff --git a/bindings/wasm/src/credential/jwt_presentation_validation/jwt_presentation_validator.rs b/bindings/wasm/src/credential/jwt_presentation_validation/jwt_presentation_validator.rs index 40a44f916b..640f96c2ef 100644 --- a/bindings/wasm/src/credential/jwt_presentation_validation/jwt_presentation_validator.rs +++ b/bindings/wasm/src/credential/jwt_presentation_validation/jwt_presentation_validator.rs @@ -23,11 +23,11 @@ pub struct WasmJwtPresentationValidator(JwtPresentationValidator WasmJwtPresentationValidator { + pub fn new(signatureVerifier: Option) -> WasmJwtPresentationValidator { let signature_verifier = WasmJwsVerifier::new(signatureVerifier); WasmJwtPresentationValidator(JwtPresentationValidator::with_signature_verifier(signature_verifier)) } diff --git a/bindings/wasm/src/did/wasm_core_document.rs b/bindings/wasm/src/did/wasm_core_document.rs index 2a7d896ac8..fd66c4e7ca 100644 --- a/bindings/wasm/src/did/wasm_core_document.rs +++ b/bindings/wasm/src/did/wasm_core_document.rs @@ -495,8 +495,9 @@ impl WasmCoreDocument { // =========================================================================== /// Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. - /// If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of - /// verifying EdDSA signatures. + /// If a `signatureVerifier` is provided it will be used when + /// verifying decoded JWS signatures, otherwise a default verifier capable of handling the `EdDSA`, `ES256`, `ES256K` + /// algorithms will be used. /// /// Regardless of which options are passed the following conditions must be met in order for a verification attempt to /// take place. @@ -509,7 +510,7 @@ impl WasmCoreDocument { &self, jws: &WasmJws, options: &WasmJwsVerificationOptions, - signatureVerifier: IJwsVerifier, + signatureVerifier: Option, detachedPayload: Option, ) -> Result { let jws_verifier = WasmJwsVerifier::new(signatureVerifier); diff --git a/bindings/wasm/src/iota/iota_document.rs b/bindings/wasm/src/iota/iota_document.rs index 777a00e679..1747f82e6e 100644 --- a/bindings/wasm/src/iota/iota_document.rs +++ b/bindings/wasm/src/iota/iota_document.rs @@ -384,8 +384,9 @@ impl WasmIotaDocument { // =========================================================================== /// Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. - /// If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of - /// verifying EdDSA signatures. + /// If a `signatureVerifier` is provided it will be used when + /// verifying decoded JWS signatures, otherwise a default verifier capable of handling the `EdDSA`, `ES256`, `ES256K` + /// algorithms will be used. /// /// Regardless of which options are passed the following conditions must be met in order for a verification attempt to /// take place. @@ -397,7 +398,7 @@ impl WasmIotaDocument { &self, jws: &WasmJws, options: &WasmJwsVerificationOptions, - signatureVerifier: IJwsVerifier, + signatureVerifier: Option, detachedPayload: Option, ) -> Result { let jws_verifier = WasmJwsVerifier::new(signatureVerifier); diff --git a/bindings/wasm/src/verification/custom_verification.rs b/bindings/wasm/src/verification/custom_verification.rs index 4c82d8dcfe..9fe2f9e8b7 100644 --- a/bindings/wasm/src/verification/custom_verification.rs +++ b/bindings/wasm/src/verification/custom_verification.rs @@ -1,6 +1,9 @@ // Copyright 2020-2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use identity_ecdsa_verifier::EcDSAJwsVerifier; +use identity_eddsa_verifier::EdDSAJwsVerifier; +use identity_iota::verification::jws::JwsAlgorithm; use identity_iota::verification::jws::JwsVerifier; use identity_iota::verification::jws::SignatureVerificationError; use identity_iota::verification::jws::SignatureVerificationErrorKind; @@ -10,12 +13,12 @@ use wasm_bindgen::prelude::*; use crate::jose::WasmJwk; /// Wrapper that enables custom TS JWS signature verification plugins to be used where the -/// JwsVerifier trait is required. Falls back to the default implementation if a custom -/// implementation was not passed. -pub(crate) struct WasmJwsVerifier(IJwsVerifier); +/// JwsVerifier trait is required. Falls back to the default implementation capable of handling +/// EdDSA (ED25519), ES256, ES256K if a custom implementation is not passed. +pub(crate) struct WasmJwsVerifier(Option); impl WasmJwsVerifier { - pub(crate) fn new(verifier: IJwsVerifier) -> Self { + pub(crate) fn new(verifier: Option) -> Self { Self(verifier) } } @@ -26,22 +29,30 @@ impl JwsVerifier for WasmJwsVerifier { input: identity_iota::verification::jws::VerificationInput, public_key: &identity_iota::verification::jwk::Jwk, ) -> Result<(), identity_iota::verification::jws::SignatureVerificationError> { - let VerificationInput { - alg, - signing_input, - decoded_signature, - } = input; - let verification_result = IJwsVerifier::verify( - &self.0, - alg.name().to_owned(), - signing_input.into(), - decoded_signature.into(), - WasmJwk(public_key.to_owned()), - ); - // Convert error - crate::error::stringify_js_error(verification_result).map_err(|error_string| { - SignatureVerificationError::new(SignatureVerificationErrorKind::Unspecified).with_custom_message(error_string) - }) + if let Some(verifier) = &self.0 { + let VerificationInput { + alg, + signing_input, + decoded_signature, + } = input; + let verification_result = IJwsVerifier::verify( + verifier, + alg.name().to_owned(), + signing_input.into(), + decoded_signature.into(), + WasmJwk(public_key.to_owned()), + ); + // Convert error + crate::error::stringify_js_error(verification_result).map_err(|error_string| { + SignatureVerificationError::new(SignatureVerificationErrorKind::Unspecified).with_custom_message(error_string) + }) + } else { + match input.alg { + JwsAlgorithm::EdDSA => EdDSAJwsVerifier::default().verify(input, public_key), + JwsAlgorithm::ES256 | JwsAlgorithm::ES256K => EcDSAJwsVerifier::default().verify(input, public_key), + _ => Err(identity_iota::verification::jws::SignatureVerificationErrorKind::UnsupportedAlg.into()), + } + } } } #[wasm_bindgen(typescript_custom_section)] diff --git a/bindings/wasm/src/verification/jws_verifier.rs b/bindings/wasm/src/verification/jws_verifier.rs index 6113674828..bd016910c8 100644 --- a/bindings/wasm/src/verification/jws_verifier.rs +++ b/bindings/wasm/src/verification/jws_verifier.rs @@ -1,6 +1,7 @@ // Copyright 2020-2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use identity_ecdsa_verifier::EcDSAJwsVerifier; use identity_eddsa_verifier::Ed25519Verifier; use identity_eddsa_verifier::EdDSAJwsVerifier; use identity_iota::verification::jws::JwsAlgorithm; @@ -80,3 +81,43 @@ impl WasmEdDSAJwsVerifier { EdDSAJwsVerifier::default().verify(input, &publicKey.0).wasm_result() } } + +/// An implementor of `IJwsVerifier` that can handle the +/// `EcDSA` algorithm. +#[wasm_bindgen(js_name = EcDSAJwsVerifier)] +pub struct WasmEcDSAJwsVerifier(); + +#[wasm_bindgen(js_class = EcDSAJwsVerifier)] +#[allow(clippy::new_without_default)] +impl WasmEcDSAJwsVerifier { + /// Constructs an EcDSAJwsVerifier. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + Self() + } + + /// Verify a JWS signature secured with the `EcDSA` algorithm. + /// Only the `ES256` and `ES256K` curves are supported for now. + /// + /// # Warning + /// + /// This function does not check the `alg` property in the protected header. Callers are expected to assert this + /// prior to calling the function. + #[wasm_bindgen] + #[allow(non_snake_case)] + pub fn verify( + &self, + alg: WasmJwsAlgorithm, + signingInput: &[u8], + decodedSignature: &[u8], + publicKey: &WasmJwk, + ) -> Result<(), JsValue> { + let alg: JwsAlgorithm = JwsAlgorithm::try_from(alg)?; + let input: VerificationInput = VerificationInput { + alg, + signing_input: signingInput.into(), + decoded_signature: decodedSignature.into(), + }; + EcDSAJwsVerifier::default().verify(input, &publicKey.0).wasm_result() + } +} From a0c7b069718ea43839a5c8d0f344f2dd3730f6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eike=20Ha=C3=9F?= Date: Tue, 10 Sep 2024 12:26:35 +0200 Subject: [PATCH 21/22] Use Typedoc for Wasm API docs (#1399) --- .../actions/publish/publish-wasm/action.yml | 2 +- .github/workflows/build-and-test.yml | 6 +- .github/workflows/shared-build-wasm.yml | 3 +- .github/workflows/upload-docs.yml | 51 + .gitignore | 2 + bindings/wasm/build/docs.js | 15 - bindings/wasm/docs/api-reference.md | 7865 ----------------- bindings/wasm/package-lock.json | 207 +- bindings/wasm/package.json | 6 +- bindings/wasm/src/sd_jwt/encoder.rs | 1 - bindings/wasm/tsconfig.typedoc.json | 4 + bindings/wasm/typedoc.json | 23 + 12 files changed, 291 insertions(+), 7894 deletions(-) create mode 100644 .github/workflows/upload-docs.yml delete mode 100644 bindings/wasm/build/docs.js delete mode 100644 bindings/wasm/docs/api-reference.md create mode 100644 bindings/wasm/tsconfig.typedoc.json create mode 100644 bindings/wasm/typedoc.json diff --git a/.github/actions/publish/publish-wasm/action.yml b/.github/actions/publish/publish-wasm/action.yml index cfaedea939..6bb1171fbd 100644 --- a/.github/actions/publish/publish-wasm/action.yml +++ b/.github/actions/publish/publish-wasm/action.yml @@ -24,7 +24,7 @@ runs: registry-url: 'https://registry.npmjs.org' - name: Download bindings/wasm artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: ${{ inputs.input-artifact-name }} path: bindings/wasm diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ba3b7ef0b1..c92432e36f 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -198,7 +198,7 @@ jobs: working-directory: bindings/wasm - name: Download bindings/wasm artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: identity-wasm-bindings-build path: bindings/wasm @@ -238,7 +238,7 @@ jobs: working-directory: bindings/wasm - name: Download bindings/wasm artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: identity-wasm-bindings-build path: bindings/wasm @@ -286,7 +286,7 @@ jobs: working-directory: bindings/wasm - name: Download bindings/wasm artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: identity-wasm-bindings-build path: bindings/wasm diff --git a/.github/workflows/shared-build-wasm.yml b/.github/workflows/shared-build-wasm.yml index 8f39769dfd..263e1da66c 100644 --- a/.github/workflows/shared-build-wasm.yml +++ b/.github/workflows/shared-build-wasm.yml @@ -82,12 +82,13 @@ jobs: os: ${{matrix.os}} - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ inputs.output-artifact-name }} path: | bindings/wasm/node bindings/wasm/web bindings/wasm/examples/dist + bindings/wasm/docs if-no-files-found: error retention-days: 1 diff --git a/.github/workflows/upload-docs.yml b/.github/workflows/upload-docs.yml new file mode 100644 index 0000000000..5ce1429767 --- /dev/null +++ b/.github/workflows/upload-docs.yml @@ -0,0 +1,51 @@ +name: Build and upload API docs + +on: + release: + types: [published] + workflow_dispatch: + inputs: + version: + description: 'Version to publish docs under (e.g. `v1.2.3-dev.1`)' + required: true + +permissions: + actions: 'write' + +jobs: + build-wasm: + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-build-wasm.yml@main + with: + run-unit-tests: false + ref: ${{ inputs.ref }} + output-artifact-name: identity-docs + + upload-docs: + runs-on: ubuntu-latest + needs: build-wasm + steps: + - uses: actions/download-artifact@v4 + with: + name: identity-docs + - name: Get release version + id: get_release_version + run: | + if [ "${{ github.event_name }}" = "release" ]; then + INPUT_VERSION="${{ github.ref }}" + else + INPUT_VERSION="${{ github.event.inputs.version }}" + fi + VERSION=$(echo $INPUT_VERSION | sed -e 's/.*v\([0-9]*\.[0-9]*\).*/\1/') + echo VERSION=$VERSION >> $GITHUB_OUTPUT + - name: Compress generated docs + run: | + tar czvf wasm.tar.gz docs/* + + - name: Upload docs to AWS S3 + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_IOTA_WIKI }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_IOTA_WIKI }} + AWS_DEFAULT_REGION: "eu-central-1" + run: | + aws s3 cp wasm.tar.gz s3://files.iota.org/iota-wiki/iota-identity/${{ steps.get_release_version.outputs.VERSION }}/ --acl public-read diff --git a/.gitignore b/.gitignore index 5a33dbab25..52f081d501 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ index.html *.hodl.* !/bindings/wasm/static/index.html + +docs diff --git a/bindings/wasm/build/docs.js b/bindings/wasm/build/docs.js deleted file mode 100644 index b496ccd7d0..0000000000 --- a/bindings/wasm/build/docs.js +++ /dev/null @@ -1,15 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const jsdoc2md = require("jsdoc-to-markdown"); - -const importFile = path.join(__dirname, "../node/identity_wasm.js"); -const exportFile = path.join(__dirname, "../docs/api-reference.md"); - -const docsRoot = path.join(__dirname, "../docs"); -const docsData = jsdoc2md.renderSync({ files: importFile }); - -if (!fs.existsSync(docsRoot)) { - fs.mkdirSync(docsRoot); -} - -fs.writeFileSync(exportFile, docsData); diff --git a/bindings/wasm/docs/api-reference.md b/bindings/wasm/docs/api-reference.md deleted file mode 100644 index 25fdf6ba04..0000000000 --- a/bindings/wasm/docs/api-reference.md +++ /dev/null @@ -1,7865 +0,0 @@ -## Classes - -
-
CoreDID
-

A method-agnostic Decentralized Identifier (DID).

-
-
CoreDocument
-

A method-agnostic DID Document.

-

Note: All methods that involve reading from this class may potentially raise an error -if the object is being concurrently modified.

-
-
Credential
-
-
CustomMethodData
-

A custom verification method data format.

-
-
DIDJwk
-

did:jwk DID.

-
-
DIDUrl
-

A method agnostic DID Url.

-
-
DecodedJptCredential
-
-
DecodedJptPresentation
-
-
DecodedJws
-

A cryptographically verified decoded token from a JWS.

-

Contains the decoded headers and the raw claims.

-
-
DecodedJwtCredential
-

A cryptographically verified and decoded Credential.

-

Note that having an instance of this type only means the JWS it was constructed from was verified. -It does not imply anything about a potentially present proof property on the credential itself.

-
-
DecodedJwtPresentation
-

A cryptographically verified and decoded presentation.

-

Note that having an instance of this type only means the JWS it was constructed from was verified. -It does not imply anything about a potentially present proof property on the presentation itself.

-
-
Disclosure
-

Represents an elements constructing a disclosure. -Object properties and array elements disclosures are supported.

-

See: https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html#name-disclosures

-
-
DomainLinkageConfiguration
-

DID Configuration Resource which contains Domain Linkage Credentials. -It can be placed in an origin's .well-known directory to prove linkage between the origin and a DID. -See: https://identity.foundation/.well-known/resources/did-configuration/#did-configuration-resource

-

Note:

- -
-
Duration
-

A span of time.

-
-
EcDSAJwsVerifier
-

An implementor of IJwsVerifier that can handle the -EcDSA algorithm.

-
-
EdDSAJwsVerifier
-

An implementor of IJwsVerifier that can handle the -EdDSA algorithm.

-
-
IotaDID
-

A DID conforming to the IOTA DID method specification.

-
-
IotaDocument
-

A DID Document adhering to the IOTA DID method specification.

-

Note: All methods that involve reading from this class may potentially raise an error -if the object is being concurrently modified.

-
-
IotaDocumentMetadata
-

Additional attributes related to an IOTA DID Document.

-
-
IotaIdentityClientExt
-

An extension interface that provides helper functions for publication -and resolution of DID documents in Alias Outputs.

-
-
IssuerProtectedHeader
-
-
Jpt
-

A JSON Proof Token (JPT).

-
-
JptCredentialValidationOptions
-

Options to declare validation criteria for Jpt.

-
-
JptCredentialValidator
-
-
JptCredentialValidatorUtils
-

Utility functions for validating JPT credentials.

-
-
JptPresentationValidationOptions
-

Options to declare validation criteria for a Jpt presentation.

-
-
JptPresentationValidator
-
-
JptPresentationValidatorUtils
-

Utility functions for verifying JPT presentations.

-
-
Jwk
-
-
JwkGenOutput
-

The result of a key generation in JwkStorage.

-
-
JwpCredentialOptions
-
-
JwpIssued
-
-
JwpPresentationOptions
-

Options to be set in the JWT claims of a verifiable presentation.

-
-
JwpVerificationOptions
-
-
Jws
-

A wrapper around a JSON Web Signature (JWS).

-
-
JwsHeader
-
-
JwsSignatureOptions
-
-
JwsVerificationOptions
-
-
Jwt
-

A wrapper around a JSON Web Token (JWK).

-
-
JwtCredentialValidationOptions
-

Options to declare validation criteria when validating credentials.

-
-
JwtCredentialValidator
-

A type for decoding and validating Credential.

-
-
JwtDomainLinkageValidator
-

A validator for a Domain Linkage Configuration and Credentials.

-
-
JwtPresentationOptions
-
-
JwtPresentationValidationOptions
-

Options to declare validation criteria when validating presentation.

-
-
JwtPresentationValidator
-
-
KeyBindingJWTValidationOptions
-

Options to declare validation criteria when validating credentials.

-
-
KeyBindingJwtClaims
-

Claims set for key binding JWT.

-
-
LinkedDomainService
-
-
MethodData
-

Supported verification method data formats.

-
-
MethodDigest
-

Unique identifier of a VerificationMethod.

-

NOTE: -This class does not have a JSON representation, -use the methods pack and unpack instead.

-
-
MethodScope
-

Supported verification method types.

-
-
MethodType
-

Supported verification method types.

-
-
PayloadEntry
-
-
Payloads
-
-
Presentation
-
-
PresentationProtectedHeader
-
-
Proof
-

Represents a cryptographic proof that can be used to validate verifiable credentials and -presentations.

-

This representation does not inherently implement any standard; instead, it -can be utilized to implement standards or user-defined proofs. The presence of the -type field is necessary to accommodate different types of cryptographic proofs.

-

Note that this proof is not related to JWT and can be used in combination or as an alternative -to it.

-
-
ProofUpdateCtx
-
-
Resolver
-

Convenience type for resolving DID documents from different DID methods.

-

Also provides methods for resolving DID Documents associated with -verifiable Credentials and Presentations.

-

Configuration

-

The resolver will only be able to resolve DID documents for methods it has been configured for in the constructor.

-
-
RevocationBitmap
-

A compressed bitmap for managing credential revocation.

-
-
RevocationTimeframeStatus
-

Information used to determine the current status of a Credential.

-
-
SdJwt
-

Representation of an SD-JWT of the format -<Issuer-signed JWT>~<Disclosure 1>~<Disclosure 2>~...~<Disclosure N>~<optional KB-JWT>.

-
-
SdJwtCredentialValidator
-

A type for decoding and validating Credential.

-
-
SdObjectDecoder
-

Substitutes digests in an SD-JWT object by their corresponding plaintext values provided by disclosures.

-
-
SdObjectEncoder
-

Transforms a JSON object into an SD-JWT object by substituting selected values -with their corresponding disclosure digests.

-

Note: digests are created using the sha-256 algorithm.

-
-
SelectiveDisclosurePresentation
-

Used to construct a JwpPresentedBuilder and handle the selective disclosure of attributes

-
    -
  • @context MUST NOT be blinded
  • -
  • id MUST be blinded
  • -
  • type MUST NOT be blinded
  • -
  • issuer MUST NOT be blinded
  • -
  • issuanceDate MUST be blinded (if Timeframe Revocation mechanism is used)
  • -
  • expirationDate MUST be blinded (if Timeframe Revocation mechanism is used)
  • -
  • credentialSubject (User have to choose which attribute must be blinded)
  • -
  • credentialSchema MUST NOT be blinded
  • -
  • credentialStatus MUST NOT be blinded
  • -
  • refreshService MUST NOT be blinded (probably will be used for Timeslot Revocation mechanism)
  • -
  • termsOfUse NO reason to use it in ZK VC (will be in any case blinded)
  • -
  • evidence (User have to choose which attribute must be blinded)
  • -
-
-
Service
-

A DID Document Service used to enable trusted interactions associated with a DID subject.

-
-
StatusList2021
-

StatusList2021 data structure as described in W3C's VC status list 2021.

-
-
StatusList2021Credential
-

A parsed StatusList2021Credential.

-
-
StatusList2021CredentialBuilder
-

Builder type to construct valid StatusList2021Credential istances.

-
-
StatusList2021Entry
-

StatusList2021Entry implementation.

-
-
Storage
-

A type wrapping a JwkStorage and KeyIdStorage that should always be used together when -working with storage backed DID documents.

-
-
Timestamp
-
-
UnknownCredential
-
-
VerificationMethod
-

A DID Document Verification Method.

-
-
- -## Members - -
-
StatusCheck
-

Controls validation behaviour when checking whether or not a credential has been revoked by its -credentialStatus.

-
-
Strict
-

Validate the status if supported, reject any unsupported -credentialStatus types.

-

Only RevocationBitmap2022 is currently supported.

-

This is the default.

-
-
SkipUnsupported
-

Validate the status if supported, skip any unsupported -credentialStatus types.

-
-
SkipAll
-

Skip all status checks.

-
-
SubjectHolderRelationship
-

Declares how credential subjects must relate to the presentation holder.

-

See also the Subject-Holder Relationship section of the specification.

-
-
AlwaysSubject
-

The holder must always match the subject on all credentials, regardless of their nonTransferable property. -This variant is the default.

-
-
SubjectOnNonTransferable
-

The holder must match the subject only for credentials where the nonTransferable property is true.

-
-
Any
-

The holder is not required to have any kind of relationship to any credential subject.

-
-
PresentationProofAlgorithm
-
-
StatusPurpose
-

Purpose of a StatusList2021.

-
-
ProofAlgorithm
-
-
CredentialStatus
-
-
FailFast
-

Declares when validation should return if an error occurs.

-
-
AllErrors
-

Return all errors that occur during validation.

-
-
FirstError
-

Return after the first error occurs.

-
-
StateMetadataEncoding
-
-
SerializationType
-
-
PayloadType
-
-
MethodRelationship
-
-
- -## Functions - -
-
encodeB64(data)string
-

Encode the given bytes in url-safe base64.

-
-
decodeB64(data)Uint8Array
-

Decode the given url-safe base64-encoded slice into its raw bytes.

-
-
verifyEd25519(alg, signingInput, decodedSignature, publicKey)
-

Verify a JWS signature secured with the EdDSA algorithm and curve Ed25519.

-

This function is useful when one is composing a IJwsVerifier that delegates -EdDSA verification with curve Ed25519 to this function.

-

Warning

-

This function does not check whether alg = EdDSA in the protected header. Callers are expected to assert this -prior to calling the function.

-
-
start()
-

Initializes the console error panic hook for better error messages

-
-
encodeB64(data)string
-

Encode the given bytes in url-safe base64.

-
-
decodeB64(data)Uint8Array
-

Decode the given url-safe base64-encoded slice into its raw bytes.

-
-
- - - -## CoreDID -A method-agnostic Decentralized Identifier (DID). - -**Kind**: global class - -* [CoreDID](#CoreDID) - * _instance_ - * [.setMethodName(value)](#CoreDID+setMethodName) - * [.setMethodId(value)](#CoreDID+setMethodId) - * [.scheme()](#CoreDID+scheme) ⇒ string - * [.authority()](#CoreDID+authority) ⇒ string - * [.method()](#CoreDID+method) ⇒ string - * [.methodId()](#CoreDID+methodId) ⇒ string - * [.join(segment)](#CoreDID+join) ⇒ [DIDUrl](#DIDUrl) - * [.toUrl()](#CoreDID+toUrl) ⇒ [DIDUrl](#DIDUrl) - * [.intoUrl()](#CoreDID+intoUrl) ⇒ [DIDUrl](#DIDUrl) - * [.toString()](#CoreDID+toString) ⇒ string - * [.toCoreDid()](#CoreDID+toCoreDid) ⇒ [CoreDID](#CoreDID) - * [.toJSON()](#CoreDID+toJSON) ⇒ any - * [.clone()](#CoreDID+clone) ⇒ [CoreDID](#CoreDID) - * _static_ - * [.parse(input)](#CoreDID.parse) ⇒ [CoreDID](#CoreDID) - * [.validMethodName(value)](#CoreDID.validMethodName) ⇒ boolean - * [.validMethodId(value)](#CoreDID.validMethodId) ⇒ boolean - * [.fromJSON(json)](#CoreDID.fromJSON) ⇒ [CoreDID](#CoreDID) - - - -### coreDID.setMethodName(value) -Set the method name of the [CoreDID](#CoreDID). - -**Kind**: instance method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| value | string | - - - -### coreDID.setMethodId(value) -Set the method-specific-id of the `DID`. - -**Kind**: instance method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| value | string | - - - -### coreDID.scheme() ⇒ string -Returns the [CoreDID](#CoreDID) scheme. - -E.g. -- `"did:example:12345678" -> "did"` -- `"did:iota:smr:12345678" -> "did"` - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.authority() ⇒ string -Returns the [CoreDID](#CoreDID) authority: the method name and method-id. - -E.g. -- `"did:example:12345678" -> "example:12345678"` -- `"did:iota:smr:12345678" -> "iota:smr:12345678"` - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.method() ⇒ string -Returns the [CoreDID](#CoreDID) method name. - -E.g. -- `"did:example:12345678" -> "example"` -- `"did:iota:smr:12345678" -> "iota"` - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.methodId() ⇒ string -Returns the [CoreDID](#CoreDID) method-specific ID. - -E.g. -- `"did:example:12345678" -> "12345678"` -- `"did:iota:smr:12345678" -> "smr:12345678"` - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.join(segment) ⇒ [DIDUrl](#DIDUrl) -Construct a new [DIDUrl](#DIDUrl) by joining with a relative DID Url string. - -**Kind**: instance method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| segment | string | - - - -### coreDID.toUrl() ⇒ [DIDUrl](#DIDUrl) -Clones the [CoreDID](#CoreDID) into a [DIDUrl](#DIDUrl). - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.intoUrl() ⇒ [DIDUrl](#DIDUrl) -Converts the [CoreDID](#CoreDID) into a [DIDUrl](#DIDUrl), consuming it. - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.toString() ⇒ string -Returns the [CoreDID](#CoreDID) as a string. - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.toCoreDid() ⇒ [CoreDID](#CoreDID) -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### coreDID.clone() ⇒ [CoreDID](#CoreDID) -Deep clones the object. - -**Kind**: instance method of [CoreDID](#CoreDID) - - -### CoreDID.parse(input) ⇒ [CoreDID](#CoreDID) -Parses a [CoreDID](#CoreDID) from the given `input`. - -### Errors - -Throws an error if the input is not a valid [CoreDID](#CoreDID). - -**Kind**: static method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| input | string | - - - -### CoreDID.validMethodName(value) ⇒ boolean -Validates whether a string is a valid DID method name. - -**Kind**: static method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| value | string | - - - -### CoreDID.validMethodId(value) ⇒ boolean -Validates whether a string is a valid `DID` method-id. - -**Kind**: static method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| value | string | - - - -### CoreDID.fromJSON(json) ⇒ [CoreDID](#CoreDID) -Deserializes an instance from a JSON object. - -**Kind**: static method of [CoreDID](#CoreDID) - -| Param | Type | -| --- | --- | -| json | any | - - - -## CoreDocument -A method-agnostic DID Document. - -Note: All methods that involve reading from this class may potentially raise an error -if the object is being concurrently modified. - -**Kind**: global class - -* [CoreDocument](#CoreDocument) - * [new CoreDocument(values)](#new_CoreDocument_new) - * _instance_ - * [.id()](#CoreDocument+id) ⇒ [CoreDID](#CoreDID) - * [.setId(id)](#CoreDocument+setId) - * [.controller()](#CoreDocument+controller) ⇒ [Array.<CoreDID>](#CoreDID) - * [.setController(controllers)](#CoreDocument+setController) - * [.alsoKnownAs()](#CoreDocument+alsoKnownAs) ⇒ Array.<string> - * [.setAlsoKnownAs(urls)](#CoreDocument+setAlsoKnownAs) - * [.verificationMethod()](#CoreDocument+verificationMethod) ⇒ [Array.<VerificationMethod>](#VerificationMethod) - * [.authentication()](#CoreDocument+authentication) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.assertionMethod()](#CoreDocument+assertionMethod) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.keyAgreement()](#CoreDocument+keyAgreement) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.capabilityDelegation()](#CoreDocument+capabilityDelegation) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.capabilityInvocation()](#CoreDocument+capabilityInvocation) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.properties()](#CoreDocument+properties) ⇒ Map.<string, any> - * [.setPropertyUnchecked(key, value)](#CoreDocument+setPropertyUnchecked) - * [.service()](#CoreDocument+service) ⇒ [Array.<Service>](#Service) - * [.insertService(service)](#CoreDocument+insertService) - * [.removeService(didUrl)](#CoreDocument+removeService) ⇒ [Service](#Service) \| undefined - * [.resolveService(query)](#CoreDocument+resolveService) ⇒ [Service](#Service) \| undefined - * [.methods([scope])](#CoreDocument+methods) ⇒ [Array.<VerificationMethod>](#VerificationMethod) - * [.verificationRelationships()](#CoreDocument+verificationRelationships) ⇒ Array.<(DIDUrl\|VerificationMethod)> - * [.insertMethod(method, scope)](#CoreDocument+insertMethod) - * [.removeMethod(did)](#CoreDocument+removeMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined - * [.resolveMethod(query, [scope])](#CoreDocument+resolveMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined - * [.attachMethodRelationship(didUrl, relationship)](#CoreDocument+attachMethodRelationship) ⇒ boolean - * [.detachMethodRelationship(didUrl, relationship)](#CoreDocument+detachMethodRelationship) ⇒ boolean - * [.verifyJws(jws, options, [signatureVerifier], [detachedPayload])](#CoreDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) - * [.revokeCredentials(serviceQuery, indices)](#CoreDocument+revokeCredentials) - * [.unrevokeCredentials(serviceQuery, indices)](#CoreDocument+unrevokeCredentials) - * [.clone()](#CoreDocument+clone) ⇒ [CoreDocument](#CoreDocument) - * [._shallowCloneInternal()](#CoreDocument+_shallowCloneInternal) ⇒ [CoreDocument](#CoreDocument) - * [._strongCountInternal()](#CoreDocument+_strongCountInternal) ⇒ number - * [.toJSON()](#CoreDocument+toJSON) ⇒ any - * [.generateMethod(storage, keyType, alg, fragment, scope)](#CoreDocument+generateMethod) ⇒ Promise.<string> - * [.purgeMethod(storage, id)](#CoreDocument+purgeMethod) ⇒ Promise.<void> - * [.createJws(storage, fragment, payload, options)](#CoreDocument+createJws) ⇒ [Promise.<Jws>](#Jws) - * [.createCredentialJwt(storage, fragment, credential, options, [custom_claims])](#CoreDocument+createCredentialJwt) ⇒ [Promise.<Jwt>](#Jwt) - * [.createPresentationJwt(storage, fragment, presentation, signature_options, presentation_options)](#CoreDocument+createPresentationJwt) ⇒ [Promise.<Jwt>](#Jwt) - * _static_ - * [.fromJSON(json)](#CoreDocument.fromJSON) ⇒ [CoreDocument](#CoreDocument) - * [.expandDIDJwk(did)](#CoreDocument.expandDIDJwk) ⇒ [CoreDocument](#CoreDocument) - - - -### new CoreDocument(values) -Creates a new [CoreDocument](#CoreDocument) with the given properties. - - -| Param | Type | -| --- | --- | -| values | ICoreDocument | - - - -### coreDocument.id() ⇒ [CoreDID](#CoreDID) -Returns a copy of the DID Document `id`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.setId(id) -Sets the DID of the document. - -### Warning - -Changing the identifier can drastically alter the results of -`resolve_method`, `resolve_service` and the related -[DID URL dereferencing](https://w3c-ccg.github.io/did-resolution/#dereferencing) algorithm. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| id | [CoreDID](#CoreDID) | - - - -### coreDocument.controller() ⇒ [Array.<CoreDID>](#CoreDID) -Returns a copy of the document controllers. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.setController(controllers) -Sets the controllers of the DID Document. - -Note: Duplicates will be ignored. -Use `null` to remove all controllers. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| controllers | [CoreDID](#CoreDID) \| [Array.<CoreDID>](#CoreDID) \| null | - - - -### coreDocument.alsoKnownAs() ⇒ Array.<string> -Returns a copy of the document's `alsoKnownAs` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.setAlsoKnownAs(urls) -Sets the `alsoKnownAs` property in the DID document. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| urls | string \| Array.<string> \| null | - - - -### coreDocument.verificationMethod() ⇒ [Array.<VerificationMethod>](#VerificationMethod) -Returns a copy of the document's `verificationMethod` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.authentication() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns a copy of the document's `authentication` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.assertionMethod() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns a copy of the document's `assertionMethod` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.keyAgreement() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns a copy of the document's `keyAgreement` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.capabilityDelegation() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns a copy of the document's `capabilityDelegation` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.capabilityInvocation() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns a copy of the document's `capabilityInvocation` set. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.properties() ⇒ Map.<string, any> -Returns a copy of the custom DID Document properties. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.setPropertyUnchecked(key, value) -Sets a custom property in the DID Document. -If the value is set to `null`, the custom property will be removed. - -### WARNING - -This method can overwrite existing properties like `id` and result in an invalid document. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| key | string | -| value | any | - - - -### coreDocument.service() ⇒ [Array.<Service>](#Service) -Returns a set of all [Service](#Service) in the document. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.insertService(service) -Add a new [Service](#Service) to the document. - -Errors if there already exists a service or verification method with the same id. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| service | [Service](#Service) | - - - -### coreDocument.removeService(didUrl) ⇒ [Service](#Service) \| undefined -Remove a [Service](#Service) identified by the given [DIDUrl](#DIDUrl) from the document. - -Returns `true` if the service was removed. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| didUrl | [DIDUrl](#DIDUrl) | - - - -### coreDocument.resolveService(query) ⇒ [Service](#Service) \| undefined -Returns the first [Service](#Service) with an `id` property matching the provided `query`, -if present. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| query | [DIDUrl](#DIDUrl) \| string | - - - -### coreDocument.methods([scope]) ⇒ [Array.<VerificationMethod>](#VerificationMethod) -Returns a list of all [VerificationMethod](#VerificationMethod) in the DID Document, -whose verification relationship matches `scope`. - -If `scope` is not set, a list over the **embedded** methods is returned. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| [scope] | [MethodScope](#MethodScope) \| undefined | - - - -### coreDocument.verificationRelationships() ⇒ Array.<(DIDUrl\|VerificationMethod)> -Returns an array of all verification relationships. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.insertMethod(method, scope) -Adds a new `method` to the document in the given `scope`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| method | [VerificationMethod](#VerificationMethod) | -| scope | [MethodScope](#MethodScope) | - - - -### coreDocument.removeMethod(did) ⇒ [VerificationMethod](#VerificationMethod) \| undefined -Removes all references to the specified Verification Method. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| did | [DIDUrl](#DIDUrl) | - - - -### coreDocument.resolveMethod(query, [scope]) ⇒ [VerificationMethod](#VerificationMethod) \| undefined -Returns a copy of the first verification method with an `id` property -matching the provided `query` and the verification relationship -specified by `scope`, if present. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| query | [DIDUrl](#DIDUrl) \| string | -| [scope] | [MethodScope](#MethodScope) \| undefined | - - - -### coreDocument.attachMethodRelationship(didUrl, relationship) ⇒ boolean -Attaches the relationship to the given method, if the method exists. - -Note: The method needs to be in the set of verification methods, -so it cannot be an embedded one. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| didUrl | [DIDUrl](#DIDUrl) | -| relationship | [MethodRelationship](#MethodRelationship) | - - - -### coreDocument.detachMethodRelationship(didUrl, relationship) ⇒ boolean -Detaches the given relationship from the given method, if the method exists. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| didUrl | [DIDUrl](#DIDUrl) | -| relationship | [MethodRelationship](#MethodRelationship) | - - - -### coreDocument.verifyJws(jws, options, [signatureVerifier], [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) -Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. - If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of -verifying EdDSA signatures. - -Regardless of which options are passed the following conditions must be met in order for a verification attempt to -take place. -- The JWS must be encoded according to the JWS compact serialization. -- The `kid` value in the protected header must be an identifier of a verification method in this DID document, -or set explicitly in the `options`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| jws | [Jws](#Jws) | -| options | [JwsVerificationOptions](#JwsVerificationOptions) | -| [signatureVerifier] | IJwsVerifier \| undefined | -| [detachedPayload] | string \| undefined | - - - -### coreDocument.revokeCredentials(serviceQuery, indices) -If the document has a [RevocationBitmap](#RevocationBitmap) service identified by `serviceQuery`, -revoke all specified `indices`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| serviceQuery | [DIDUrl](#DIDUrl) \| string | -| indices | number \| Array.<number> | - - - -### coreDocument.unrevokeCredentials(serviceQuery, indices) -If the document has a [RevocationBitmap](#RevocationBitmap) service identified by `serviceQuery`, -unrevoke all specified `indices`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| serviceQuery | [DIDUrl](#DIDUrl) \| string | -| indices | number \| Array.<number> | - - - -### coreDocument.clone() ⇒ [CoreDocument](#CoreDocument) -Deep clones the [CoreDocument](#CoreDocument). - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.\_shallowCloneInternal() ⇒ [CoreDocument](#CoreDocument) -### Warning -This is for internal use only. Do not rely on or call this method. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.\_strongCountInternal() ⇒ number -### Warning -This is for internal use only. Do not rely on or call this method. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.toJSON() ⇒ any -Serializes to a plain JS representation. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - - -### coreDocument.generateMethod(storage, keyType, alg, fragment, scope) ⇒ Promise.<string> -Generate new key material in the given `storage` and insert a new verification method with the corresponding -public key material into the DID document. - -- If no fragment is given the `kid` of the generated JWK is used, if it is set, otherwise an error is returned. -- The `keyType` must be compatible with the given `storage`. `Storage`s are expected to export key type constants -for that use case. - -The fragment of the generated method is returned. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| keyType | string | -| alg | JwsAlgorithm | -| fragment | string \| undefined | -| scope | [MethodScope](#MethodScope) | - - - -### coreDocument.purgeMethod(storage, id) ⇒ Promise.<void> -Remove the method identified by the `fragment` from the document and delete the corresponding key material in -the `storage`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| id | [DIDUrl](#DIDUrl) | - - - -### coreDocument.createJws(storage, fragment, payload, options) ⇒ [Promise.<Jws>](#Jws) -Sign the `payload` according to `options` with the storage backed private key corresponding to the public key -material in the verification method identified by the given `fragment. - -Upon success a string representing a JWS encoded according to the Compact JWS Serialization format is returned. -See [RFC7515 section 3.1](https://www.rfc-editor.org/rfc/rfc7515#section-3.1). - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| payload | string | -| options | [JwsSignatureOptions](#JwsSignatureOptions) | - - - -### coreDocument.createCredentialJwt(storage, fragment, credential, options, [custom_claims]) ⇒ [Promise.<Jwt>](#Jwt) -Produces a JWT where the payload is produced from the given `credential` -in accordance with [VC Data Model v1.1](https://www.w3.org/TR/vc-data-model/#json-web-token). - -Unless the `kid` is explicitly set in the options, the `kid` in the protected header is the `id` -of the method identified by `fragment` and the JWS signature will be produced by the corresponding -private key backed by the `storage` in accordance with the passed `options`. - -The `custom_claims` can be used to set additional claims on the resulting JWT. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| credential | [Credential](#Credential) | -| options | [JwsSignatureOptions](#JwsSignatureOptions) | -| [custom_claims] | Record.<string, any> \| undefined | - - - -### coreDocument.createPresentationJwt(storage, fragment, presentation, signature_options, presentation_options) ⇒ [Promise.<Jwt>](#Jwt) -Produces a JWT where the payload is produced from the given presentation. -in accordance with [VC Data Model v1.1](https://www.w3.org/TR/vc-data-model/#json-web-token). - -Unless the `kid` is explicitly set in the options, the `kid` in the protected header is the `id` -of the method identified by `fragment` and the JWS signature will be produced by the corresponding -private key backed by the `storage` in accordance with the passed `options`. - -**Kind**: instance method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| presentation | [Presentation](#Presentation) | -| signature_options | [JwsSignatureOptions](#JwsSignatureOptions) | -| presentation_options | [JwtPresentationOptions](#JwtPresentationOptions) | - - - -### CoreDocument.fromJSON(json) ⇒ [CoreDocument](#CoreDocument) -Deserializes an instance from a plain JS representation. - -**Kind**: static method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| json | any | - - - -### CoreDocument.expandDIDJwk(did) ⇒ [CoreDocument](#CoreDocument) -Creates a [CoreDocument](#CoreDocument) from the given [DIDJwk](#DIDJwk). - -**Kind**: static method of [CoreDocument](#CoreDocument) - -| Param | Type | -| --- | --- | -| did | [DIDJwk](#DIDJwk) | - - - -## Credential -**Kind**: global class - -* [Credential](#Credential) - * [new Credential(values)](#new_Credential_new) - * _instance_ - * [.context()](#Credential+context) ⇒ Array.<(string\|Record.<string, any>)> - * [.id()](#Credential+id) ⇒ string \| undefined - * [.type()](#Credential+type) ⇒ Array.<string> - * [.credentialSubject()](#Credential+credentialSubject) ⇒ Array.<Subject> - * [.issuer()](#Credential+issuer) ⇒ string \| Issuer - * [.issuanceDate()](#Credential+issuanceDate) ⇒ [Timestamp](#Timestamp) - * [.expirationDate()](#Credential+expirationDate) ⇒ [Timestamp](#Timestamp) \| undefined - * [.credentialStatus()](#Credential+credentialStatus) ⇒ Array.<Status> - * [.credentialSchema()](#Credential+credentialSchema) ⇒ Array.<Schema> - * [.refreshService()](#Credential+refreshService) ⇒ Array.<RefreshService> - * [.termsOfUse()](#Credential+termsOfUse) ⇒ Array.<Policy> - * [.evidence()](#Credential+evidence) ⇒ Array.<Evidence> - * [.nonTransferable()](#Credential+nonTransferable) ⇒ boolean \| undefined - * [.proof()](#Credential+proof) ⇒ [Proof](#Proof) \| undefined - * [.properties()](#Credential+properties) ⇒ Map.<string, any> - * [.setProof([proof])](#Credential+setProof) - * [.toJwtClaims([custom_claims])](#Credential+toJwtClaims) ⇒ Record.<string, any> - * [.toJSON()](#Credential+toJSON) ⇒ any - * [.clone()](#Credential+clone) ⇒ [Credential](#Credential) - * _static_ - * [.BaseContext()](#Credential.BaseContext) ⇒ string - * [.BaseType()](#Credential.BaseType) ⇒ string - * [.createDomainLinkageCredential(values)](#Credential.createDomainLinkageCredential) ⇒ [Credential](#Credential) - * [.fromJSON(json)](#Credential.fromJSON) ⇒ [Credential](#Credential) - - - -### new Credential(values) -Constructs a new [Credential](#Credential). - - -| Param | Type | -| --- | --- | -| values | ICredential | - - - -### credential.context() ⇒ Array.<(string\|Record.<string, any>)> -Returns a copy of the JSON-LD context(s) applicable to the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.id() ⇒ string \| undefined -Returns a copy of the unique `URI` identifying the [Credential](#Credential) . - -**Kind**: instance method of [Credential](#Credential) - - -### credential.type() ⇒ Array.<string> -Returns a copy of the URIs defining the type of the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.credentialSubject() ⇒ Array.<Subject> -Returns a copy of the [Credential](#Credential) subject(s). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.issuer() ⇒ string \| Issuer -Returns a copy of the issuer of the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.issuanceDate() ⇒ [Timestamp](#Timestamp) -Returns a copy of the timestamp of when the [Credential](#Credential) becomes valid. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.expirationDate() ⇒ [Timestamp](#Timestamp) \| undefined -Returns a copy of the timestamp of when the [Credential](#Credential) should no longer be considered valid. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.credentialStatus() ⇒ Array.<Status> -Returns a copy of the information used to determine the current status of the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.credentialSchema() ⇒ Array.<Schema> -Returns a copy of the information used to assist in the enforcement of a specific [Credential](#Credential) structure. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.refreshService() ⇒ Array.<RefreshService> -Returns a copy of the service(s) used to refresh an expired [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.termsOfUse() ⇒ Array.<Policy> -Returns a copy of the terms-of-use specified by the [Credential](#Credential) issuer. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.evidence() ⇒ Array.<Evidence> -Returns a copy of the human-readable evidence used to support the claims within the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.nonTransferable() ⇒ boolean \| undefined -Returns whether or not the [Credential](#Credential) must only be contained within a [Presentation](#Presentation) -with a proof issued from the [Credential](#Credential) subject. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.proof() ⇒ [Proof](#Proof) \| undefined -Optional cryptographic proof, unrelated to JWT. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.properties() ⇒ Map.<string, any> -Returns a copy of the miscellaneous properties on the [Credential](#Credential). - -**Kind**: instance method of [Credential](#Credential) - - -### credential.setProof([proof]) -Sets the `proof` property of the [Credential](#Credential). - -Note that this proof is not related to JWT. - -**Kind**: instance method of [Credential](#Credential) - -| Param | Type | -| --- | --- | -| [proof] | [Proof](#Proof) \| undefined | - - - -### credential.toJwtClaims([custom_claims]) ⇒ Record.<string, any> -Serializes the `Credential` as a JWT claims set -in accordance with [VC Data Model v1.1](https://www.w3.org/TR/vc-data-model/#json-web-token). - -The resulting object can be used as the payload of a JWS when issuing the credential. - -**Kind**: instance method of [Credential](#Credential) - -| Param | Type | -| --- | --- | -| [custom_claims] | Record.<string, any> \| undefined | - - - -### credential.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Credential](#Credential) - - -### credential.clone() ⇒ [Credential](#Credential) -Deep clones the object. - -**Kind**: instance method of [Credential](#Credential) - - -### Credential.BaseContext() ⇒ string -Returns the base JSON-LD context. - -**Kind**: static method of [Credential](#Credential) - - -### Credential.BaseType() ⇒ string -Returns the base type. - -**Kind**: static method of [Credential](#Credential) - - -### Credential.createDomainLinkageCredential(values) ⇒ [Credential](#Credential) -**Kind**: static method of [Credential](#Credential) - -| Param | Type | -| --- | --- | -| values | IDomainLinkageCredential | - - - -### Credential.fromJSON(json) ⇒ [Credential](#Credential) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Credential](#Credential) - -| Param | Type | -| --- | --- | -| json | any | - - - -## CustomMethodData -A custom verification method data format. - -**Kind**: global class - -* [CustomMethodData](#CustomMethodData) - * [new CustomMethodData(name, data)](#new_CustomMethodData_new) - * _instance_ - * [.clone()](#CustomMethodData+clone) ⇒ [CustomMethodData](#CustomMethodData) - * [.toJSON()](#CustomMethodData+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#CustomMethodData.fromJSON) ⇒ [CustomMethodData](#CustomMethodData) - - - -### new CustomMethodData(name, data) - -| Param | Type | -| --- | --- | -| name | string | -| data | any | - - - -### customMethodData.clone() ⇒ [CustomMethodData](#CustomMethodData) -Deep clones the object. - -**Kind**: instance method of [CustomMethodData](#CustomMethodData) - - -### customMethodData.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [CustomMethodData](#CustomMethodData) - - -### CustomMethodData.fromJSON(json) ⇒ [CustomMethodData](#CustomMethodData) -Deserializes an instance from a JSON object. - -**Kind**: static method of [CustomMethodData](#CustomMethodData) - -| Param | Type | -| --- | --- | -| json | any | - - - -## DIDJwk -`did:jwk` DID. - -**Kind**: global class - -* [DIDJwk](#DIDJwk) - * [new DIDJwk(did)](#new_DIDJwk_new) - * _instance_ - * [.jwk()](#DIDJwk+jwk) ⇒ [Jwk](#Jwk) - * [.scheme()](#DIDJwk+scheme) ⇒ string - * [.authority()](#DIDJwk+authority) ⇒ string - * [.method()](#DIDJwk+method) ⇒ string - * [.methodId()](#DIDJwk+methodId) ⇒ string - * [.toString()](#DIDJwk+toString) ⇒ string - * [.toCoreDid()](#DIDJwk+toCoreDid) ⇒ [CoreDID](#CoreDID) - * [.toJSON()](#DIDJwk+toJSON) ⇒ any - * [.clone()](#DIDJwk+clone) ⇒ [DIDJwk](#DIDJwk) - * _static_ - * [.parse(input)](#DIDJwk.parse) ⇒ [DIDJwk](#DIDJwk) - * [.fromJSON(json)](#DIDJwk.fromJSON) ⇒ [DIDJwk](#DIDJwk) - - - -### new DIDJwk(did) -Creates a new [DIDJwk](#DIDJwk) from a [CoreDID](#CoreDID). - -### Errors -Throws an error if the given did is not a valid `did:jwk` DID. - - -| Param | Type | -| --- | --- | -| did | [CoreDID](#CoreDID) \| IToCoreDID | - - - -### didJwk.jwk() ⇒ [Jwk](#Jwk) -Returns the JSON WEB KEY (JWK) encoded inside this `did:jwk`. - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.scheme() ⇒ string -Returns the [CoreDID](#CoreDID) scheme. - -E.g. -- `"did:example:12345678" -> "did"` -- `"did:iota:smr:12345678" -> "did"` - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.authority() ⇒ string -Returns the [CoreDID](#CoreDID) authority: the method name and method-id. - -E.g. -- `"did:example:12345678" -> "example:12345678"` -- `"did:iota:smr:12345678" -> "iota:smr:12345678"` - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.method() ⇒ string -Returns the [CoreDID](#CoreDID) method name. - -E.g. -- `"did:example:12345678" -> "example"` -- `"did:iota:smr:12345678" -> "iota"` - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.methodId() ⇒ string -Returns the [CoreDID](#CoreDID) method-specific ID. - -E.g. -- `"did:example:12345678" -> "12345678"` -- `"did:iota:smr:12345678" -> "smr:12345678"` - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.toString() ⇒ string -Returns the [CoreDID](#CoreDID) as a string. - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.toCoreDid() ⇒ [CoreDID](#CoreDID) -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### didJwk.clone() ⇒ [DIDJwk](#DIDJwk) -Deep clones the object. - -**Kind**: instance method of [DIDJwk](#DIDJwk) - - -### DIDJwk.parse(input) ⇒ [DIDJwk](#DIDJwk) -Parses a [DIDJwk](#DIDJwk) from the given `input`. - -### Errors - -Throws an error if the input is not a valid [DIDJwk](#DIDJwk). - -**Kind**: static method of [DIDJwk](#DIDJwk) - -| Param | Type | -| --- | --- | -| input | string | - - - -### DIDJwk.fromJSON(json) ⇒ [DIDJwk](#DIDJwk) -Deserializes an instance from a JSON object. - -**Kind**: static method of [DIDJwk](#DIDJwk) - -| Param | Type | -| --- | --- | -| json | any | - - - -## DIDUrl -A method agnostic DID Url. - -**Kind**: global class - -* [DIDUrl](#DIDUrl) - * _instance_ - * [.did()](#DIDUrl+did) ⇒ [CoreDID](#CoreDID) - * [.urlStr()](#DIDUrl+urlStr) ⇒ string - * [.fragment()](#DIDUrl+fragment) ⇒ string \| undefined - * [.setFragment([value])](#DIDUrl+setFragment) - * [.path()](#DIDUrl+path) ⇒ string \| undefined - * [.setPath([value])](#DIDUrl+setPath) - * [.query()](#DIDUrl+query) ⇒ string \| undefined - * [.setQuery([value])](#DIDUrl+setQuery) - * [.join(segment)](#DIDUrl+join) ⇒ [DIDUrl](#DIDUrl) - * [.toString()](#DIDUrl+toString) ⇒ string - * [.toJSON()](#DIDUrl+toJSON) ⇒ any - * [.clone()](#DIDUrl+clone) ⇒ [DIDUrl](#DIDUrl) - * _static_ - * [.parse(input)](#DIDUrl.parse) ⇒ [DIDUrl](#DIDUrl) - * [.fromJSON(json)](#DIDUrl.fromJSON) ⇒ [DIDUrl](#DIDUrl) - - - -### didUrl.did() ⇒ [CoreDID](#CoreDID) -Return a copy of the [CoreDID](#CoreDID) section of the [DIDUrl](#DIDUrl). - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.urlStr() ⇒ string -Return a copy of the relative DID Url as a string, including only the path, query, and fragment. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.fragment() ⇒ string \| undefined -Returns a copy of the [DIDUrl](#DIDUrl) method fragment, if any. Excludes the leading '#'. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.setFragment([value]) -Sets the `fragment` component of the [DIDUrl](#DIDUrl). - -**Kind**: instance method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| [value] | string \| undefined | - - - -### didUrl.path() ⇒ string \| undefined -Returns a copy of the [DIDUrl](#DIDUrl) path. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.setPath([value]) -Sets the `path` component of the [DIDUrl](#DIDUrl). - -**Kind**: instance method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| [value] | string \| undefined | - - - -### didUrl.query() ⇒ string \| undefined -Returns a copy of the [DIDUrl](#DIDUrl) method query, if any. Excludes the leading '?'. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.setQuery([value]) -Sets the `query` component of the [DIDUrl](#DIDUrl). - -**Kind**: instance method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| [value] | string \| undefined | - - - -### didUrl.join(segment) ⇒ [DIDUrl](#DIDUrl) -Append a string representing a path, query, and/or fragment, returning a new [DIDUrl](#DIDUrl). - -Must begin with a valid delimiter character: '/', '?', '#'. Overwrites the existing URL -segment and any following segments in order of path, query, then fragment. - -I.e. -- joining a path will clear the query and fragment. -- joining a query will clear the fragment. -- joining a fragment will only overwrite the fragment. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| segment | string | - - - -### didUrl.toString() ⇒ string -Returns the [DIDUrl](#DIDUrl) as a string. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### didUrl.clone() ⇒ [DIDUrl](#DIDUrl) -Deep clones the object. - -**Kind**: instance method of [DIDUrl](#DIDUrl) - - -### DIDUrl.parse(input) ⇒ [DIDUrl](#DIDUrl) -Parses a [DIDUrl](#DIDUrl) from the input string. - -**Kind**: static method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| input | string | - - - -### DIDUrl.fromJSON(json) ⇒ [DIDUrl](#DIDUrl) -Deserializes an instance from a JSON object. - -**Kind**: static method of [DIDUrl](#DIDUrl) - -| Param | Type | -| --- | --- | -| json | any | - - - -## DecodedJptCredential -**Kind**: global class - -* [DecodedJptCredential](#DecodedJptCredential) - * [.clone()](#DecodedJptCredential+clone) ⇒ [DecodedJptCredential](#DecodedJptCredential) - * [.credential()](#DecodedJptCredential+credential) ⇒ [Credential](#Credential) - * [.customClaims()](#DecodedJptCredential+customClaims) ⇒ Map.<string, any> - * [.decodedJwp()](#DecodedJptCredential+decodedJwp) ⇒ [JwpIssued](#JwpIssued) - - - -### decodedJptCredential.clone() ⇒ [DecodedJptCredential](#DecodedJptCredential) -Deep clones the object. - -**Kind**: instance method of [DecodedJptCredential](#DecodedJptCredential) - - -### decodedJptCredential.credential() ⇒ [Credential](#Credential) -Returns the [Credential](#Credential) embedded into this JPT. - -**Kind**: instance method of [DecodedJptCredential](#DecodedJptCredential) - - -### decodedJptCredential.customClaims() ⇒ Map.<string, any> -Returns the custom claims parsed from the JPT. - -**Kind**: instance method of [DecodedJptCredential](#DecodedJptCredential) - - -### decodedJptCredential.decodedJwp() ⇒ [JwpIssued](#JwpIssued) -**Kind**: instance method of [DecodedJptCredential](#DecodedJptCredential) - - -## DecodedJptPresentation -**Kind**: global class - -* [DecodedJptPresentation](#DecodedJptPresentation) - * [.clone()](#DecodedJptPresentation+clone) ⇒ [DecodedJptPresentation](#DecodedJptPresentation) - * [.credential()](#DecodedJptPresentation+credential) ⇒ [Credential](#Credential) - * [.customClaims()](#DecodedJptPresentation+customClaims) ⇒ Map.<string, any> - * [.aud()](#DecodedJptPresentation+aud) ⇒ string \| undefined - - - -### decodedJptPresentation.clone() ⇒ [DecodedJptPresentation](#DecodedJptPresentation) -Deep clones the object. - -**Kind**: instance method of [DecodedJptPresentation](#DecodedJptPresentation) - - -### decodedJptPresentation.credential() ⇒ [Credential](#Credential) -Returns the [Credential](#Credential) embedded into this JPT. - -**Kind**: instance method of [DecodedJptPresentation](#DecodedJptPresentation) - - -### decodedJptPresentation.customClaims() ⇒ Map.<string, any> -Returns the custom claims parsed from the JPT. - -**Kind**: instance method of [DecodedJptPresentation](#DecodedJptPresentation) - - -### decodedJptPresentation.aud() ⇒ string \| undefined -Returns the `aud` property parsed from the JWT claims. - -**Kind**: instance method of [DecodedJptPresentation](#DecodedJptPresentation) - - -## DecodedJws -A cryptographically verified decoded token from a JWS. - -Contains the decoded headers and the raw claims. - -**Kind**: global class - -* [DecodedJws](#DecodedJws) - * [.claims()](#DecodedJws+claims) ⇒ string - * [.claimsBytes()](#DecodedJws+claimsBytes) ⇒ Uint8Array - * [.protectedHeader()](#DecodedJws+protectedHeader) ⇒ [JwsHeader](#JwsHeader) - * [.clone()](#DecodedJws+clone) ⇒ [DecodedJws](#DecodedJws) - * [.toJSON()](#DecodedJws+toJSON) ⇒ any - - - -### decodedJws.claims() ⇒ string -Returns a copy of the parsed claims represented as a string. - -# Errors -An error is thrown if the claims cannot be represented as a string. - -This error can only occur if the Token was decoded from a detached payload. - -**Kind**: instance method of [DecodedJws](#DecodedJws) - - -### decodedJws.claimsBytes() ⇒ Uint8Array -Return a copy of the parsed claims represented as an array of bytes. - -**Kind**: instance method of [DecodedJws](#DecodedJws) - - -### decodedJws.protectedHeader() ⇒ [JwsHeader](#JwsHeader) -Returns a copy of the protected header. - -**Kind**: instance method of [DecodedJws](#DecodedJws) - - -### decodedJws.clone() ⇒ [DecodedJws](#DecodedJws) -Deep clones the object. - -**Kind**: instance method of [DecodedJws](#DecodedJws) - - -### decodedJws.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [DecodedJws](#DecodedJws) - - -## DecodedJwtCredential -A cryptographically verified and decoded Credential. - -Note that having an instance of this type only means the JWS it was constructed from was verified. -It does not imply anything about a potentially present proof property on the credential itself. - -**Kind**: global class - -* [DecodedJwtCredential](#DecodedJwtCredential) - * [.credential()](#DecodedJwtCredential+credential) ⇒ [Credential](#Credential) - * [.protectedHeader()](#DecodedJwtCredential+protectedHeader) ⇒ [JwsHeader](#JwsHeader) - * [.customClaims()](#DecodedJwtCredential+customClaims) ⇒ Record.<string, any> \| undefined - * [.intoCredential()](#DecodedJwtCredential+intoCredential) ⇒ [Credential](#Credential) - - - -### decodedJwtCredential.credential() ⇒ [Credential](#Credential) -Returns a copy of the credential parsed to the [Verifiable Credentials Data model](https://www.w3.org/TR/vc-data-model/). - -**Kind**: instance method of [DecodedJwtCredential](#DecodedJwtCredential) - - -### decodedJwtCredential.protectedHeader() ⇒ [JwsHeader](#JwsHeader) -Returns a copy of the protected header parsed from the decoded JWS. - -**Kind**: instance method of [DecodedJwtCredential](#DecodedJwtCredential) - - -### decodedJwtCredential.customClaims() ⇒ Record.<string, any> \| undefined -The custom claims parsed from the JWT. - -**Kind**: instance method of [DecodedJwtCredential](#DecodedJwtCredential) - - -### decodedJwtCredential.intoCredential() ⇒ [Credential](#Credential) -Consumes the object and returns the decoded credential. - -### Warning - -This destroys the [DecodedJwtCredential](#DecodedJwtCredential) object. - -**Kind**: instance method of [DecodedJwtCredential](#DecodedJwtCredential) - - -## DecodedJwtPresentation -A cryptographically verified and decoded presentation. - -Note that having an instance of this type only means the JWS it was constructed from was verified. -It does not imply anything about a potentially present proof property on the presentation itself. - -**Kind**: global class - -* [DecodedJwtPresentation](#DecodedJwtPresentation) - * [.presentation()](#DecodedJwtPresentation+presentation) ⇒ [Presentation](#Presentation) - * [.protectedHeader()](#DecodedJwtPresentation+protectedHeader) ⇒ [JwsHeader](#JwsHeader) - * [.intoPresentation()](#DecodedJwtPresentation+intoPresentation) ⇒ [Presentation](#Presentation) - * [.expirationDate()](#DecodedJwtPresentation+expirationDate) ⇒ [Timestamp](#Timestamp) \| undefined - * [.issuanceDate()](#DecodedJwtPresentation+issuanceDate) ⇒ [Timestamp](#Timestamp) \| undefined - * [.audience()](#DecodedJwtPresentation+audience) ⇒ string \| undefined - * [.customClaims()](#DecodedJwtPresentation+customClaims) ⇒ Record.<string, any> \| undefined - - - -### decodedJwtPresentation.presentation() ⇒ [Presentation](#Presentation) -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.protectedHeader() ⇒ [JwsHeader](#JwsHeader) -Returns a copy of the protected header parsed from the decoded JWS. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.intoPresentation() ⇒ [Presentation](#Presentation) -Consumes the object and returns the decoded presentation. - -### Warning -This destroys the [DecodedJwtPresentation](#DecodedJwtPresentation) object. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.expirationDate() ⇒ [Timestamp](#Timestamp) \| undefined -The expiration date parsed from the JWT claims. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.issuanceDate() ⇒ [Timestamp](#Timestamp) \| undefined -The issuance date parsed from the JWT claims. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.audience() ⇒ string \| undefined -The `aud` property parsed from JWT claims. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -### decodedJwtPresentation.customClaims() ⇒ Record.<string, any> \| undefined -The custom claims parsed from the JWT. - -**Kind**: instance method of [DecodedJwtPresentation](#DecodedJwtPresentation) - - -## Disclosure -Represents an elements constructing a disclosure. -Object properties and array elements disclosures are supported. - -See: https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html#name-disclosures - -**Kind**: global class - -* [Disclosure](#Disclosure) - * [new Disclosure(salt, claim_name, claim_value)](#new_Disclosure_new) - * _instance_ - * [.disclosure()](#Disclosure+disclosure) ⇒ string - * [.toEncodedString()](#Disclosure+toEncodedString) ⇒ string - * [.toString()](#Disclosure+toString) ⇒ string - * [.salt()](#Disclosure+salt) ⇒ string - * [.claimName()](#Disclosure+claimName) ⇒ string \| undefined - * [.claimValue()](#Disclosure+claimValue) ⇒ any - * [.toJSON()](#Disclosure+toJSON) ⇒ any - * _static_ - * [.parse(disclosure)](#Disclosure.parse) ⇒ [Disclosure](#Disclosure) - * [.fromJSON(json)](#Disclosure.fromJSON) ⇒ [Disclosure](#Disclosure) - - - -### new Disclosure(salt, claim_name, claim_value) - -| Param | Type | -| --- | --- | -| salt | string | -| claim_name | string \| undefined | -| claim_value | any | - - - -### disclosure.disclosure() ⇒ string -Returns a copy of the base64url-encoded string. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.toEncodedString() ⇒ string -Returns a copy of the base64url-encoded string. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.toString() ⇒ string -Returns a copy of the base64url-encoded string. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.salt() ⇒ string -Returns a copy of the salt value. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.claimName() ⇒ string \| undefined -Returns a copy of the claim name, optional for array elements. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.claimValue() ⇒ any -Returns a copy of the claim Value which can be of any type. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### disclosure.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Disclosure](#Disclosure) - - -### Disclosure.parse(disclosure) ⇒ [Disclosure](#Disclosure) -Parses a Base64 encoded disclosure into a `Disclosure`. - -## Error - -Returns an `InvalidDisclosure` if input is not a valid disclosure. - -**Kind**: static method of [Disclosure](#Disclosure) - -| Param | Type | -| --- | --- | -| disclosure | string | - - - -### Disclosure.fromJSON(json) ⇒ [Disclosure](#Disclosure) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Disclosure](#Disclosure) - -| Param | Type | -| --- | --- | -| json | any | - - - -## DomainLinkageConfiguration -DID Configuration Resource which contains Domain Linkage Credentials. -It can be placed in an origin's `.well-known` directory to prove linkage between the origin and a DID. -See: - -Note: -- Only the [JSON Web Token Proof Format](https://identity.foundation/.well-known/resources/did-configuration/#json-web-token-proof-format) - -**Kind**: global class - -* [DomainLinkageConfiguration](#DomainLinkageConfiguration) - * [new DomainLinkageConfiguration(linkedDids)](#new_DomainLinkageConfiguration_new) - * _instance_ - * [.linkedDids()](#DomainLinkageConfiguration+linkedDids) ⇒ [Array.<Jwt>](#Jwt) - * [.issuers()](#DomainLinkageConfiguration+issuers) ⇒ [Array.<CoreDID>](#CoreDID) - * [.toJSON()](#DomainLinkageConfiguration+toJSON) ⇒ any - * [.clone()](#DomainLinkageConfiguration+clone) ⇒ [DomainLinkageConfiguration](#DomainLinkageConfiguration) - * _static_ - * [.fromJSON(json)](#DomainLinkageConfiguration.fromJSON) ⇒ [DomainLinkageConfiguration](#DomainLinkageConfiguration) - - - -### new DomainLinkageConfiguration(linkedDids) -Constructs a new [DomainLinkageConfiguration](#DomainLinkageConfiguration). - - -| Param | Type | -| --- | --- | -| linkedDids | [Array.<Jwt>](#Jwt) | - - - -### domainLinkageConfiguration.linkedDids() ⇒ [Array.<Jwt>](#Jwt) -List of the Domain Linkage Credentials. - -**Kind**: instance method of [DomainLinkageConfiguration](#DomainLinkageConfiguration) - - -### domainLinkageConfiguration.issuers() ⇒ [Array.<CoreDID>](#CoreDID) -List of the issuers of the Domain Linkage Credentials. - -**Kind**: instance method of [DomainLinkageConfiguration](#DomainLinkageConfiguration) - - -### domainLinkageConfiguration.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [DomainLinkageConfiguration](#DomainLinkageConfiguration) - - -### domainLinkageConfiguration.clone() ⇒ [DomainLinkageConfiguration](#DomainLinkageConfiguration) -Deep clones the object. - -**Kind**: instance method of [DomainLinkageConfiguration](#DomainLinkageConfiguration) - - -### DomainLinkageConfiguration.fromJSON(json) ⇒ [DomainLinkageConfiguration](#DomainLinkageConfiguration) -Deserializes an instance from a JSON object. - -**Kind**: static method of [DomainLinkageConfiguration](#DomainLinkageConfiguration) - -| Param | Type | -| --- | --- | -| json | any | - - - -## Duration -A span of time. - -**Kind**: global class - -* [Duration](#Duration) - * _instance_ - * [.toJSON()](#Duration+toJSON) ⇒ any - * _static_ - * [.seconds(seconds)](#Duration.seconds) ⇒ [Duration](#Duration) - * [.minutes(minutes)](#Duration.minutes) ⇒ [Duration](#Duration) - * [.hours(hours)](#Duration.hours) ⇒ [Duration](#Duration) - * [.days(days)](#Duration.days) ⇒ [Duration](#Duration) - * [.weeks(weeks)](#Duration.weeks) ⇒ [Duration](#Duration) - * [.fromJSON(json)](#Duration.fromJSON) ⇒ [Duration](#Duration) - - - -### duration.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Duration](#Duration) - - -### Duration.seconds(seconds) ⇒ [Duration](#Duration) -Create a new [Duration](#Duration) with the given number of seconds. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| seconds | number | - - - -### Duration.minutes(minutes) ⇒ [Duration](#Duration) -Create a new [Duration](#Duration) with the given number of minutes. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| minutes | number | - - - -### Duration.hours(hours) ⇒ [Duration](#Duration) -Create a new [Duration](#Duration) with the given number of hours. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| hours | number | - - - -### Duration.days(days) ⇒ [Duration](#Duration) -Create a new [Duration](#Duration) with the given number of days. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| days | number | - - - -### Duration.weeks(weeks) ⇒ [Duration](#Duration) -Create a new [Duration](#Duration) with the given number of weeks. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| weeks | number | - - - -### Duration.fromJSON(json) ⇒ [Duration](#Duration) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Duration](#Duration) - -| Param | Type | -| --- | --- | -| json | any | - - - -## EcDSAJwsVerifier -An implementor of `IJwsVerifier` that can handle the -`EcDSA` algorithm. - -**Kind**: global class - -* [EcDSAJwsVerifier](#EcDSAJwsVerifier) - * [new EcDSAJwsVerifier()](#new_EcDSAJwsVerifier_new) - * [.verify(alg, signingInput, decodedSignature, publicKey)](#EcDSAJwsVerifier+verify) - - - -### new EcDSAJwsVerifier() -Constructs an EcDSAJwsVerifier. - - - -### ecDSAJwsVerifier.verify(alg, signingInput, decodedSignature, publicKey) -Verify a JWS signature secured with the `EcDSA` algorithm. -Only the `ES256` and `ES256K` curves are supported for now. - -# Warning - -This function does not check the `alg` property in the protected header. Callers are expected to assert this -prior to calling the function. - -**Kind**: instance method of [EcDSAJwsVerifier](#EcDSAJwsVerifier) - -| Param | Type | -| --- | --- | -| alg | JwsAlgorithm | -| signingInput | Uint8Array | -| decodedSignature | Uint8Array | -| publicKey | [Jwk](#Jwk) | - - - -## EdDSAJwsVerifier -An implementor of `IJwsVerifier` that can handle the -`EdDSA` algorithm. - -**Kind**: global class - -* [EdDSAJwsVerifier](#EdDSAJwsVerifier) - * [new EdDSAJwsVerifier()](#new_EdDSAJwsVerifier_new) - * [.verify(alg, signingInput, decodedSignature, publicKey)](#EdDSAJwsVerifier+verify) - - - -### new EdDSAJwsVerifier() -Constructs an EdDSAJwsVerifier. - - - -### edDSAJwsVerifier.verify(alg, signingInput, decodedSignature, publicKey) -Verify a JWS signature secured with the `EdDSA` algorithm. -Only the `Ed25519` curve is supported for now. - -This function is useful when one is building an `IJwsVerifier` that extends the default provided by -the IOTA Identity Framework. - -# Warning - -This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this -prior to calling the function. - -**Kind**: instance method of [EdDSAJwsVerifier](#EdDSAJwsVerifier) - -| Param | Type | -| --- | --- | -| alg | JwsAlgorithm | -| signingInput | Uint8Array | -| decodedSignature | Uint8Array | -| publicKey | [Jwk](#Jwk) | - - - -## IotaDID -A DID conforming to the IOTA DID method specification. - -**Kind**: global class - -* [IotaDID](#IotaDID) - * [new IotaDID(bytes, network)](#new_IotaDID_new) - * _instance_ - * [.network()](#IotaDID+network) ⇒ string - * [.tag()](#IotaDID+tag) ⇒ string - * [.toCoreDid()](#IotaDID+toCoreDid) ⇒ [CoreDID](#CoreDID) - * [.scheme()](#IotaDID+scheme) ⇒ string - * [.authority()](#IotaDID+authority) ⇒ string - * [.method()](#IotaDID+method) ⇒ string - * [.methodId()](#IotaDID+methodId) ⇒ string - * [.join(segment)](#IotaDID+join) ⇒ [DIDUrl](#DIDUrl) - * [.toUrl()](#IotaDID+toUrl) ⇒ [DIDUrl](#DIDUrl) - * [.toAliasId()](#IotaDID+toAliasId) ⇒ string - * [.intoUrl()](#IotaDID+intoUrl) ⇒ [DIDUrl](#DIDUrl) - * [.toString()](#IotaDID+toString) ⇒ string - * [.toJSON()](#IotaDID+toJSON) ⇒ any - * [.clone()](#IotaDID+clone) ⇒ [IotaDID](#IotaDID) - * _static_ - * [.METHOD](#IotaDID.METHOD) ⇒ string - * [.DEFAULT_NETWORK](#IotaDID.DEFAULT_NETWORK) ⇒ string - * [.fromAliasId(aliasId, network)](#IotaDID.fromAliasId) ⇒ [IotaDID](#IotaDID) - * [.placeholder(network)](#IotaDID.placeholder) ⇒ [IotaDID](#IotaDID) - * [.parse(input)](#IotaDID.parse) ⇒ [IotaDID](#IotaDID) - * [.fromJSON(json)](#IotaDID.fromJSON) ⇒ [IotaDID](#IotaDID) - - - -### new IotaDID(bytes, network) -Constructs a new [IotaDID](#IotaDID) from a byte representation of the tag and the given -network name. - -See also [placeholder](#IotaDID.placeholder). - - -| Param | Type | -| --- | --- | -| bytes | Uint8Array | -| network | string | - - - -### did.network() ⇒ string -Returns the Tangle network name of the [IotaDID](#IotaDID). - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.tag() ⇒ string -Returns a copy of the unique tag of the [IotaDID](#IotaDID). - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.toCoreDid() ⇒ [CoreDID](#CoreDID) -Returns the DID represented as a [CoreDID](#CoreDID). - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.scheme() ⇒ string -Returns the `DID` scheme. - -E.g. -- `"did:example:12345678" -> "did"` -- `"did:iota:main:12345678" -> "did"` - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.authority() ⇒ string -Returns the `DID` authority: the method name and method-id. - -E.g. -- `"did:example:12345678" -> "example:12345678"` -- `"did:iota:main:12345678" -> "iota:main:12345678"` - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.method() ⇒ string -Returns the `DID` method name. - -E.g. -- `"did:example:12345678" -> "example"` -- `"did:iota:main:12345678" -> "iota"` - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.methodId() ⇒ string -Returns the `DID` method-specific ID. - -E.g. -- `"did:example:12345678" -> "12345678"` -- `"did:iota:main:12345678" -> "main:12345678"` - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.join(segment) ⇒ [DIDUrl](#DIDUrl) -Construct a new [DIDUrl](#DIDUrl) by joining with a relative DID Url string. - -**Kind**: instance method of [IotaDID](#IotaDID) - -| Param | Type | -| --- | --- | -| segment | string | - - - -### did.toUrl() ⇒ [DIDUrl](#DIDUrl) -Clones the `DID` into a [DIDUrl](#DIDUrl). - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.toAliasId() ⇒ string -Returns the hex-encoded AliasId with a '0x' prefix, from the DID tag. - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.intoUrl() ⇒ [DIDUrl](#DIDUrl) -Converts the `DID` into a [DIDUrl](#DIDUrl), consuming it. - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.toString() ⇒ string -Returns the `DID` as a string. - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### did.clone() ⇒ [IotaDID](#IotaDID) -Deep clones the object. - -**Kind**: instance method of [IotaDID](#IotaDID) - - -### IotaDID.METHOD ⇒ string -The IOTA DID method name (`"iota"`). - -**Kind**: static property of [IotaDID](#IotaDID) - - -### IotaDID.DEFAULT\_NETWORK ⇒ string -The default Tangle network (`"iota"`). - -**Kind**: static property of [IotaDID](#IotaDID) - - -### IotaDID.fromAliasId(aliasId, network) ⇒ [IotaDID](#IotaDID) -Constructs a new [IotaDID](#IotaDID) from a hex representation of an Alias Id and the given -network name. - -**Kind**: static method of [IotaDID](#IotaDID) - -| Param | Type | -| --- | --- | -| aliasId | string | -| network | string | - - - -### IotaDID.placeholder(network) ⇒ [IotaDID](#IotaDID) -Creates a new placeholder [IotaDID](#IotaDID) with the given network name. - -E.g. `did:iota:smr:0x0000000000000000000000000000000000000000000000000000000000000000`. - -**Kind**: static method of [IotaDID](#IotaDID) - -| Param | Type | -| --- | --- | -| network | string | - - - -### IotaDID.parse(input) ⇒ [IotaDID](#IotaDID) -Parses a [IotaDID](#IotaDID) from the input string. - -**Kind**: static method of [IotaDID](#IotaDID) - -| Param | Type | -| --- | --- | -| input | string | - - - -### IotaDID.fromJSON(json) ⇒ [IotaDID](#IotaDID) -Deserializes an instance from a JSON object. - -**Kind**: static method of [IotaDID](#IotaDID) - -| Param | Type | -| --- | --- | -| json | any | - - - -## IotaDocument -A DID Document adhering to the IOTA DID method specification. - -Note: All methods that involve reading from this class may potentially raise an error -if the object is being concurrently modified. - -**Kind**: global class - -* [IotaDocument](#IotaDocument) - * [new IotaDocument(network)](#new_IotaDocument_new) - * _instance_ - * [.id()](#IotaDocument+id) ⇒ [IotaDID](#IotaDID) - * [.controller()](#IotaDocument+controller) ⇒ [Array.<IotaDID>](#IotaDID) - * [.setController(controller)](#IotaDocument+setController) - * [.alsoKnownAs()](#IotaDocument+alsoKnownAs) ⇒ Array.<string> - * [.setAlsoKnownAs(urls)](#IotaDocument+setAlsoKnownAs) - * [.properties()](#IotaDocument+properties) ⇒ Map.<string, any> - * [.setPropertyUnchecked(key, value)](#IotaDocument+setPropertyUnchecked) - * [.service()](#IotaDocument+service) ⇒ [Array.<Service>](#Service) - * [.insertService(service)](#IotaDocument+insertService) - * [.removeService(did)](#IotaDocument+removeService) ⇒ [Service](#Service) \| undefined - * [.resolveService(query)](#IotaDocument+resolveService) ⇒ [Service](#Service) \| undefined - * [.methods([scope])](#IotaDocument+methods) ⇒ [Array.<VerificationMethod>](#VerificationMethod) - * [.insertMethod(method, scope)](#IotaDocument+insertMethod) - * [.removeMethod(did)](#IotaDocument+removeMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined - * [.resolveMethod(query, [scope])](#IotaDocument+resolveMethod) ⇒ [VerificationMethod](#VerificationMethod) \| undefined - * [.attachMethodRelationship(didUrl, relationship)](#IotaDocument+attachMethodRelationship) ⇒ boolean - * [.detachMethodRelationship(didUrl, relationship)](#IotaDocument+detachMethodRelationship) ⇒ boolean - * [.verifyJws(jws, options, [signatureVerifier], [detachedPayload])](#IotaDocument+verifyJws) ⇒ [DecodedJws](#DecodedJws) - * [.pack()](#IotaDocument+pack) ⇒ Uint8Array - * [.packWithEncoding(encoding)](#IotaDocument+packWithEncoding) ⇒ Uint8Array - * [.metadata()](#IotaDocument+metadata) ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) - * [.metadataCreated()](#IotaDocument+metadataCreated) ⇒ [Timestamp](#Timestamp) \| undefined - * [.setMetadataCreated(timestamp)](#IotaDocument+setMetadataCreated) - * [.metadataUpdated()](#IotaDocument+metadataUpdated) ⇒ [Timestamp](#Timestamp) \| undefined - * [.setMetadataUpdated(timestamp)](#IotaDocument+setMetadataUpdated) - * [.metadataDeactivated()](#IotaDocument+metadataDeactivated) ⇒ boolean \| undefined - * [.setMetadataDeactivated([deactivated])](#IotaDocument+setMetadataDeactivated) - * [.metadataStateControllerAddress()](#IotaDocument+metadataStateControllerAddress) ⇒ string \| undefined - * [.metadataGovernorAddress()](#IotaDocument+metadataGovernorAddress) ⇒ string \| undefined - * [.setMetadataPropertyUnchecked(key, value)](#IotaDocument+setMetadataPropertyUnchecked) - * [.revokeCredentials(serviceQuery, indices)](#IotaDocument+revokeCredentials) - * [.unrevokeCredentials(serviceQuery, indices)](#IotaDocument+unrevokeCredentials) - * [.clone()](#IotaDocument+clone) ⇒ [IotaDocument](#IotaDocument) - * [._shallowCloneInternal()](#IotaDocument+_shallowCloneInternal) ⇒ [IotaDocument](#IotaDocument) - * [._strongCountInternal()](#IotaDocument+_strongCountInternal) ⇒ number - * [.toJSON()](#IotaDocument+toJSON) ⇒ any - * [.toCoreDocument()](#IotaDocument+toCoreDocument) ⇒ [CoreDocument](#CoreDocument) - * [.generateMethod(storage, keyType, alg, fragment, scope)](#IotaDocument+generateMethod) ⇒ Promise.<string> - * [.purgeMethod(storage, id)](#IotaDocument+purgeMethod) ⇒ Promise.<void> - * ~~[.createJwt(storage, fragment, payload, options)](#IotaDocument+createJwt) ⇒ [Promise.<Jws>](#Jws)~~ - * [.createJws(storage, fragment, payload, options)](#IotaDocument+createJws) ⇒ [Promise.<Jws>](#Jws) - * [.createCredentialJwt(storage, fragment, credential, options, [custom_claims])](#IotaDocument+createCredentialJwt) ⇒ [Promise.<Jwt>](#Jwt) - * [.createPresentationJwt(storage, fragment, presentation, signature_options, presentation_options)](#IotaDocument+createPresentationJwt) ⇒ [Promise.<Jwt>](#Jwt) - * [.generateMethodJwp(storage, alg, fragment, scope)](#IotaDocument+generateMethodJwp) ⇒ Promise.<string> - * [.createIssuedJwp(storage, fragment, jpt_claims, options)](#IotaDocument+createIssuedJwp) ⇒ Promise.<string> - * [.createPresentedJwp(presentation, method_id, options)](#IotaDocument+createPresentedJwp) ⇒ Promise.<string> - * [.createCredentialJpt(credential, storage, fragment, options, [custom_claims])](#IotaDocument+createCredentialJpt) ⇒ [Promise.<Jpt>](#Jpt) - * [.createPresentationJpt(presentation, method_id, options)](#IotaDocument+createPresentationJpt) ⇒ [Promise.<Jpt>](#Jpt) - * _static_ - * [.newWithId(id)](#IotaDocument.newWithId) ⇒ [IotaDocument](#IotaDocument) - * [.unpackFromOutput(did, aliasOutput, allowEmpty)](#IotaDocument.unpackFromOutput) ⇒ [IotaDocument](#IotaDocument) - * [.unpackFromBlock(network, block)](#IotaDocument.unpackFromBlock) ⇒ [Array.<IotaDocument>](#IotaDocument) - * [.fromJSON(json)](#IotaDocument.fromJSON) ⇒ [IotaDocument](#IotaDocument) - - - -### new IotaDocument(network) -Constructs an empty IOTA DID Document with a [placeholder](#IotaDID.placeholder) identifier -for the given `network`. - - -| Param | Type | -| --- | --- | -| network | string | - - - -### iotaDocument.id() ⇒ [IotaDID](#IotaDID) -Returns a copy of the DID Document `id`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.controller() ⇒ [Array.<IotaDID>](#IotaDID) -Returns a copy of the list of document controllers. - -NOTE: controllers are determined by the `state_controller` unlock condition of the output -during resolution and are omitted when publishing. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setController(controller) -Sets the controllers of the document. - -Note: Duplicates will be ignored. -Use `null` to remove all controllers. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| controller | [Array.<IotaDID>](#IotaDID) \| null | - - - -### iotaDocument.alsoKnownAs() ⇒ Array.<string> -Returns a copy of the document's `alsoKnownAs` set. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setAlsoKnownAs(urls) -Sets the `alsoKnownAs` property in the DID document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| urls | string \| Array.<string> \| null | - - - -### iotaDocument.properties() ⇒ Map.<string, any> -Returns a copy of the custom DID Document properties. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setPropertyUnchecked(key, value) -Sets a custom property in the DID Document. -If the value is set to `null`, the custom property will be removed. - -### WARNING - -This method can overwrite existing properties like `id` and result in an invalid document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| key | string | -| value | any | - - - -### iotaDocument.service() ⇒ [Array.<Service>](#Service) -Return a set of all [Service](#Service) in the document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.insertService(service) -Add a new [Service](#Service) to the document. - -Returns `true` if the service was added. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| service | [Service](#Service) | - - - -### iotaDocument.removeService(did) ⇒ [Service](#Service) \| undefined -Remove a [Service](#Service) identified by the given [DIDUrl](#DIDUrl) from the document. - -Returns `true` if a service was removed. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| did | [DIDUrl](#DIDUrl) | - - - -### iotaDocument.resolveService(query) ⇒ [Service](#Service) \| undefined -Returns the first [Service](#Service) with an `id` property matching the provided `query`, -if present. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| query | [DIDUrl](#DIDUrl) \| string | - - - -### iotaDocument.methods([scope]) ⇒ [Array.<VerificationMethod>](#VerificationMethod) -Returns a list of all [VerificationMethod](#VerificationMethod) in the DID Document, -whose verification relationship matches `scope`. - -If `scope` is not set, a list over the **embedded** methods is returned. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| [scope] | [MethodScope](#MethodScope) \| undefined | - - - -### iotaDocument.insertMethod(method, scope) -Adds a new `method` to the document in the given `scope`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| method | [VerificationMethod](#VerificationMethod) | -| scope | [MethodScope](#MethodScope) | - - - -### iotaDocument.removeMethod(did) ⇒ [VerificationMethod](#VerificationMethod) \| undefined -Removes all references to the specified Verification Method. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| did | [DIDUrl](#DIDUrl) | - - - -### iotaDocument.resolveMethod(query, [scope]) ⇒ [VerificationMethod](#VerificationMethod) \| undefined -Returns a copy of the first verification method with an `id` property -matching the provided `query` and the verification relationship -specified by `scope`, if present. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| query | [DIDUrl](#DIDUrl) \| string | -| [scope] | [MethodScope](#MethodScope) \| undefined | - - - -### iotaDocument.attachMethodRelationship(didUrl, relationship) ⇒ boolean -Attaches the relationship to the given method, if the method exists. - -Note: The method needs to be in the set of verification methods, -so it cannot be an embedded one. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| didUrl | [DIDUrl](#DIDUrl) | -| relationship | [MethodRelationship](#MethodRelationship) | - - - -### iotaDocument.detachMethodRelationship(didUrl, relationship) ⇒ boolean -Detaches the given relationship from the given method, if the method exists. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| didUrl | [DIDUrl](#DIDUrl) | -| relationship | [MethodRelationship](#MethodRelationship) | - - - -### iotaDocument.verifyJws(jws, options, [signatureVerifier], [detachedPayload]) ⇒ [DecodedJws](#DecodedJws) -Decodes and verifies the provided JWS according to the passed `options` and `signatureVerifier`. - If no `signatureVerifier` argument is provided a default verifier will be used that is (only) capable of -verifying EdDSA signatures. - -Regardless of which options are passed the following conditions must be met in order for a verification attempt to -take place. -- The JWS must be encoded according to the JWS compact serialization. -- The `kid` value in the protected header must be an identifier of a verification method in this DID document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| jws | [Jws](#Jws) | -| options | [JwsVerificationOptions](#JwsVerificationOptions) | -| [signatureVerifier] | IJwsVerifier \| undefined | -| [detachedPayload] | string \| undefined | - - - -### iotaDocument.pack() ⇒ Uint8Array -Serializes the document for inclusion in an Alias Output's state metadata -with the default [StateMetadataEncoding](#StateMetadataEncoding). - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.packWithEncoding(encoding) ⇒ Uint8Array -Serializes the document for inclusion in an Alias Output's state metadata. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| encoding | [StateMetadataEncoding](#StateMetadataEncoding) | - - - -### iotaDocument.metadata() ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) -Returns a copy of the metadata associated with this document. - -NOTE: Copies all the metadata. See also `metadataCreated`, `metadataUpdated`, -`metadataPreviousMessageId`, `metadataProof` if only a subset of the metadata required. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.metadataCreated() ⇒ [Timestamp](#Timestamp) \| undefined -Returns a copy of the timestamp of when the DID document was created. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setMetadataCreated(timestamp) -Sets the timestamp of when the DID document was created. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| timestamp | [Timestamp](#Timestamp) \| undefined | - - - -### iotaDocument.metadataUpdated() ⇒ [Timestamp](#Timestamp) \| undefined -Returns a copy of the timestamp of the last DID document update. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setMetadataUpdated(timestamp) -Sets the timestamp of the last DID document update. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| timestamp | [Timestamp](#Timestamp) \| undefined | - - - -### iotaDocument.metadataDeactivated() ⇒ boolean \| undefined -Returns a copy of the deactivated status of the DID document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setMetadataDeactivated([deactivated]) -Sets the deactivated status of the DID document. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| [deactivated] | boolean \| undefined | - - - -### iotaDocument.metadataStateControllerAddress() ⇒ string \| undefined -Returns a copy of the Bech32-encoded state controller address, if present. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.metadataGovernorAddress() ⇒ string \| undefined -Returns a copy of the Bech32-encoded governor address, if present. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.setMetadataPropertyUnchecked(key, value) -Sets a custom property in the document metadata. -If the value is set to `null`, the custom property will be removed. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| key | string | -| value | any | - - - -### iotaDocument.revokeCredentials(serviceQuery, indices) -If the document has a [RevocationBitmap](#RevocationBitmap) service identified by `serviceQuery`, -revoke all specified `indices`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| serviceQuery | [DIDUrl](#DIDUrl) \| string | -| indices | number \| Array.<number> | - - - -### iotaDocument.unrevokeCredentials(serviceQuery, indices) -If the document has a [RevocationBitmap](#RevocationBitmap) service identified by `serviceQuery`, -unrevoke all specified `indices`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| serviceQuery | [DIDUrl](#DIDUrl) \| string | -| indices | number \| Array.<number> | - - - -### iotaDocument.clone() ⇒ [IotaDocument](#IotaDocument) -Returns a deep clone of the [IotaDocument](#IotaDocument). - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.\_shallowCloneInternal() ⇒ [IotaDocument](#IotaDocument) -### Warning -This is for internal use only. Do not rely on or call this method. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.\_strongCountInternal() ⇒ number -### Warning -This is for internal use only. Do not rely on or call this method. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.toJSON() ⇒ any -Serializes to a plain JS representation. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.toCoreDocument() ⇒ [CoreDocument](#CoreDocument) -Transforms the [IotaDocument](#IotaDocument) to its [CoreDocument](#CoreDocument) representation. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - - -### iotaDocument.generateMethod(storage, keyType, alg, fragment, scope) ⇒ Promise.<string> -Generate new key material in the given `storage` and insert a new verification method with the corresponding -public key material into the DID document. - -- If no fragment is given the `kid` of the generated JWK is used, if it is set, otherwise an error is returned. -- The `keyType` must be compatible with the given `storage`. `Storage`s are expected to export key type constants -for that use case. - -The fragment of the generated method is returned. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| keyType | string | -| alg | JwsAlgorithm | -| fragment | string \| undefined | -| scope | [MethodScope](#MethodScope) | - - - -### iotaDocument.purgeMethod(storage, id) ⇒ Promise.<void> -Remove the method identified by the given fragment from the document and delete the corresponding key material in -the given `storage`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| id | [DIDUrl](#DIDUrl) | - - - -### ~~iotaDocument.createJwt(storage, fragment, payload, options) ⇒ [Promise.<Jws>](#Jws)~~ -***Deprecated*** - -Sign the `payload` according to `options` with the storage backed private key corresponding to the public key -material in the verification method identified by the given `fragment. - -Upon success a string representing a JWS encoded according to the Compact JWS Serialization format is returned. -See [RFC7515 section 3.1](https://www.rfc-editor.org/rfc/rfc7515#section-3.1). - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| payload | string | -| options | [JwsSignatureOptions](#JwsSignatureOptions) | - - - -### iotaDocument.createJws(storage, fragment, payload, options) ⇒ [Promise.<Jws>](#Jws) -Sign the `payload` according to `options` with the storage backed private key corresponding to the public key -material in the verification method identified by the given `fragment. - -Upon success a string representing a JWS encoded according to the Compact JWS Serialization format is returned. -See [RFC7515 section 3.1](https://www.rfc-editor.org/rfc/rfc7515#section-3.1). - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| payload | string | -| options | [JwsSignatureOptions](#JwsSignatureOptions) | - - - -### iotaDocument.createCredentialJwt(storage, fragment, credential, options, [custom_claims]) ⇒ [Promise.<Jwt>](#Jwt) -Produces a JWS where the payload is produced from the given `credential` -in accordance with [VC Data Model v1.1](https://www.w3.org/TR/vc-data-model/#json-web-token). - -Unless the `kid` is explicitly set in the options, the `kid` in the protected header is the `id` -of the method identified by `fragment` and the JWS signature will be produced by the corresponding -private key backed by the `storage` in accordance with the passed `options`. - -The `custom_claims` can be used to set additional claims on the resulting JWT. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| credential | [Credential](#Credential) | -| options | [JwsSignatureOptions](#JwsSignatureOptions) | -| [custom_claims] | Record.<string, any> \| undefined | - - - -### iotaDocument.createPresentationJwt(storage, fragment, presentation, signature_options, presentation_options) ⇒ [Promise.<Jwt>](#Jwt) -Produces a JWT where the payload is produced from the given presentation. -in accordance with [VC Data Model v1.1](https://www.w3.org/TR/vc-data-model/#json-web-token). - -Unless the `kid` is explicitly set in the options, the `kid` in the protected header is the `id` -of the method identified by `fragment` and the JWS signature will be produced by the corresponding -private key backed by the `storage` in accordance with the passed `options`. - -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| presentation | [Presentation](#Presentation) | -| signature_options | [JwsSignatureOptions](#JwsSignatureOptions) | -| presentation_options | [JwtPresentationOptions](#JwtPresentationOptions) | - - - -### iotaDocument.generateMethodJwp(storage, alg, fragment, scope) ⇒ Promise.<string> -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| alg | [ProofAlgorithm](#ProofAlgorithm) | -| fragment | string \| undefined | -| scope | [MethodScope](#MethodScope) | - - - -### iotaDocument.createIssuedJwp(storage, fragment, jpt_claims, options) ⇒ Promise.<string> -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| storage | [Storage](#Storage) | -| fragment | string | -| jpt_claims | JptClaims | -| options | [JwpCredentialOptions](#JwpCredentialOptions) | - - - -### iotaDocument.createPresentedJwp(presentation, method_id, options) ⇒ Promise.<string> -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| presentation | [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) | -| method_id | string | -| options | [JwpPresentationOptions](#JwpPresentationOptions) | - - - -### iotaDocument.createCredentialJpt(credential, storage, fragment, options, [custom_claims]) ⇒ [Promise.<Jpt>](#Jpt) -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| storage | [Storage](#Storage) | -| fragment | string | -| options | [JwpCredentialOptions](#JwpCredentialOptions) | -| [custom_claims] | Map.<string, any> \| undefined | - - - -### iotaDocument.createPresentationJpt(presentation, method_id, options) ⇒ [Promise.<Jpt>](#Jpt) -**Kind**: instance method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| presentation | [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) | -| method_id | string | -| options | [JwpPresentationOptions](#JwpPresentationOptions) | - - - -### IotaDocument.newWithId(id) ⇒ [IotaDocument](#IotaDocument) -Constructs an empty DID Document with the given identifier. - -**Kind**: static method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| id | [IotaDID](#IotaDID) | - - - -### IotaDocument.unpackFromOutput(did, aliasOutput, allowEmpty) ⇒ [IotaDocument](#IotaDocument) -Deserializes the document from an Alias Output. - -If `allowEmpty` is true, this will return an empty DID document marked as `deactivated` -if `stateMetadata` is empty. - -The `tokenSupply` must be equal to the token supply of the network the DID is associated with. - -NOTE: `did` is required since it is omitted from the serialized DID Document and -cannot be inferred from the state metadata. It also indicates the network, which is not -encoded in the `AliasId` alone. - -**Kind**: static method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| did | [IotaDID](#IotaDID) | -| aliasOutput | AliasOutputBuilderParams | -| allowEmpty | boolean | - - - -### IotaDocument.unpackFromBlock(network, block) ⇒ [Array.<IotaDocument>](#IotaDocument) -Returns all DID documents of the Alias Outputs contained in the block's transaction payload -outputs, if any. - -Errors if any Alias Output does not contain a valid or empty DID Document. - -**Kind**: static method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| network | string | -| block | Block | - - - -### IotaDocument.fromJSON(json) ⇒ [IotaDocument](#IotaDocument) -Deserializes an instance from a plain JS representation. - -**Kind**: static method of [IotaDocument](#IotaDocument) - -| Param | Type | -| --- | --- | -| json | any | - - - -## IotaDocumentMetadata -Additional attributes related to an IOTA DID Document. - -**Kind**: global class - -* [IotaDocumentMetadata](#IotaDocumentMetadata) - * _instance_ - * [.created()](#IotaDocumentMetadata+created) ⇒ [Timestamp](#Timestamp) \| undefined - * [.updated()](#IotaDocumentMetadata+updated) ⇒ [Timestamp](#Timestamp) \| undefined - * [.deactivated()](#IotaDocumentMetadata+deactivated) ⇒ boolean \| undefined - * [.stateControllerAddress()](#IotaDocumentMetadata+stateControllerAddress) ⇒ string \| undefined - * [.governorAddress()](#IotaDocumentMetadata+governorAddress) ⇒ string \| undefined - * [.properties()](#IotaDocumentMetadata+properties) ⇒ Map.<string, any> - * [.toJSON()](#IotaDocumentMetadata+toJSON) ⇒ any - * [.clone()](#IotaDocumentMetadata+clone) ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) - * _static_ - * [.fromJSON(json)](#IotaDocumentMetadata.fromJSON) ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) - - - -### iotaDocumentMetadata.created() ⇒ [Timestamp](#Timestamp) \| undefined -Returns a copy of the timestamp of when the DID document was created. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.updated() ⇒ [Timestamp](#Timestamp) \| undefined -Returns a copy of the timestamp of the last DID document update. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.deactivated() ⇒ boolean \| undefined -Returns a copy of the deactivated status of the DID document. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.stateControllerAddress() ⇒ string \| undefined -Returns a copy of the Bech32-encoded state controller address, if present. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.governorAddress() ⇒ string \| undefined -Returns a copy of the Bech32-encoded governor address, if present. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.properties() ⇒ Map.<string, any> -Returns a copy of the custom metadata properties. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### iotaDocumentMetadata.clone() ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) -Deep clones the object. - -**Kind**: instance method of [IotaDocumentMetadata](#IotaDocumentMetadata) - - -### IotaDocumentMetadata.fromJSON(json) ⇒ [IotaDocumentMetadata](#IotaDocumentMetadata) -Deserializes an instance from a JSON object. - -**Kind**: static method of [IotaDocumentMetadata](#IotaDocumentMetadata) - -| Param | Type | -| --- | --- | -| json | any | - - - -## IotaIdentityClientExt -An extension interface that provides helper functions for publication -and resolution of DID documents in Alias Outputs. - -**Kind**: global class - -* [IotaIdentityClientExt](#IotaIdentityClientExt) - * [.newDidOutput(client, address, document, [rentStructure])](#IotaIdentityClientExt.newDidOutput) ⇒ Promise.<AliasOutputBuilderParams> - * [.updateDidOutput(client, document)](#IotaIdentityClientExt.updateDidOutput) ⇒ Promise.<AliasOutputBuilderParams> - * [.deactivateDidOutput(client, did)](#IotaIdentityClientExt.deactivateDidOutput) ⇒ Promise.<AliasOutputBuilderParams> - * [.resolveDid(client, did)](#IotaIdentityClientExt.resolveDid) ⇒ [Promise.<IotaDocument>](#IotaDocument) - * [.resolveDidOutput(client, did)](#IotaIdentityClientExt.resolveDidOutput) ⇒ Promise.<AliasOutputBuilderParams> - - - -### IotaIdentityClientExt.newDidOutput(client, address, document, [rentStructure]) ⇒ Promise.<AliasOutputBuilderParams> -Create a DID with a new Alias Output containing the given `document`. - -The `address` will be set as the state controller and governor unlock conditions. -The minimum required token deposit amount will be set according to the given -`rent_structure`, which will be fetched from the node if not provided. -The returned Alias Output can be further customised before publication, if desired. - -NOTE: this does *not* publish the Alias Output. - -**Kind**: static method of [IotaIdentityClientExt](#IotaIdentityClientExt) - -| Param | Type | -| --- | --- | -| client | IIotaIdentityClient | -| address | Address | -| document | [IotaDocument](#IotaDocument) | -| [rentStructure] | IRent \| undefined | - - - -### IotaIdentityClientExt.updateDidOutput(client, document) ⇒ Promise.<AliasOutputBuilderParams> -Fetches the associated Alias Output and updates it with `document` in its state metadata. -The storage deposit on the output is left unchanged. If the size of the document increased, -the amount should be increased manually. - -NOTE: this does *not* publish the updated Alias Output. - -**Kind**: static method of [IotaIdentityClientExt](#IotaIdentityClientExt) - -| Param | Type | -| --- | --- | -| client | IIotaIdentityClient | -| document | [IotaDocument](#IotaDocument) | - - - -### IotaIdentityClientExt.deactivateDidOutput(client, did) ⇒ Promise.<AliasOutputBuilderParams> -Removes the DID document from the state metadata of its Alias Output, -effectively deactivating it. The storage deposit on the output is left unchanged, -and should be reallocated manually. - -Deactivating does not destroy the output. Hence, it can be re-activated by publishing -an update containing a DID document. - -NOTE: this does *not* publish the updated Alias Output. - -**Kind**: static method of [IotaIdentityClientExt](#IotaIdentityClientExt) - -| Param | Type | -| --- | --- | -| client | IIotaIdentityClient | -| did | [IotaDID](#IotaDID) | - - - -### IotaIdentityClientExt.resolveDid(client, did) ⇒ [Promise.<IotaDocument>](#IotaDocument) -Resolve a [IotaDocument](#IotaDocument). Returns an empty, deactivated document if the state metadata -of the Alias Output is empty. - -**Kind**: static method of [IotaIdentityClientExt](#IotaIdentityClientExt) - -| Param | Type | -| --- | --- | -| client | IIotaIdentityClient | -| did | [IotaDID](#IotaDID) | - - - -### IotaIdentityClientExt.resolveDidOutput(client, did) ⇒ Promise.<AliasOutputBuilderParams> -Fetches the `IAliasOutput` associated with the given DID. - -**Kind**: static method of [IotaIdentityClientExt](#IotaIdentityClientExt) - -| Param | Type | -| --- | --- | -| client | IIotaIdentityClient | -| did | [IotaDID](#IotaDID) | - - - -## IssuerProtectedHeader -**Kind**: global class - -* [IssuerProtectedHeader](#IssuerProtectedHeader) - * [.typ](#IssuerProtectedHeader+typ) ⇒ string \| undefined - * [.typ](#IssuerProtectedHeader+typ) - * [.alg](#IssuerProtectedHeader+alg) ⇒ [ProofAlgorithm](#ProofAlgorithm) - * [.alg](#IssuerProtectedHeader+alg) - * [.kid](#IssuerProtectedHeader+kid) ⇒ string \| undefined - * [.kid](#IssuerProtectedHeader+kid) - * [.cid](#IssuerProtectedHeader+cid) ⇒ string \| undefined - * [.cid](#IssuerProtectedHeader+cid) - * [.claims()](#IssuerProtectedHeader+claims) ⇒ Array.<string> - - - -### issuerProtectedHeader.typ ⇒ string \| undefined -JWP type (JPT). - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - - -### issuerProtectedHeader.typ -JWP type (JPT). - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### issuerProtectedHeader.alg ⇒ [ProofAlgorithm](#ProofAlgorithm) -Algorithm used for the JWP. - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - - -### issuerProtectedHeader.alg -Algorithm used for the JWP. - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - -| Param | Type | -| --- | --- | -| arg0 | [ProofAlgorithm](#ProofAlgorithm) | - - - -### issuerProtectedHeader.kid ⇒ string \| undefined -ID for the key used for the JWP. - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - - -### issuerProtectedHeader.kid -ID for the key used for the JWP. - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### issuerProtectedHeader.cid ⇒ string \| undefined -Not handled for now. Will be used in the future to resolve external claims - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - - -### issuerProtectedHeader.cid -Not handled for now. Will be used in the future to resolve external claims - -**Kind**: instance property of [IssuerProtectedHeader](#IssuerProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### issuerProtectedHeader.claims() ⇒ Array.<string> -**Kind**: instance method of [IssuerProtectedHeader](#IssuerProtectedHeader) - - -## Jpt -A JSON Proof Token (JPT). - -**Kind**: global class - -* [Jpt](#Jpt) - * [new Jpt(jpt_string)](#new_Jpt_new) - * [.toString()](#Jpt+toString) ⇒ string - * [.clone()](#Jpt+clone) ⇒ [Jpt](#Jpt) - - - -### new Jpt(jpt_string) -Creates a new [Jpt](#Jpt). - - -| Param | Type | -| --- | --- | -| jpt_string | string | - - - -### jpt.toString() ⇒ string -**Kind**: instance method of [Jpt](#Jpt) - - -### jpt.clone() ⇒ [Jpt](#Jpt) -Deep clones the object. - -**Kind**: instance method of [Jpt](#Jpt) - - -## JptCredentialValidationOptions -Options to declare validation criteria for [Jpt](#Jpt). - -**Kind**: global class - -* [JptCredentialValidationOptions](#JptCredentialValidationOptions) - * [new JptCredentialValidationOptions([opts])](#new_JptCredentialValidationOptions_new) - * _instance_ - * [.clone()](#JptCredentialValidationOptions+clone) ⇒ [JptCredentialValidationOptions](#JptCredentialValidationOptions) - * [.toJSON()](#JptCredentialValidationOptions+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#JptCredentialValidationOptions.fromJSON) ⇒ [JptCredentialValidationOptions](#JptCredentialValidationOptions) - - - -### new JptCredentialValidationOptions([opts]) -Creates a new default istance. - - -| Param | Type | -| --- | --- | -| [opts] | IJptCredentialValidationOptions \| undefined | - - - -### jptCredentialValidationOptions.clone() ⇒ [JptCredentialValidationOptions](#JptCredentialValidationOptions) -Deep clones the object. - -**Kind**: instance method of [JptCredentialValidationOptions](#JptCredentialValidationOptions) - - -### jptCredentialValidationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JptCredentialValidationOptions](#JptCredentialValidationOptions) - - -### JptCredentialValidationOptions.fromJSON(json) ⇒ [JptCredentialValidationOptions](#JptCredentialValidationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JptCredentialValidationOptions](#JptCredentialValidationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JptCredentialValidator -**Kind**: global class - - -### JptCredentialValidator.validate(credential_jpt, issuer, options, fail_fast) ⇒ [DecodedJptCredential](#DecodedJptCredential) -**Kind**: static method of [JptCredentialValidator](#JptCredentialValidator) - -| Param | Type | -| --- | --- | -| credential_jpt | [Jpt](#Jpt) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| options | [JptCredentialValidationOptions](#JptCredentialValidationOptions) | -| fail_fast | [FailFast](#FailFast) | - - - -## JptCredentialValidatorUtils -Utility functions for validating JPT credentials. - -**Kind**: global class - -* [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - * [.extractIssuer(credential)](#JptCredentialValidatorUtils.extractIssuer) ⇒ [CoreDID](#CoreDID) - * [.extractIssuerFromIssuedJpt(credential)](#JptCredentialValidatorUtils.extractIssuerFromIssuedJpt) ⇒ [CoreDID](#CoreDID) - * [.checkTimeframesWithValidityTimeframe2024(credential, validity_timeframe, status_check)](#JptCredentialValidatorUtils.checkTimeframesWithValidityTimeframe2024) - * [.checkRevocationWithValidityTimeframe2024(credential, issuer, status_check)](#JptCredentialValidatorUtils.checkRevocationWithValidityTimeframe2024) - * [.checkTimeframesAndRevocationWithValidityTimeframe2024(credential, issuer, validity_timeframe, status_check)](#JptCredentialValidatorUtils.checkTimeframesAndRevocationWithValidityTimeframe2024) - - - -### JptCredentialValidatorUtils.extractIssuer(credential) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a [Credential](#Credential) as a DID. -# Errors -Fails if the issuer field is not a valid DID. - -**Kind**: static method of [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | - - - -### JptCredentialValidatorUtils.extractIssuerFromIssuedJpt(credential) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a credential in JPT representation as DID. -# Errors -If the JPT decoding fails or the issuer field is not a valid DID. - -**Kind**: static method of [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Jpt](#Jpt) | - - - -### JptCredentialValidatorUtils.checkTimeframesWithValidityTimeframe2024(credential, validity_timeframe, status_check) -**Kind**: static method of [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| validity_timeframe | [Timestamp](#Timestamp) \| undefined | -| status_check | [StatusCheck](#StatusCheck) | - - - -### JptCredentialValidatorUtils.checkRevocationWithValidityTimeframe2024(credential, issuer, status_check) -Checks whether the credential status has been revoked. - -Only supports `RevocationTimeframe2024`. - -**Kind**: static method of [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| status_check | [StatusCheck](#StatusCheck) | - - - -### JptCredentialValidatorUtils.checkTimeframesAndRevocationWithValidityTimeframe2024(credential, issuer, validity_timeframe, status_check) -Checks whether the credential status has been revoked or the timeframe interval is INVALID - -Only supports `RevocationTimeframe2024`. - -**Kind**: static method of [JptCredentialValidatorUtils](#JptCredentialValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| validity_timeframe | [Timestamp](#Timestamp) \| undefined | -| status_check | [StatusCheck](#StatusCheck) | - - - -## JptPresentationValidationOptions -Options to declare validation criteria for a [Jpt](#Jpt) presentation. - -**Kind**: global class - -* [JptPresentationValidationOptions](#JptPresentationValidationOptions) - * [new JptPresentationValidationOptions([opts])](#new_JptPresentationValidationOptions_new) - * _instance_ - * [.clone()](#JptPresentationValidationOptions+clone) ⇒ [JptPresentationValidationOptions](#JptPresentationValidationOptions) - * [.toJSON()](#JptPresentationValidationOptions+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#JptPresentationValidationOptions.fromJSON) ⇒ [JptPresentationValidationOptions](#JptPresentationValidationOptions) - - - -### new JptPresentationValidationOptions([opts]) - -| Param | Type | -| --- | --- | -| [opts] | IJptPresentationValidationOptions \| undefined | - - - -### jptPresentationValidationOptions.clone() ⇒ [JptPresentationValidationOptions](#JptPresentationValidationOptions) -Deep clones the object. - -**Kind**: instance method of [JptPresentationValidationOptions](#JptPresentationValidationOptions) - - -### jptPresentationValidationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JptPresentationValidationOptions](#JptPresentationValidationOptions) - - -### JptPresentationValidationOptions.fromJSON(json) ⇒ [JptPresentationValidationOptions](#JptPresentationValidationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JptPresentationValidationOptions](#JptPresentationValidationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JptPresentationValidator -**Kind**: global class - - -### JptPresentationValidator.validate(presentation_jpt, issuer, options, fail_fast) ⇒ [DecodedJptPresentation](#DecodedJptPresentation) -Decodes and validates a Presented [Credential](#Credential) issued as a JPT (JWP Presented Form). A -[DecodedJptPresentation](#DecodedJptPresentation) is returned upon success. - -The following properties are validated according to `options`: -- the holder's proof on the JWP, -- the expiration date, -- the issuance date, -- the semantic structure. - -**Kind**: static method of [JptPresentationValidator](#JptPresentationValidator) - -| Param | Type | -| --- | --- | -| presentation_jpt | [Jpt](#Jpt) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| options | [JptPresentationValidationOptions](#JptPresentationValidationOptions) | -| fail_fast | [FailFast](#FailFast) | - - - -## JptPresentationValidatorUtils -Utility functions for verifying JPT presentations. - -**Kind**: global class - -* [JptPresentationValidatorUtils](#JptPresentationValidatorUtils) - * [.extractIssuerFromPresentedJpt(presentation)](#JptPresentationValidatorUtils.extractIssuerFromPresentedJpt) ⇒ [CoreDID](#CoreDID) - * [.checkTimeframesWithValidityTimeframe2024(credential, validity_timeframe, status_check)](#JptPresentationValidatorUtils.checkTimeframesWithValidityTimeframe2024) - - - -### JptPresentationValidatorUtils.extractIssuerFromPresentedJpt(presentation) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a credential in JPT representation as DID. -# Errors -If the JPT decoding fails or the issuer field is not a valid DID. - -**Kind**: static method of [JptPresentationValidatorUtils](#JptPresentationValidatorUtils) - -| Param | Type | -| --- | --- | -| presentation | [Jpt](#Jpt) | - - - -### JptPresentationValidatorUtils.checkTimeframesWithValidityTimeframe2024(credential, validity_timeframe, status_check) -Check timeframe interval in credentialStatus with `RevocationTimeframeStatus`. - -**Kind**: static method of [JptPresentationValidatorUtils](#JptPresentationValidatorUtils) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| validity_timeframe | [Timestamp](#Timestamp) \| undefined | -| status_check | [StatusCheck](#StatusCheck) | - - - -## Jwk -**Kind**: global class - -* [Jwk](#Jwk) - * [new Jwk(jwk)](#new_Jwk_new) - * _instance_ - * [.kty()](#Jwk+kty) ⇒ JwkType - * [.use()](#Jwk+use) ⇒ JwkUse \| undefined - * [.keyOps()](#Jwk+keyOps) ⇒ Array.<JwkOperation> - * [.alg()](#Jwk+alg) ⇒ JwsAlgorithm \| undefined - * [.kid()](#Jwk+kid) ⇒ string \| undefined - * [.x5u()](#Jwk+x5u) ⇒ string \| undefined - * [.x5c()](#Jwk+x5c) ⇒ Array.<string> - * [.x5t()](#Jwk+x5t) ⇒ string \| undefined - * [.x5t256()](#Jwk+x5t256) ⇒ string \| undefined - * [.paramsEc()](#Jwk+paramsEc) ⇒ JwkParamsEc \| undefined - * [.paramsOkp()](#Jwk+paramsOkp) ⇒ JwkParamsOkp \| undefined - * [.paramsOct()](#Jwk+paramsOct) ⇒ JwkParamsOct \| undefined - * [.paramsRsa()](#Jwk+paramsRsa) ⇒ JwkParamsRsa \| undefined - * [.toPublic()](#Jwk+toPublic) ⇒ [Jwk](#Jwk) \| undefined - * [.isPublic()](#Jwk+isPublic) ⇒ boolean - * [.isPrivate()](#Jwk+isPrivate) ⇒ boolean - * [.toJSON()](#Jwk+toJSON) ⇒ any - * [.clone()](#Jwk+clone) ⇒ [Jwk](#Jwk) - * _static_ - * [.fromJSON(json)](#Jwk.fromJSON) ⇒ [Jwk](#Jwk) - - - -### new Jwk(jwk) - -| Param | Type | -| --- | --- | -| jwk | IJwkParams | - - - -### jwk.kty() ⇒ JwkType -Returns the value for the key type parameter (kty). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.use() ⇒ JwkUse \| undefined -Returns the value for the use property (use). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.keyOps() ⇒ Array.<JwkOperation> -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.alg() ⇒ JwsAlgorithm \| undefined -Returns the value for the algorithm property (alg). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.kid() ⇒ string \| undefined -Returns the value of the key ID property (kid). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.x5u() ⇒ string \| undefined -Returns the value of the X.509 URL property (x5u). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.x5c() ⇒ Array.<string> -Returns the value of the X.509 certificate chain property (x5c). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.x5t() ⇒ string \| undefined -Returns the value of the X.509 certificate SHA-1 thumbprint property (x5t). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.x5t256() ⇒ string \| undefined -Returns the value of the X.509 certificate SHA-256 thumbprint property (x5t#S256). - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.paramsEc() ⇒ JwkParamsEc \| undefined -If this JWK is of kty EC, returns those parameters. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.paramsOkp() ⇒ JwkParamsOkp \| undefined -If this JWK is of kty OKP, returns those parameters. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.paramsOct() ⇒ JwkParamsOct \| undefined -If this JWK is of kty OCT, returns those parameters. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.paramsRsa() ⇒ JwkParamsRsa \| undefined -If this JWK is of kty RSA, returns those parameters. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.toPublic() ⇒ [Jwk](#Jwk) \| undefined -Returns a clone of the [Jwk](#Jwk) with _all_ private key components unset. -Nothing is returned when `kty = oct` as this key type is not considered public by this library. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.isPublic() ⇒ boolean -Returns `true` if _all_ private key components of the key are unset, `false` otherwise. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.isPrivate() ⇒ boolean -Returns `true` if _all_ private key components of the key are set, `false` otherwise. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Jwk](#Jwk) - - -### jwk.clone() ⇒ [Jwk](#Jwk) -Deep clones the object. - -**Kind**: instance method of [Jwk](#Jwk) - - -### Jwk.fromJSON(json) ⇒ [Jwk](#Jwk) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Jwk](#Jwk) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwkGenOutput -The result of a key generation in `JwkStorage`. - -**Kind**: global class - -* [JwkGenOutput](#JwkGenOutput) - * [new JwkGenOutput(key_id, jwk)](#new_JwkGenOutput_new) - * _instance_ - * [.jwk()](#JwkGenOutput+jwk) ⇒ [Jwk](#Jwk) - * [.keyId()](#JwkGenOutput+keyId) ⇒ string - * [.toJSON()](#JwkGenOutput+toJSON) ⇒ any - * [.clone()](#JwkGenOutput+clone) ⇒ [JwkGenOutput](#JwkGenOutput) - * _static_ - * [.fromJSON(json)](#JwkGenOutput.fromJSON) ⇒ [JwkGenOutput](#JwkGenOutput) - - - -### new JwkGenOutput(key_id, jwk) - -| Param | Type | -| --- | --- | -| key_id | string | -| jwk | [Jwk](#Jwk) | - - - -### jwkGenOutput.jwk() ⇒ [Jwk](#Jwk) -Returns the generated public [Jwk](#Jwk). - -**Kind**: instance method of [JwkGenOutput](#JwkGenOutput) - - -### jwkGenOutput.keyId() ⇒ string -Returns the key id of the generated [Jwk](#Jwk). - -**Kind**: instance method of [JwkGenOutput](#JwkGenOutput) - - -### jwkGenOutput.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwkGenOutput](#JwkGenOutput) - - -### jwkGenOutput.clone() ⇒ [JwkGenOutput](#JwkGenOutput) -Deep clones the object. - -**Kind**: instance method of [JwkGenOutput](#JwkGenOutput) - - -### JwkGenOutput.fromJSON(json) ⇒ [JwkGenOutput](#JwkGenOutput) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwkGenOutput](#JwkGenOutput) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwpCredentialOptions -**Kind**: global class - -* [JwpCredentialOptions](#JwpCredentialOptions) - * _instance_ - * [.kid](#JwpCredentialOptions+kid) ⇒ string \| undefined - * [.kid](#JwpCredentialOptions+kid) - * [.toJSON()](#JwpCredentialOptions+toJSON) ⇒ any - * _static_ - * [.fromJSON(value)](#JwpCredentialOptions.fromJSON) ⇒ [JwpCredentialOptions](#JwpCredentialOptions) - - - -### jwpCredentialOptions.kid ⇒ string \| undefined -**Kind**: instance property of [JwpCredentialOptions](#JwpCredentialOptions) - - -### jwpCredentialOptions.kid -**Kind**: instance property of [JwpCredentialOptions](#JwpCredentialOptions) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### jwpCredentialOptions.toJSON() ⇒ any -**Kind**: instance method of [JwpCredentialOptions](#JwpCredentialOptions) - - -### JwpCredentialOptions.fromJSON(value) ⇒ [JwpCredentialOptions](#JwpCredentialOptions) -**Kind**: static method of [JwpCredentialOptions](#JwpCredentialOptions) - -| Param | Type | -| --- | --- | -| value | any | - - - -## JwpIssued -**Kind**: global class - -* [JwpIssued](#JwpIssued) - * _instance_ - * [.toJSON()](#JwpIssued+toJSON) ⇒ any - * [.clone()](#JwpIssued+clone) ⇒ [JwpIssued](#JwpIssued) - * [.encode(serialization)](#JwpIssued+encode) ⇒ string - * [.setProof(proof)](#JwpIssued+setProof) - * [.getProof()](#JwpIssued+getProof) ⇒ Uint8Array - * [.getPayloads()](#JwpIssued+getPayloads) ⇒ [Payloads](#Payloads) - * [.setPayloads(payloads)](#JwpIssued+setPayloads) - * [.getIssuerProtectedHeader()](#JwpIssued+getIssuerProtectedHeader) ⇒ [IssuerProtectedHeader](#IssuerProtectedHeader) - * _static_ - * [.fromJSON(json)](#JwpIssued.fromJSON) ⇒ [JwpIssued](#JwpIssued) - - - -### jwpIssued.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwpIssued](#JwpIssued) - - -### jwpIssued.clone() ⇒ [JwpIssued](#JwpIssued) -Deep clones the object. - -**Kind**: instance method of [JwpIssued](#JwpIssued) - - -### jwpIssued.encode(serialization) ⇒ string -**Kind**: instance method of [JwpIssued](#JwpIssued) - -| Param | Type | -| --- | --- | -| serialization | [SerializationType](#SerializationType) | - - - -### jwpIssued.setProof(proof) -**Kind**: instance method of [JwpIssued](#JwpIssued) - -| Param | Type | -| --- | --- | -| proof | Uint8Array | - - - -### jwpIssued.getProof() ⇒ Uint8Array -**Kind**: instance method of [JwpIssued](#JwpIssued) - - -### jwpIssued.getPayloads() ⇒ [Payloads](#Payloads) -**Kind**: instance method of [JwpIssued](#JwpIssued) - - -### jwpIssued.setPayloads(payloads) -**Kind**: instance method of [JwpIssued](#JwpIssued) - -| Param | Type | -| --- | --- | -| payloads | [Payloads](#Payloads) | - - - -### jwpIssued.getIssuerProtectedHeader() ⇒ [IssuerProtectedHeader](#IssuerProtectedHeader) -**Kind**: instance method of [JwpIssued](#JwpIssued) - - -### JwpIssued.fromJSON(json) ⇒ [JwpIssued](#JwpIssued) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwpIssued](#JwpIssued) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwpPresentationOptions -Options to be set in the JWT claims of a verifiable presentation. - -**Kind**: global class - -* [JwpPresentationOptions](#JwpPresentationOptions) - * [.audience](#JwpPresentationOptions+audience) ⇒ string \| undefined - * [.audience](#JwpPresentationOptions+audience) - * [.nonce](#JwpPresentationOptions+nonce) ⇒ string \| undefined - * [.nonce](#JwpPresentationOptions+nonce) - - - -### jwpPresentationOptions.audience ⇒ string \| undefined -Sets the audience for presentation (`aud` property in JWP Presentation Header). - -**Kind**: instance property of [JwpPresentationOptions](#JwpPresentationOptions) - - -### jwpPresentationOptions.audience -Sets the audience for presentation (`aud` property in JWP Presentation Header). - -**Kind**: instance property of [JwpPresentationOptions](#JwpPresentationOptions) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### jwpPresentationOptions.nonce ⇒ string \| undefined -The nonce to be placed in the Presentation Protected Header. - -**Kind**: instance property of [JwpPresentationOptions](#JwpPresentationOptions) - - -### jwpPresentationOptions.nonce -The nonce to be placed in the Presentation Protected Header. - -**Kind**: instance property of [JwpPresentationOptions](#JwpPresentationOptions) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -## JwpVerificationOptions -**Kind**: global class - -* [JwpVerificationOptions](#JwpVerificationOptions) - * _instance_ - * [.clone()](#JwpVerificationOptions+clone) ⇒ [JwpVerificationOptions](#JwpVerificationOptions) - * [.toJSON()](#JwpVerificationOptions+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#JwpVerificationOptions.fromJSON) ⇒ [JwpVerificationOptions](#JwpVerificationOptions) - * [.new([opts])](#JwpVerificationOptions.new) ⇒ [JwpVerificationOptions](#JwpVerificationOptions) - - - -### jwpVerificationOptions.clone() ⇒ [JwpVerificationOptions](#JwpVerificationOptions) -Deep clones the object. - -**Kind**: instance method of [JwpVerificationOptions](#JwpVerificationOptions) - - -### jwpVerificationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwpVerificationOptions](#JwpVerificationOptions) - - -### JwpVerificationOptions.fromJSON(json) ⇒ [JwpVerificationOptions](#JwpVerificationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwpVerificationOptions](#JwpVerificationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -### JwpVerificationOptions.new([opts]) ⇒ [JwpVerificationOptions](#JwpVerificationOptions) -**Kind**: static method of [JwpVerificationOptions](#JwpVerificationOptions) - -| Param | Type | -| --- | --- | -| [opts] | IJwpVerificationOptions \| undefined | - - - -## Jws -A wrapper around a JSON Web Signature (JWS). - -**Kind**: global class - -* [Jws](#Jws) - * [new Jws(jws_string)](#new_Jws_new) - * [.toString()](#Jws+toString) ⇒ string - - - -### new Jws(jws_string) -Creates a new [Jws](#Jws) from the given string. - - -| Param | Type | -| --- | --- | -| jws_string | string | - - - -### jws.toString() ⇒ string -Returns a clone of the JWS string. - -**Kind**: instance method of [Jws](#Jws) - - -## JwsHeader -**Kind**: global class - -* [JwsHeader](#JwsHeader) - * [new JwsHeader()](#new_JwsHeader_new) - * _instance_ - * [.alg()](#JwsHeader+alg) ⇒ JwsAlgorithm \| undefined - * [.setAlg(value)](#JwsHeader+setAlg) - * [.b64()](#JwsHeader+b64) ⇒ boolean \| undefined - * [.setB64(value)](#JwsHeader+setB64) - * [.custom()](#JwsHeader+custom) ⇒ Record.<string, any> \| undefined - * [.has(claim)](#JwsHeader+has) ⇒ boolean - * [.isDisjoint(other)](#JwsHeader+isDisjoint) ⇒ boolean - * [.jku()](#JwsHeader+jku) ⇒ string \| undefined - * [.setJku(value)](#JwsHeader+setJku) - * [.jwk()](#JwsHeader+jwk) ⇒ [Jwk](#Jwk) \| undefined - * [.setJwk(value)](#JwsHeader+setJwk) - * [.kid()](#JwsHeader+kid) ⇒ string \| undefined - * [.setKid(value)](#JwsHeader+setKid) - * [.x5u()](#JwsHeader+x5u) ⇒ string \| undefined - * [.setX5u(value)](#JwsHeader+setX5u) - * [.x5c()](#JwsHeader+x5c) ⇒ Array.<string> - * [.setX5c(value)](#JwsHeader+setX5c) - * [.x5t()](#JwsHeader+x5t) ⇒ string \| undefined - * [.setX5t(value)](#JwsHeader+setX5t) - * [.x5tS256()](#JwsHeader+x5tS256) ⇒ string \| undefined - * [.setX5tS256(value)](#JwsHeader+setX5tS256) - * [.typ()](#JwsHeader+typ) ⇒ string \| undefined - * [.setTyp(value)](#JwsHeader+setTyp) - * [.cty()](#JwsHeader+cty) ⇒ string \| undefined - * [.setCty(value)](#JwsHeader+setCty) - * [.crit()](#JwsHeader+crit) ⇒ Array.<string> - * [.setCrit(value)](#JwsHeader+setCrit) - * [.url()](#JwsHeader+url) ⇒ string \| undefined - * [.setUrl(value)](#JwsHeader+setUrl) - * [.nonce()](#JwsHeader+nonce) ⇒ string \| undefined - * [.setNonce(value)](#JwsHeader+setNonce) - * [.toJSON()](#JwsHeader+toJSON) ⇒ any - * [.clone()](#JwsHeader+clone) ⇒ [JwsHeader](#JwsHeader) - * _static_ - * [.fromJSON(json)](#JwsHeader.fromJSON) ⇒ [JwsHeader](#JwsHeader) - - - -### new JwsHeader() -Create a new empty [JwsHeader](#JwsHeader). - - - -### jwsHeader.alg() ⇒ JwsAlgorithm \| undefined -Returns the value for the algorithm claim (alg). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setAlg(value) -Sets a value for the algorithm claim (alg). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | JwsAlgorithm | - - - -### jwsHeader.b64() ⇒ boolean \| undefined -Returns the value of the base64url-encode payload claim (b64). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setB64(value) -Sets a value for the base64url-encode payload claim (b64). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | boolean | - - - -### jwsHeader.custom() ⇒ Record.<string, any> \| undefined -Additional header parameters. - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.has(claim) ⇒ boolean -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| claim | string | - - - -### jwsHeader.isDisjoint(other) ⇒ boolean -Returns `true` if none of the fields are set in both `self` and `other`. - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| other | [JwsHeader](#JwsHeader) | - - - -### jwsHeader.jku() ⇒ string \| undefined -Returns the value of the JWK Set URL claim (jku). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setJku(value) -Sets a value for the JWK Set URL claim (jku). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.jwk() ⇒ [Jwk](#Jwk) \| undefined -Returns the value of the JWK claim (jwk). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setJwk(value) -Sets a value for the JWK claim (jwk). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | [Jwk](#Jwk) | - - - -### jwsHeader.kid() ⇒ string \| undefined -Returns the value of the key ID claim (kid). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setKid(value) -Sets a value for the key ID claim (kid). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.x5u() ⇒ string \| undefined -Returns the value of the X.509 URL claim (x5u). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setX5u(value) -Sets a value for the X.509 URL claim (x5u). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.x5c() ⇒ Array.<string> -Returns the value of the X.509 certificate chain claim (x5c). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setX5c(value) -Sets values for the X.509 certificate chain claim (x5c). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | Array.<string> | - - - -### jwsHeader.x5t() ⇒ string \| undefined -Returns the value of the X.509 certificate SHA-1 thumbprint claim (x5t). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setX5t(value) -Sets a value for the X.509 certificate SHA-1 thumbprint claim (x5t). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.x5tS256() ⇒ string \| undefined -Returns the value of the X.509 certificate SHA-256 thumbprint claim -(x5t#S256). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setX5tS256(value) -Sets a value for the X.509 certificate SHA-256 thumbprint claim -(x5t#S256). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.typ() ⇒ string \| undefined -Returns the value of the token type claim (typ). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setTyp(value) -Sets a value for the token type claim (typ). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.cty() ⇒ string \| undefined -Returns the value of the content type claim (cty). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setCty(value) -Sets a value for the content type claim (cty). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.crit() ⇒ Array.<string> -Returns the value of the critical claim (crit). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setCrit(value) -Sets values for the critical claim (crit). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | Array.<string> | - - - -### jwsHeader.url() ⇒ string \| undefined -Returns the value of the url claim (url). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setUrl(value) -Sets a value for the url claim (url). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.nonce() ⇒ string \| undefined -Returns the value of the nonce claim (nonce). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.setNonce(value) -Sets a value for the nonce claim (nonce). - -**Kind**: instance method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsHeader.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### jwsHeader.clone() ⇒ [JwsHeader](#JwsHeader) -Deep clones the object. - -**Kind**: instance method of [JwsHeader](#JwsHeader) - - -### JwsHeader.fromJSON(json) ⇒ [JwsHeader](#JwsHeader) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwsHeader](#JwsHeader) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwsSignatureOptions -**Kind**: global class - -* [JwsSignatureOptions](#JwsSignatureOptions) - * [new JwsSignatureOptions([options])](#new_JwsSignatureOptions_new) - * _instance_ - * [.setAttachJwk(value)](#JwsSignatureOptions+setAttachJwk) - * [.setB64(value)](#JwsSignatureOptions+setB64) - * [.setTyp(value)](#JwsSignatureOptions+setTyp) - * [.setCty(value)](#JwsSignatureOptions+setCty) - * [.serUrl(value)](#JwsSignatureOptions+serUrl) - * [.setNonce(value)](#JwsSignatureOptions+setNonce) - * [.setKid(value)](#JwsSignatureOptions+setKid) - * [.setDetachedPayload(value)](#JwsSignatureOptions+setDetachedPayload) - * [.setCustomHeaderParameters(value)](#JwsSignatureOptions+setCustomHeaderParameters) - * [.toJSON()](#JwsSignatureOptions+toJSON) ⇒ any - * [.clone()](#JwsSignatureOptions+clone) ⇒ [JwsSignatureOptions](#JwsSignatureOptions) - * _static_ - * [.fromJSON(json)](#JwsSignatureOptions.fromJSON) ⇒ [JwsSignatureOptions](#JwsSignatureOptions) - - - -### new JwsSignatureOptions([options]) - -| Param | Type | -| --- | --- | -| [options] | IJwsSignatureOptions \| undefined | - - - -### jwsSignatureOptions.setAttachJwk(value) -Replace the value of the `attachJwk` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | boolean | - - - -### jwsSignatureOptions.setB64(value) -Replace the value of the `b64` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | boolean | - - - -### jwsSignatureOptions.setTyp(value) -Replace the value of the `typ` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsSignatureOptions.setCty(value) -Replace the value of the `cty` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsSignatureOptions.serUrl(value) -Replace the value of the `url` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsSignatureOptions.setNonce(value) -Replace the value of the `nonce` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsSignatureOptions.setKid(value) -Replace the value of the `kid` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsSignatureOptions.setDetachedPayload(value) -Replace the value of the `detached_payload` field. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | boolean | - - - -### jwsSignatureOptions.setCustomHeaderParameters(value) -Add additional header parameters. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| value | Record.<string, any> | - - - -### jwsSignatureOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - - -### jwsSignatureOptions.clone() ⇒ [JwsSignatureOptions](#JwsSignatureOptions) -Deep clones the object. - -**Kind**: instance method of [JwsSignatureOptions](#JwsSignatureOptions) - - -### JwsSignatureOptions.fromJSON(json) ⇒ [JwsSignatureOptions](#JwsSignatureOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwsSignatureOptions](#JwsSignatureOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwsVerificationOptions -**Kind**: global class - -* [JwsVerificationOptions](#JwsVerificationOptions) - * [new JwsVerificationOptions([options])](#new_JwsVerificationOptions_new) - * _instance_ - * [.setNonce(value)](#JwsVerificationOptions+setNonce) - * [.setMethodScope(value)](#JwsVerificationOptions+setMethodScope) - * [.setMethodId(value)](#JwsVerificationOptions+setMethodId) - * [.toJSON()](#JwsVerificationOptions+toJSON) ⇒ any - * [.clone()](#JwsVerificationOptions+clone) ⇒ [JwsVerificationOptions](#JwsVerificationOptions) - * _static_ - * [.fromJSON(json)](#JwsVerificationOptions.fromJSON) ⇒ [JwsVerificationOptions](#JwsVerificationOptions) - - - -### new JwsVerificationOptions([options]) -Creates a new [JwsVerificationOptions](#JwsVerificationOptions) from the given fields. - - -| Param | Type | -| --- | --- | -| [options] | IJwsVerificationOptions \| undefined | - - - -### jwsVerificationOptions.setNonce(value) -Set the expected value for the `nonce` parameter of the protected header. - -**Kind**: instance method of [JwsVerificationOptions](#JwsVerificationOptions) - -| Param | Type | -| --- | --- | -| value | string | - - - -### jwsVerificationOptions.setMethodScope(value) -Set the scope of the verification methods that may be used to verify the given JWS. - -**Kind**: instance method of [JwsVerificationOptions](#JwsVerificationOptions) - -| Param | Type | -| --- | --- | -| value | [MethodScope](#MethodScope) | - - - -### jwsVerificationOptions.setMethodId(value) -Set the DID URl of the method, whose JWK should be used to verify the JWS. - -**Kind**: instance method of [JwsVerificationOptions](#JwsVerificationOptions) - -| Param | Type | -| --- | --- | -| value | [DIDUrl](#DIDUrl) | - - - -### jwsVerificationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwsVerificationOptions](#JwsVerificationOptions) - - -### jwsVerificationOptions.clone() ⇒ [JwsVerificationOptions](#JwsVerificationOptions) -Deep clones the object. - -**Kind**: instance method of [JwsVerificationOptions](#JwsVerificationOptions) - - -### JwsVerificationOptions.fromJSON(json) ⇒ [JwsVerificationOptions](#JwsVerificationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwsVerificationOptions](#JwsVerificationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## Jwt -A wrapper around a JSON Web Token (JWK). - -**Kind**: global class - -* [Jwt](#Jwt) - * [new Jwt(jwt_string)](#new_Jwt_new) - * _instance_ - * [.toString()](#Jwt+toString) ⇒ string - * [.toJSON()](#Jwt+toJSON) ⇒ any - * [.clone()](#Jwt+clone) ⇒ [Jwt](#Jwt) - * _static_ - * [.fromJSON(json)](#Jwt.fromJSON) ⇒ [Jwt](#Jwt) - - - -### new Jwt(jwt_string) -Creates a new [Jwt](#Jwt) from the given string. - - -| Param | Type | -| --- | --- | -| jwt_string | string | - - - -### jwt.toString() ⇒ string -Returns a clone of the JWT string. - -**Kind**: instance method of [Jwt](#Jwt) - - -### jwt.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Jwt](#Jwt) - - -### jwt.clone() ⇒ [Jwt](#Jwt) -Deep clones the object. - -**Kind**: instance method of [Jwt](#Jwt) - - -### Jwt.fromJSON(json) ⇒ [Jwt](#Jwt) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Jwt](#Jwt) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwtCredentialValidationOptions -Options to declare validation criteria when validating credentials. - -**Kind**: global class - -* [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - * [new JwtCredentialValidationOptions([options])](#new_JwtCredentialValidationOptions_new) - * _instance_ - * [.toJSON()](#JwtCredentialValidationOptions+toJSON) ⇒ any - * [.clone()](#JwtCredentialValidationOptions+clone) ⇒ [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - * _static_ - * [.fromJSON(json)](#JwtCredentialValidationOptions.fromJSON) ⇒ [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - - - -### new JwtCredentialValidationOptions([options]) - -| Param | Type | -| --- | --- | -| [options] | IJwtCredentialValidationOptions \| undefined | - - - -### jwtCredentialValidationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - - -### jwtCredentialValidationOptions.clone() ⇒ [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) -Deep clones the object. - -**Kind**: instance method of [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - - -### JwtCredentialValidationOptions.fromJSON(json) ⇒ [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwtCredentialValidator -A type for decoding and validating [Credential](#Credential). - -**Kind**: global class - -* [JwtCredentialValidator](#JwtCredentialValidator) - * [new JwtCredentialValidator([signatureVerifier])](#new_JwtCredentialValidator_new) - * _instance_ - * [.validate(credential_jwt, issuer, options, fail_fast)](#JwtCredentialValidator+validate) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) - * [.verifySignature(credential, trustedIssuers, options)](#JwtCredentialValidator+verifySignature) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) - * _static_ - * [.checkExpiresOnOrAfter(credential, timestamp)](#JwtCredentialValidator.checkExpiresOnOrAfter) - * [.checkIssuedOnOrBefore(credential, timestamp)](#JwtCredentialValidator.checkIssuedOnOrBefore) - * [.checkSubjectHolderRelationship(credential, holder, relationship)](#JwtCredentialValidator.checkSubjectHolderRelationship) - * [.checkStatus(credential, trustedIssuers, statusCheck)](#JwtCredentialValidator.checkStatus) - * [.checkStatusWithStatusList2021(credential, status_list, status_check)](#JwtCredentialValidator.checkStatusWithStatusList2021) - * [.extractIssuer(credential)](#JwtCredentialValidator.extractIssuer) ⇒ [CoreDID](#CoreDID) - * [.extractIssuerFromJwt(credential)](#JwtCredentialValidator.extractIssuerFromJwt) ⇒ [CoreDID](#CoreDID) - - - -### new JwtCredentialValidator([signatureVerifier]) -Creates a new [JwtCredentialValidator](#JwtCredentialValidator). If a `signatureVerifier` is provided it will be used when -verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` -algorithm will be used. - - -| Param | Type | -| --- | --- | -| [signatureVerifier] | IJwsVerifier \| undefined | - - - -### jwtCredentialValidator.validate(credential_jwt, issuer, options, fail_fast) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) -Decodes and validates a [Credential](#Credential) issued as a JWS. A [DecodedJwtCredential](#DecodedJwtCredential) is returned upon -success. - -The following properties are validated according to `options`: -- the issuer's signature on the JWS, -- the expiration date, -- the issuance date, -- the semantic structure. - -# Warning -The lack of an error returned from this method is in of itself not enough to conclude that the credential can be -trusted. This section contains more information on additional checks that should be carried out before and after -calling this method. - -## The state of the issuer's DID Document -The caller must ensure that `issuer` represents an up-to-date DID Document. - -## Properties that are not validated - There are many properties defined in [The Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) that are **not** validated, such as: -`proof`, `credentialStatus`, `type`, `credentialSchema`, `refreshService` **and more**. -These should be manually checked after validation, according to your requirements. - -# Errors -An error is returned whenever a validated condition is not satisfied. - -**Kind**: instance method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential_jwt | [Jwt](#Jwt) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| options | [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) | -| fail_fast | [FailFast](#FailFast) | - - - -### jwtCredentialValidator.verifySignature(credential, trustedIssuers, options) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) -Decode and verify the JWS signature of a [Credential](#Credential) issued as a JWT using the DID Document of a trusted -issuer. - -A [DecodedJwtCredential](#DecodedJwtCredential) is returned upon success. - -# Warning -The caller must ensure that the DID Documents of the trusted issuers are up-to-date. - -## Proofs - Only the JWS signature is verified. If the [Credential](#Credential) contains a `proof` property this will not be -verified by this method. - -# Errors -This method immediately returns an error if -the credential issuer' url cannot be parsed to a DID belonging to one of the trusted issuers. Otherwise an attempt -to verify the credential's signature will be made and an error is returned upon failure. - -**Kind**: instance method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Jwt](#Jwt) | -| trustedIssuers | Array.<(CoreDocument\|IToCoreDocument)> | -| options | [JwsVerificationOptions](#JwsVerificationOptions) | - - - -### JwtCredentialValidator.checkExpiresOnOrAfter(credential, timestamp) -Validate that the credential expires on or after the specified timestamp. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| timestamp | [Timestamp](#Timestamp) | - - - -### JwtCredentialValidator.checkIssuedOnOrBefore(credential, timestamp) -Validate that the credential is issued on or before the specified timestamp. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| timestamp | [Timestamp](#Timestamp) | - - - -### JwtCredentialValidator.checkSubjectHolderRelationship(credential, holder, relationship) -Validate that the relationship between the `holder` and the credential subjects is in accordance with -`relationship`. The `holder` parameter is expected to be the URL of the holder. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| holder | string | -| relationship | [SubjectHolderRelationship](#SubjectHolderRelationship) | - - - -### JwtCredentialValidator.checkStatus(credential, trustedIssuers, statusCheck) -Checks whether the credential status has been revoked. - -Only supports `RevocationBitmap2022`. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| trustedIssuers | Array.<(CoreDocument\|IToCoreDocument)> | -| statusCheck | [StatusCheck](#StatusCheck) | - - - -### JwtCredentialValidator.checkStatusWithStatusList2021(credential, status_list, status_check) -Checks wheter the credential status has been revoked using `StatusList2021`. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| status_list | [StatusList2021Credential](#StatusList2021Credential) | -| status_check | [StatusCheck](#StatusCheck) | - - - -### JwtCredentialValidator.extractIssuer(credential) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a [Credential](#Credential) as a DID. - -### Errors - -Fails if the issuer field is not a valid DID. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | - - - -### JwtCredentialValidator.extractIssuerFromJwt(credential) ⇒ [CoreDID](#CoreDID) -Utility for extracting the issuer field of a credential in JWT representation as DID. - -# Errors - -If the JWT decoding fails or the issuer field is not a valid DID. - -**Kind**: static method of [JwtCredentialValidator](#JwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [Jwt](#Jwt) | - - - -## JwtDomainLinkageValidator -A validator for a Domain Linkage Configuration and Credentials. - -**Kind**: global class - -* [JwtDomainLinkageValidator](#JwtDomainLinkageValidator) - * [new JwtDomainLinkageValidator([signatureVerifier])](#new_JwtDomainLinkageValidator_new) - * [.validateLinkage(issuer, configuration, domain, options)](#JwtDomainLinkageValidator+validateLinkage) - * [.validateCredential(issuer, credentialJwt, domain, options)](#JwtDomainLinkageValidator+validateCredential) - - - -### new JwtDomainLinkageValidator([signatureVerifier]) -Creates a new [JwtDomainLinkageValidator](#JwtDomainLinkageValidator). If a `signatureVerifier` is provided it will be used when -verifying decoded JWS signatures, otherwise the default which is capable of handling the `EdDSA`, `ES256`, `ES256K` -algorithms will be used. - - -| Param | Type | -| --- | --- | -| [signatureVerifier] | IJwsVerifier \| undefined | - - - -### jwtDomainLinkageValidator.validateLinkage(issuer, configuration, domain, options) -Validates the linkage between a domain and a DID. -[DomainLinkageConfiguration](#DomainLinkageConfiguration) is validated according to [DID Configuration Resource Verification](https://identity.foundation/.well-known/resources/did-configuration/#did-configuration-resource-verification). - -Linkage is valid if no error is thrown. - -# Note: -- Only the [JSON Web Token Proof Format](https://identity.foundation/.well-known/resources/did-configuration/#json-web-token-proof-format) - is supported. -- Only the Credential issued by `issuer` is verified. - -# Errors - - - Semantic structure of `configuration` is invalid. - - `configuration` includes multiple credentials issued by `issuer`. - - Validation of the matched Domain Linkage Credential fails. - -**Kind**: instance method of [JwtDomainLinkageValidator](#JwtDomainLinkageValidator) - -| Param | Type | -| --- | --- | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| configuration | [DomainLinkageConfiguration](#DomainLinkageConfiguration) | -| domain | string | -| options | [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) | - - - -### jwtDomainLinkageValidator.validateCredential(issuer, credentialJwt, domain, options) -Validates a [Domain Linkage Credential](https://identity.foundation/.well-known/resources/did-configuration/#domain-linkage-credential). - -Error will be thrown in case the validation fails. - -**Kind**: instance method of [JwtDomainLinkageValidator](#JwtDomainLinkageValidator) - -| Param | Type | -| --- | --- | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| credentialJwt | [Jwt](#Jwt) | -| domain | string | -| options | [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) | - - - -## JwtPresentationOptions -**Kind**: global class - -* [JwtPresentationOptions](#JwtPresentationOptions) - * [new JwtPresentationOptions([options])](#new_JwtPresentationOptions_new) - * _instance_ - * [.toJSON()](#JwtPresentationOptions+toJSON) ⇒ any - * [.clone()](#JwtPresentationOptions+clone) ⇒ [JwtPresentationOptions](#JwtPresentationOptions) - * _static_ - * [.fromJSON(json)](#JwtPresentationOptions.fromJSON) ⇒ [JwtPresentationOptions](#JwtPresentationOptions) - - - -### new JwtPresentationOptions([options]) -Creates a new [JwtPresentationOptions](#JwtPresentationOptions) from the given fields. - -Throws an error if any of the options are invalid. - - -| Param | Type | -| --- | --- | -| [options] | IJwtPresentationOptions \| undefined | - - - -### jwtPresentationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwtPresentationOptions](#JwtPresentationOptions) - - -### jwtPresentationOptions.clone() ⇒ [JwtPresentationOptions](#JwtPresentationOptions) -Deep clones the object. - -**Kind**: instance method of [JwtPresentationOptions](#JwtPresentationOptions) - - -### JwtPresentationOptions.fromJSON(json) ⇒ [JwtPresentationOptions](#JwtPresentationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwtPresentationOptions](#JwtPresentationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwtPresentationValidationOptions -Options to declare validation criteria when validating presentation. - -**Kind**: global class - -* [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - * [new JwtPresentationValidationOptions([options])](#new_JwtPresentationValidationOptions_new) - * _instance_ - * [.toJSON()](#JwtPresentationValidationOptions+toJSON) ⇒ any - * [.clone()](#JwtPresentationValidationOptions+clone) ⇒ [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - * _static_ - * [.fromJSON(json)](#JwtPresentationValidationOptions.fromJSON) ⇒ [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - - - -### new JwtPresentationValidationOptions([options]) -Creates a new [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) from the given fields. - -Throws an error if any of the options are invalid. - - -| Param | Type | -| --- | --- | -| [options] | IJwtPresentationValidationOptions \| undefined | - - - -### jwtPresentationValidationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - - -### jwtPresentationValidationOptions.clone() ⇒ [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) -Deep clones the object. - -**Kind**: instance method of [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - - -### JwtPresentationValidationOptions.fromJSON(json) ⇒ [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## JwtPresentationValidator -**Kind**: global class - -* [JwtPresentationValidator](#JwtPresentationValidator) - * [new JwtPresentationValidator([signatureVerifier])](#new_JwtPresentationValidator_new) - * _instance_ - * [.validate(presentationJwt, holder, validation_options)](#JwtPresentationValidator+validate) ⇒ [DecodedJwtPresentation](#DecodedJwtPresentation) - * _static_ - * [.checkStructure(presentation)](#JwtPresentationValidator.checkStructure) - * [.extractHolder(presentation)](#JwtPresentationValidator.extractHolder) ⇒ [CoreDID](#CoreDID) - - - -### new JwtPresentationValidator([signatureVerifier]) -Creates a new [JwtPresentationValidator](#JwtPresentationValidator). If a `signatureVerifier` is provided it will be used when -verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` -algorithm will be used. - - -| Param | Type | -| --- | --- | -| [signatureVerifier] | IJwsVerifier \| undefined | - - - -### jwtPresentationValidator.validate(presentationJwt, holder, validation_options) ⇒ [DecodedJwtPresentation](#DecodedJwtPresentation) -Validates a [Presentation](#Presentation) encoded as a [Jwt](#Jwt). - -The following properties are validated according to `options`: -- the JWT can be decoded into a semantically valid presentation. -- the expiration and issuance date contained in the JWT claims. -- the holder's signature. - -Validation is done with respect to the properties set in `options`. - -# Warning - -* This method does NOT validate the constituent credentials and therefore also not the relationship between the -credentials' subjects and the presentation holder. This can be done with [JwtCredentialValidationOptions](#JwtCredentialValidationOptions). -* The lack of an error returned from this method is in of itself not enough to conclude that the presentation can -be trusted. This section contains more information on additional checks that should be carried out before and -after calling this method. - -## The state of the supplied DID Documents. - -The caller must ensure that the DID Documents in `holder` are up-to-date. - -# Errors - -An error is returned whenever a validated condition is not satisfied or when decoding fails. - -**Kind**: instance method of [JwtPresentationValidator](#JwtPresentationValidator) - -| Param | Type | -| --- | --- | -| presentationJwt | [Jwt](#Jwt) | -| holder | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| validation_options | [JwtPresentationValidationOptions](#JwtPresentationValidationOptions) | - - - -### JwtPresentationValidator.checkStructure(presentation) -Validates the semantic structure of the [Presentation](#Presentation). - -**Kind**: static method of [JwtPresentationValidator](#JwtPresentationValidator) - -| Param | Type | -| --- | --- | -| presentation | [Presentation](#Presentation) | - - - -### JwtPresentationValidator.extractHolder(presentation) ⇒ [CoreDID](#CoreDID) -Attempt to extract the holder of the presentation. - -# Errors: -* If deserialization/decoding of the presentation fails. -* If the holder can't be parsed as DIDs. - -**Kind**: static method of [JwtPresentationValidator](#JwtPresentationValidator) - -| Param | Type | -| --- | --- | -| presentation | [Jwt](#Jwt) | - - - -## KeyBindingJWTValidationOptions -Options to declare validation criteria when validating credentials. - -**Kind**: global class - -* [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - * [new KeyBindingJWTValidationOptions([options])](#new_KeyBindingJWTValidationOptions_new) - * _instance_ - * [.toJSON()](#KeyBindingJWTValidationOptions+toJSON) ⇒ any - * [.clone()](#KeyBindingJWTValidationOptions+clone) ⇒ [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - * _static_ - * [.fromJSON(json)](#KeyBindingJWTValidationOptions.fromJSON) ⇒ [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - - - -### new KeyBindingJWTValidationOptions([options]) - -| Param | Type | -| --- | --- | -| [options] | IKeyBindingJWTValidationOptions \| undefined | - - - -### keyBindingJWTValidationOptions.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - - -### keyBindingJWTValidationOptions.clone() ⇒ [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) -Deep clones the object. - -**Kind**: instance method of [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - - -### KeyBindingJWTValidationOptions.fromJSON(json) ⇒ [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) -Deserializes an instance from a JSON object. - -**Kind**: static method of [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) - -| Param | Type | -| --- | --- | -| json | any | - - - -## KeyBindingJwtClaims -Claims set for key binding JWT. - -**Kind**: global class - -* [KeyBindingJwtClaims](#KeyBindingJwtClaims) - * [new KeyBindingJwtClaims(jwt, disclosures, nonce, aud, [issued_at], [custom_properties])](#new_KeyBindingJwtClaims_new) - * _instance_ - * [.toString()](#KeyBindingJwtClaims+toString) ⇒ string - * [.iat()](#KeyBindingJwtClaims+iat) ⇒ bigint - * [.aud()](#KeyBindingJwtClaims+aud) ⇒ string - * [.nonce()](#KeyBindingJwtClaims+nonce) ⇒ string - * [.sdHash()](#KeyBindingJwtClaims+sdHash) ⇒ string - * [.customProperties()](#KeyBindingJwtClaims+customProperties) ⇒ Record.<string, any> - * [.toJSON()](#KeyBindingJwtClaims+toJSON) ⇒ any - * [.clone()](#KeyBindingJwtClaims+clone) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) - * _static_ - * [.keyBindingJwtHeaderTyp()](#KeyBindingJwtClaims.keyBindingJwtHeaderTyp) ⇒ string - * [.fromJSON(json)](#KeyBindingJwtClaims.fromJSON) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - - -### new KeyBindingJwtClaims(jwt, disclosures, nonce, aud, [issued_at], [custom_properties]) -Creates a new [`KeyBindingJwtClaims`]. -When `issued_at` is left as None, it will automatically default to the current time. - -# Error -When `issued_at` is set to `None` and the system returns time earlier than `SystemTime::UNIX_EPOCH`. - - -| Param | Type | -| --- | --- | -| jwt | string | -| disclosures | Array.<string> | -| nonce | string | -| aud | string | -| [issued_at] | [Timestamp](#Timestamp) \| undefined | -| [custom_properties] | Record.<string, any> \| undefined | - - - -### keyBindingJwtClaims.toString() ⇒ string -Returns a string representation of the claims. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.iat() ⇒ bigint -Returns a copy of the issued at `iat` property. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.aud() ⇒ string -Returns a copy of the audience `aud` property. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.nonce() ⇒ string -Returns a copy of the `nonce` property. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.sdHash() ⇒ string -Returns a copy of the `sd_hash` property. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.customProperties() ⇒ Record.<string, any> -Returns a copy of the custom properties. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### keyBindingJwtClaims.clone() ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) -Deep clones the object. - -**Kind**: instance method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### KeyBindingJwtClaims.keyBindingJwtHeaderTyp() ⇒ string -Returns the value of the `typ` property of the JWT header according to -https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html#name-key-binding-jwt - -**Kind**: static method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - -### KeyBindingJwtClaims.fromJSON(json) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) -Deserializes an instance from a JSON object. - -**Kind**: static method of [KeyBindingJwtClaims](#KeyBindingJwtClaims) - -| Param | Type | -| --- | --- | -| json | any | - - - -## LinkedDomainService -**Kind**: global class - -* [LinkedDomainService](#LinkedDomainService) - * [new LinkedDomainService(options)](#new_LinkedDomainService_new) - * _instance_ - * [.domains()](#LinkedDomainService+domains) ⇒ Array.<string> - * [.toService()](#LinkedDomainService+toService) ⇒ [Service](#Service) - * [.clone()](#LinkedDomainService+clone) ⇒ [LinkedDomainService](#LinkedDomainService) - * _static_ - * [.fromService(service)](#LinkedDomainService.fromService) ⇒ [LinkedDomainService](#LinkedDomainService) - * [.isValid(service)](#LinkedDomainService.isValid) ⇒ boolean - - - -### new LinkedDomainService(options) -Constructs a new [LinkedDomainService](#LinkedDomainService) that wraps a spec compliant [Linked Domain Service Endpoint](https://identity.foundation/.well-known/resources/did-configuration/#linked-domain-service-endpoint). - -Domain URLs must include the `https` scheme in order to pass the domain linkage validation. - - -| Param | Type | -| --- | --- | -| options | ILinkedDomainService | - - - -### linkedDomainService.domains() ⇒ Array.<string> -Returns the domains contained in the Linked Domain Service. - -**Kind**: instance method of [LinkedDomainService](#LinkedDomainService) - - -### linkedDomainService.toService() ⇒ [Service](#Service) -Returns the inner service which can be added to a DID Document. - -**Kind**: instance method of [LinkedDomainService](#LinkedDomainService) - - -### linkedDomainService.clone() ⇒ [LinkedDomainService](#LinkedDomainService) -Deep clones the object. - -**Kind**: instance method of [LinkedDomainService](#LinkedDomainService) - - -### LinkedDomainService.fromService(service) ⇒ [LinkedDomainService](#LinkedDomainService) -Creates a new [LinkedDomainService](#LinkedDomainService) from a [Service](#Service). - -# Error - -Errors if `service` is not a valid Linked Domain Service. - -**Kind**: static method of [LinkedDomainService](#LinkedDomainService) - -| Param | Type | -| --- | --- | -| service | [Service](#Service) | - - - -### LinkedDomainService.isValid(service) ⇒ boolean -Returns `true` if a [Service](#Service) is a valid Linked Domain Service. - -**Kind**: static method of [LinkedDomainService](#LinkedDomainService) - -| Param | Type | -| --- | --- | -| service | [Service](#Service) | - - - -## MethodData -Supported verification method data formats. - -**Kind**: global class - -* [MethodData](#MethodData) - * _instance_ - * [.tryCustom()](#MethodData+tryCustom) ⇒ [CustomMethodData](#CustomMethodData) - * [.tryDecode()](#MethodData+tryDecode) ⇒ Uint8Array - * [.tryPublicKeyJwk()](#MethodData+tryPublicKeyJwk) ⇒ [Jwk](#Jwk) - * [.toJSON()](#MethodData+toJSON) ⇒ any - * [.clone()](#MethodData+clone) ⇒ [MethodData](#MethodData) - * _static_ - * [.newBase58(data)](#MethodData.newBase58) ⇒ [MethodData](#MethodData) - * [.newMultibase(data)](#MethodData.newMultibase) ⇒ [MethodData](#MethodData) - * [.newJwk(key)](#MethodData.newJwk) ⇒ [MethodData](#MethodData) - * [.newCustom(name, data)](#MethodData.newCustom) ⇒ [MethodData](#MethodData) - * [.fromJSON(json)](#MethodData.fromJSON) ⇒ [MethodData](#MethodData) - - - -### methodData.tryCustom() ⇒ [CustomMethodData](#CustomMethodData) -Returns the wrapped custom method data format is `Custom`. - -**Kind**: instance method of [MethodData](#MethodData) - - -### methodData.tryDecode() ⇒ Uint8Array -Returns a `Uint8Array` containing the decoded bytes of the [MethodData](#MethodData). - -This is generally a public key identified by a [MethodData](#MethodData) value. - -### Errors -Decoding can fail if [MethodData](#MethodData) has invalid content or cannot be -represented as a vector of bytes. - -**Kind**: instance method of [MethodData](#MethodData) - - -### methodData.tryPublicKeyJwk() ⇒ [Jwk](#Jwk) -Returns the wrapped [Jwk](#Jwk) if the format is `PublicKeyJwk`. - -**Kind**: instance method of [MethodData](#MethodData) - - -### methodData.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [MethodData](#MethodData) - - -### methodData.clone() ⇒ [MethodData](#MethodData) -Deep clones the object. - -**Kind**: instance method of [MethodData](#MethodData) - - -### MethodData.newBase58(data) ⇒ [MethodData](#MethodData) -Creates a new [MethodData](#MethodData) variant with Base58-BTC encoded content. - -**Kind**: static method of [MethodData](#MethodData) - -| Param | Type | -| --- | --- | -| data | Uint8Array | - - - -### MethodData.newMultibase(data) ⇒ [MethodData](#MethodData) -Creates a new [MethodData](#MethodData) variant with Multibase-encoded content. - -**Kind**: static method of [MethodData](#MethodData) - -| Param | Type | -| --- | --- | -| data | Uint8Array | - - - -### MethodData.newJwk(key) ⇒ [MethodData](#MethodData) -Creates a new [MethodData](#MethodData) variant consisting of the given `key`. - -### Errors -An error is thrown if the given `key` contains any private components. - -**Kind**: static method of [MethodData](#MethodData) - -| Param | Type | -| --- | --- | -| key | [Jwk](#Jwk) | - - - -### MethodData.newCustom(name, data) ⇒ [MethodData](#MethodData) -Creates a new custom [MethodData](#MethodData). - -**Kind**: static method of [MethodData](#MethodData) - -| Param | Type | -| --- | --- | -| name | string | -| data | any | - - - -### MethodData.fromJSON(json) ⇒ [MethodData](#MethodData) -Deserializes an instance from a JSON object. - -**Kind**: static method of [MethodData](#MethodData) - -| Param | Type | -| --- | --- | -| json | any | - - - -## MethodDigest -Unique identifier of a [VerificationMethod](#VerificationMethod). - -NOTE: -This class does not have a JSON representation, -use the methods `pack` and `unpack` instead. - -**Kind**: global class - -* [MethodDigest](#MethodDigest) - * [new MethodDigest(verification_method)](#new_MethodDigest_new) - * _instance_ - * [.pack()](#MethodDigest+pack) ⇒ Uint8Array - * [.clone()](#MethodDigest+clone) ⇒ [MethodDigest](#MethodDigest) - * _static_ - * [.unpack(bytes)](#MethodDigest.unpack) ⇒ [MethodDigest](#MethodDigest) - - - -### new MethodDigest(verification_method) - -| Param | Type | -| --- | --- | -| verification_method | [VerificationMethod](#VerificationMethod) | - - - -### methodDigest.pack() ⇒ Uint8Array -Packs [MethodDigest](#MethodDigest) into bytes. - -**Kind**: instance method of [MethodDigest](#MethodDigest) - - -### methodDigest.clone() ⇒ [MethodDigest](#MethodDigest) -Deep clones the object. - -**Kind**: instance method of [MethodDigest](#MethodDigest) - - -### MethodDigest.unpack(bytes) ⇒ [MethodDigest](#MethodDigest) -Unpacks bytes into [MethodDigest](#MethodDigest). - -**Kind**: static method of [MethodDigest](#MethodDigest) - -| Param | Type | -| --- | --- | -| bytes | Uint8Array | - - - -## MethodScope -Supported verification method types. - -**Kind**: global class - -* [MethodScope](#MethodScope) - * _instance_ - * [.toString()](#MethodScope+toString) ⇒ string - * [.toJSON()](#MethodScope+toJSON) ⇒ any - * [.clone()](#MethodScope+clone) ⇒ [MethodScope](#MethodScope) - * _static_ - * [.VerificationMethod()](#MethodScope.VerificationMethod) ⇒ [MethodScope](#MethodScope) - * [.Authentication()](#MethodScope.Authentication) ⇒ [MethodScope](#MethodScope) - * [.AssertionMethod()](#MethodScope.AssertionMethod) ⇒ [MethodScope](#MethodScope) - * [.KeyAgreement()](#MethodScope.KeyAgreement) ⇒ [MethodScope](#MethodScope) - * [.CapabilityDelegation()](#MethodScope.CapabilityDelegation) ⇒ [MethodScope](#MethodScope) - * [.CapabilityInvocation()](#MethodScope.CapabilityInvocation) ⇒ [MethodScope](#MethodScope) - * [.fromJSON(json)](#MethodScope.fromJSON) ⇒ [MethodScope](#MethodScope) - - - -### methodScope.toString() ⇒ string -Returns the [MethodScope](#MethodScope) as a string. - -**Kind**: instance method of [MethodScope](#MethodScope) - - -### methodScope.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [MethodScope](#MethodScope) - - -### methodScope.clone() ⇒ [MethodScope](#MethodScope) -Deep clones the object. - -**Kind**: instance method of [MethodScope](#MethodScope) - - -### MethodScope.VerificationMethod() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.Authentication() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.AssertionMethod() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.KeyAgreement() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.CapabilityDelegation() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.CapabilityInvocation() ⇒ [MethodScope](#MethodScope) -**Kind**: static method of [MethodScope](#MethodScope) - - -### MethodScope.fromJSON(json) ⇒ [MethodScope](#MethodScope) -Deserializes an instance from a JSON object. - -**Kind**: static method of [MethodScope](#MethodScope) - -| Param | Type | -| --- | --- | -| json | any | - - - -## MethodType -Supported verification method types. - -**Kind**: global class - -* [MethodType](#MethodType) - * _instance_ - * [.toString()](#MethodType+toString) ⇒ string - * [.toJSON()](#MethodType+toJSON) ⇒ any - * [.clone()](#MethodType+clone) ⇒ [MethodType](#MethodType) - * _static_ - * [.Ed25519VerificationKey2018()](#MethodType.Ed25519VerificationKey2018) ⇒ [MethodType](#MethodType) - * [.X25519KeyAgreementKey2019()](#MethodType.X25519KeyAgreementKey2019) ⇒ [MethodType](#MethodType) - * ~~[.JsonWebKey()](#MethodType.JsonWebKey)~~ - * [.JsonWebKey2020()](#MethodType.JsonWebKey2020) ⇒ [MethodType](#MethodType) - * [.custom(type_)](#MethodType.custom) ⇒ [MethodType](#MethodType) - * [.fromJSON(json)](#MethodType.fromJSON) ⇒ [MethodType](#MethodType) - - - -### methodType.toString() ⇒ string -Returns the [MethodType](#MethodType) as a string. - -**Kind**: instance method of [MethodType](#MethodType) - - -### methodType.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [MethodType](#MethodType) - - -### methodType.clone() ⇒ [MethodType](#MethodType) -Deep clones the object. - -**Kind**: instance method of [MethodType](#MethodType) - - -### MethodType.Ed25519VerificationKey2018() ⇒ [MethodType](#MethodType) -**Kind**: static method of [MethodType](#MethodType) - - -### MethodType.X25519KeyAgreementKey2019() ⇒ [MethodType](#MethodType) -**Kind**: static method of [MethodType](#MethodType) - - -### ~~MethodType.JsonWebKey()~~ -***Deprecated*** - -**Kind**: static method of [MethodType](#MethodType) - - -### MethodType.JsonWebKey2020() ⇒ [MethodType](#MethodType) -A verification method for use with JWT verification as prescribed by the [Jwk](#Jwk) -in the `publicKeyJwk` entry. - -**Kind**: static method of [MethodType](#MethodType) - - -### MethodType.custom(type_) ⇒ [MethodType](#MethodType) -A custom method. - -**Kind**: static method of [MethodType](#MethodType) - -| Param | Type | -| --- | --- | -| type_ | string | - - - -### MethodType.fromJSON(json) ⇒ [MethodType](#MethodType) -Deserializes an instance from a JSON object. - -**Kind**: static method of [MethodType](#MethodType) - -| Param | Type | -| --- | --- | -| json | any | - - - -## PayloadEntry -**Kind**: global class - -* [PayloadEntry](#PayloadEntry) - * [.1](#PayloadEntry+1) ⇒ [PayloadType](#PayloadType) - * [.1](#PayloadEntry+1) - * [.value](#PayloadEntry+value) - * [.value](#PayloadEntry+value) ⇒ any - - - -### payloadEntry.1 ⇒ [PayloadType](#PayloadType) -**Kind**: instance property of [PayloadEntry](#PayloadEntry) - - -### payloadEntry.1 -**Kind**: instance property of [PayloadEntry](#PayloadEntry) - -| Param | Type | -| --- | --- | -| arg0 | [PayloadType](#PayloadType) | - - - -### payloadEntry.value -**Kind**: instance property of [PayloadEntry](#PayloadEntry) - -| Param | Type | -| --- | --- | -| value | any | - - - -### payloadEntry.value ⇒ any -**Kind**: instance property of [PayloadEntry](#PayloadEntry) - - -## Payloads -**Kind**: global class - -* [Payloads](#Payloads) - * [new Payloads(entries)](#new_Payloads_new) - * _instance_ - * [.toJSON()](#Payloads+toJSON) ⇒ any - * [.clone()](#Payloads+clone) ⇒ [Payloads](#Payloads) - * [.getValues()](#Payloads+getValues) ⇒ Array.<any> - * [.getUndisclosedIndexes()](#Payloads+getUndisclosedIndexes) ⇒ Uint32Array - * [.getDisclosedIndexes()](#Payloads+getDisclosedIndexes) ⇒ Uint32Array - * [.getUndisclosedPayloads()](#Payloads+getUndisclosedPayloads) ⇒ Array.<any> - * [.getDisclosedPayloads()](#Payloads+getDisclosedPayloads) ⇒ [Payloads](#Payloads) - * [.setUndisclosed(index)](#Payloads+setUndisclosed) - * [.replacePayloadAtIndex(index, value)](#Payloads+replacePayloadAtIndex) ⇒ any - * _static_ - * [.fromJSON(json)](#Payloads.fromJSON) ⇒ [Payloads](#Payloads) - * [.newFromValues(values)](#Payloads.newFromValues) ⇒ [Payloads](#Payloads) - - - -### new Payloads(entries) - -| Param | Type | -| --- | --- | -| entries | [Array.<PayloadEntry>](#PayloadEntry) | - - - -### payloads.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.clone() ⇒ [Payloads](#Payloads) -Deep clones the object. - -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.getValues() ⇒ Array.<any> -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.getUndisclosedIndexes() ⇒ Uint32Array -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.getDisclosedIndexes() ⇒ Uint32Array -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.getUndisclosedPayloads() ⇒ Array.<any> -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.getDisclosedPayloads() ⇒ [Payloads](#Payloads) -**Kind**: instance method of [Payloads](#Payloads) - - -### payloads.setUndisclosed(index) -**Kind**: instance method of [Payloads](#Payloads) - -| Param | Type | -| --- | --- | -| index | number | - - - -### payloads.replacePayloadAtIndex(index, value) ⇒ any -**Kind**: instance method of [Payloads](#Payloads) - -| Param | Type | -| --- | --- | -| index | number | -| value | any | - - - -### Payloads.fromJSON(json) ⇒ [Payloads](#Payloads) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Payloads](#Payloads) - -| Param | Type | -| --- | --- | -| json | any | - - - -### Payloads.newFromValues(values) ⇒ [Payloads](#Payloads) -**Kind**: static method of [Payloads](#Payloads) - -| Param | Type | -| --- | --- | -| values | Array.<any> | - - - -## Presentation -**Kind**: global class - -* [Presentation](#Presentation) - * [new Presentation(values)](#new_Presentation_new) - * _instance_ - * [.context()](#Presentation+context) ⇒ Array.<(string\|Record.<string, any>)> - * [.id()](#Presentation+id) ⇒ string \| undefined - * [.type()](#Presentation+type) ⇒ Array.<string> - * [.verifiableCredential()](#Presentation+verifiableCredential) ⇒ [Array.<UnknownCredential>](#UnknownCredential) - * [.holder()](#Presentation+holder) ⇒ string - * [.refreshService()](#Presentation+refreshService) ⇒ Array.<RefreshService> - * [.termsOfUse()](#Presentation+termsOfUse) ⇒ Array.<Policy> - * [.proof()](#Presentation+proof) ⇒ [Proof](#Proof) \| undefined - * [.setProof([proof])](#Presentation+setProof) - * [.properties()](#Presentation+properties) ⇒ Map.<string, any> - * [.toJSON()](#Presentation+toJSON) ⇒ any - * [.clone()](#Presentation+clone) ⇒ [Presentation](#Presentation) - * _static_ - * [.BaseContext()](#Presentation.BaseContext) ⇒ string - * [.BaseType()](#Presentation.BaseType) ⇒ string - * [.fromJSON(json)](#Presentation.fromJSON) ⇒ [Presentation](#Presentation) - - - -### new Presentation(values) -Constructs a new presentation. - - -| Param | Type | -| --- | --- | -| values | IPresentation | - - - -### presentation.context() ⇒ Array.<(string\|Record.<string, any>)> -Returns a copy of the JSON-LD context(s) applicable to the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.id() ⇒ string \| undefined -Returns a copy of the unique `URI` identifying the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.type() ⇒ Array.<string> -Returns a copy of the URIs defining the type of the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.verifiableCredential() ⇒ [Array.<UnknownCredential>](#UnknownCredential) -Returns the JWT credentials expressing the claims of the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.holder() ⇒ string -Returns a copy of the URI of the entity that generated the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.refreshService() ⇒ Array.<RefreshService> -Returns a copy of the service(s) used to refresh an expired [Credential](#Credential) in the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.termsOfUse() ⇒ Array.<Policy> -Returns a copy of the terms-of-use specified by the presentation holder - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.proof() ⇒ [Proof](#Proof) \| undefined -Optional cryptographic proof, unrelated to JWT. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.setProof([proof]) -Sets the proof property of the [Presentation](#Presentation). - -Note that this proof is not related to JWT. - -**Kind**: instance method of [Presentation](#Presentation) - -| Param | Type | -| --- | --- | -| [proof] | [Proof](#Proof) \| undefined | - - - -### presentation.properties() ⇒ Map.<string, any> -Returns a copy of the miscellaneous properties on the presentation. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Presentation](#Presentation) - - -### presentation.clone() ⇒ [Presentation](#Presentation) -Deep clones the object. - -**Kind**: instance method of [Presentation](#Presentation) - - -### Presentation.BaseContext() ⇒ string -Returns the base JSON-LD context. - -**Kind**: static method of [Presentation](#Presentation) - - -### Presentation.BaseType() ⇒ string -Returns the base type. - -**Kind**: static method of [Presentation](#Presentation) - - -### Presentation.fromJSON(json) ⇒ [Presentation](#Presentation) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Presentation](#Presentation) - -| Param | Type | -| --- | --- | -| json | any | - - - -## PresentationProtectedHeader -**Kind**: global class - -* [PresentationProtectedHeader](#PresentationProtectedHeader) - * [.alg](#PresentationProtectedHeader+alg) ⇒ [PresentationProofAlgorithm](#PresentationProofAlgorithm) - * [.alg](#PresentationProtectedHeader+alg) - * [.kid](#PresentationProtectedHeader+kid) ⇒ string \| undefined - * [.kid](#PresentationProtectedHeader+kid) - * [.aud](#PresentationProtectedHeader+aud) ⇒ string \| undefined - * [.aud](#PresentationProtectedHeader+aud) - * [.nonce](#PresentationProtectedHeader+nonce) ⇒ string \| undefined - * [.nonce](#PresentationProtectedHeader+nonce) - - - -### presentationProtectedHeader.alg ⇒ [PresentationProofAlgorithm](#PresentationProofAlgorithm) -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - - -### presentationProtectedHeader.alg -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - -| Param | Type | -| --- | --- | -| arg0 | [PresentationProofAlgorithm](#PresentationProofAlgorithm) | - - - -### presentationProtectedHeader.kid ⇒ string \| undefined -ID for the key used for the JWP. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - - -### presentationProtectedHeader.kid -ID for the key used for the JWP. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### presentationProtectedHeader.aud ⇒ string \| undefined -Who have received the JPT. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - - -### presentationProtectedHeader.aud -Who have received the JPT. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -### presentationProtectedHeader.nonce ⇒ string \| undefined -For replay attacks. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - - -### presentationProtectedHeader.nonce -For replay attacks. - -**Kind**: instance property of [PresentationProtectedHeader](#PresentationProtectedHeader) - -| Param | Type | -| --- | --- | -| [arg0] | string \| undefined | - - - -## Proof -Represents a cryptographic proof that can be used to validate verifiable credentials and -presentations. - -This representation does not inherently implement any standard; instead, it -can be utilized to implement standards or user-defined proofs. The presence of the -`type` field is necessary to accommodate different types of cryptographic proofs. - -Note that this proof is not related to JWT and can be used in combination or as an alternative -to it. - -**Kind**: global class - -* [Proof](#Proof) - * [new Proof(type_, properties)](#new_Proof_new) - * _instance_ - * [.type()](#Proof+type) ⇒ string - * [.properties()](#Proof+properties) ⇒ any - * [.toJSON()](#Proof+toJSON) ⇒ any - * [.clone()](#Proof+clone) ⇒ [Proof](#Proof) - * _static_ - * [.fromJSON(json)](#Proof.fromJSON) ⇒ [Proof](#Proof) - - - -### new Proof(type_, properties) - -| Param | Type | -| --- | --- | -| type_ | string | -| properties | any | - - - -### proof.type() ⇒ string -Returns the type of proof. - -**Kind**: instance method of [Proof](#Proof) - - -### proof.properties() ⇒ any -Returns the properties of the proof. - -**Kind**: instance method of [Proof](#Proof) - - -### proof.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Proof](#Proof) - - -### proof.clone() ⇒ [Proof](#Proof) -Deep clones the object. - -**Kind**: instance method of [Proof](#Proof) - - -### Proof.fromJSON(json) ⇒ [Proof](#Proof) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Proof](#Proof) - -| Param | Type | -| --- | --- | -| json | any | - - - -## ProofUpdateCtx -**Kind**: global class - -* [ProofUpdateCtx](#ProofUpdateCtx) - * [.old_start_validity_timeframe](#ProofUpdateCtx+old_start_validity_timeframe) ⇒ Uint8Array - * [.old_start_validity_timeframe](#ProofUpdateCtx+old_start_validity_timeframe) - * [.new_start_validity_timeframe](#ProofUpdateCtx+new_start_validity_timeframe) ⇒ Uint8Array - * [.new_start_validity_timeframe](#ProofUpdateCtx+new_start_validity_timeframe) - * [.old_end_validity_timeframe](#ProofUpdateCtx+old_end_validity_timeframe) ⇒ Uint8Array - * [.old_end_validity_timeframe](#ProofUpdateCtx+old_end_validity_timeframe) - * [.new_end_validity_timeframe](#ProofUpdateCtx+new_end_validity_timeframe) ⇒ Uint8Array - * [.new_end_validity_timeframe](#ProofUpdateCtx+new_end_validity_timeframe) - * [.index_start_validity_timeframe](#ProofUpdateCtx+index_start_validity_timeframe) ⇒ number - * [.index_start_validity_timeframe](#ProofUpdateCtx+index_start_validity_timeframe) - * [.index_end_validity_timeframe](#ProofUpdateCtx+index_end_validity_timeframe) ⇒ number - * [.index_end_validity_timeframe](#ProofUpdateCtx+index_end_validity_timeframe) - * [.number_of_signed_messages](#ProofUpdateCtx+number_of_signed_messages) ⇒ number - * [.number_of_signed_messages](#ProofUpdateCtx+number_of_signed_messages) - - - -### proofUpdateCtx.old\_start\_validity\_timeframe ⇒ Uint8Array -Old `startValidityTimeframe` value - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.old\_start\_validity\_timeframe -Old `startValidityTimeframe` value - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | Uint8Array | - - - -### proofUpdateCtx.new\_start\_validity\_timeframe ⇒ Uint8Array -New `startValidityTimeframe` value to be signed - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.new\_start\_validity\_timeframe -New `startValidityTimeframe` value to be signed - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | Uint8Array | - - - -### proofUpdateCtx.old\_end\_validity\_timeframe ⇒ Uint8Array -Old `endValidityTimeframe` value - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.old\_end\_validity\_timeframe -Old `endValidityTimeframe` value - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | Uint8Array | - - - -### proofUpdateCtx.new\_end\_validity\_timeframe ⇒ Uint8Array -New `endValidityTimeframe` value to be signed - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.new\_end\_validity\_timeframe -New `endValidityTimeframe` value to be signed - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | Uint8Array | - - - -### proofUpdateCtx.index\_start\_validity\_timeframe ⇒ number -Index of `startValidityTimeframe` claim inside the array of Claims - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.index\_start\_validity\_timeframe -Index of `startValidityTimeframe` claim inside the array of Claims - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | number | - - - -### proofUpdateCtx.index\_end\_validity\_timeframe ⇒ number -Index of `endValidityTimeframe` claim inside the array of Claims - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.index\_end\_validity\_timeframe -Index of `endValidityTimeframe` claim inside the array of Claims - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | number | - - - -### proofUpdateCtx.number\_of\_signed\_messages ⇒ number -Number of signed messages, number of payloads in a JWP - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - - -### proofUpdateCtx.number\_of\_signed\_messages -Number of signed messages, number of payloads in a JWP - -**Kind**: instance property of [ProofUpdateCtx](#ProofUpdateCtx) - -| Param | Type | -| --- | --- | -| arg0 | number | - - - -## Resolver -Convenience type for resolving DID documents from different DID methods. - -Also provides methods for resolving DID Documents associated with -verifiable [Credential](#Credential)s and [Presentation](#Presentation)s. - -# Configuration - -The resolver will only be able to resolve DID documents for methods it has been configured for in the constructor. - -**Kind**: global class - -* [Resolver](#Resolver) - * [new Resolver(config)](#new_Resolver_new) - * [.resolve(did)](#Resolver+resolve) ⇒ Promise.<(CoreDocument\|IToCoreDocument)> - * [.resolveMultiple(dids)](#Resolver+resolveMultiple) ⇒ Promise.<Array.<(CoreDocument\|IToCoreDocument)>> - - - -### new Resolver(config) -Constructs a new [Resolver](#Resolver). - -# Errors -If both a `client` is given and the `handlers` map contains the "iota" key the construction process -will throw an error because the handler for the "iota" method then becomes ambiguous. - - -| Param | Type | -| --- | --- | -| config | ResolverConfig | - - - -### resolver.resolve(did) ⇒ Promise.<(CoreDocument\|IToCoreDocument)> -Fetches the DID Document of the given DID. - -### Errors - -Errors if the resolver has not been configured to handle the method -corresponding to the given DID or the resolution process itself fails. - -**Kind**: instance method of [Resolver](#Resolver) - -| Param | Type | -| --- | --- | -| did | string | - - - -### resolver.resolveMultiple(dids) ⇒ Promise.<Array.<(CoreDocument\|IToCoreDocument)>> -Concurrently fetches the DID Documents of the multiple given DIDs. - -# Errors -* If the resolver has not been configured to handle the method of any of the given DIDs. -* If the resolution process of any DID fails. - -## Note -* The order of the documents in the returned array matches that in `dids`. -* If `dids` contains duplicates, these will be resolved only once and the resolved document -is copied into the returned array to match the order of `dids`. - -**Kind**: instance method of [Resolver](#Resolver) - -| Param | Type | -| --- | --- | -| dids | Array.<string> | - - - -## RevocationBitmap -A compressed bitmap for managing credential revocation. - -**Kind**: global class - -* [RevocationBitmap](#RevocationBitmap) - * [new RevocationBitmap()](#new_RevocationBitmap_new) - * _instance_ - * [.isRevoked(index)](#RevocationBitmap+isRevoked) ⇒ boolean - * [.revoke(index)](#RevocationBitmap+revoke) ⇒ boolean - * [.unrevoke(index)](#RevocationBitmap+unrevoke) ⇒ boolean - * [.len()](#RevocationBitmap+len) ⇒ number - * [.toService(serviceId)](#RevocationBitmap+toService) ⇒ [Service](#Service) - * _static_ - * [.type()](#RevocationBitmap.type) ⇒ string - * [.fromEndpoint(service)](#RevocationBitmap.fromEndpoint) ⇒ [RevocationBitmap](#RevocationBitmap) - - - -### new RevocationBitmap() -Creates a new [RevocationBitmap](#RevocationBitmap) instance. - - - -### revocationBitmap.isRevoked(index) ⇒ boolean -Returns `true` if the credential at the given `index` is revoked. - -**Kind**: instance method of [RevocationBitmap](#RevocationBitmap) - -| Param | Type | -| --- | --- | -| index | number | - - - -### revocationBitmap.revoke(index) ⇒ boolean -Mark the given index as revoked. - -Returns true if the index was absent from the set. - -**Kind**: instance method of [RevocationBitmap](#RevocationBitmap) - -| Param | Type | -| --- | --- | -| index | number | - - - -### revocationBitmap.unrevoke(index) ⇒ boolean -Mark the index as not revoked. - -Returns true if the index was present in the set. - -**Kind**: instance method of [RevocationBitmap](#RevocationBitmap) - -| Param | Type | -| --- | --- | -| index | number | - - - -### revocationBitmap.len() ⇒ number -Returns the number of revoked credentials. - -**Kind**: instance method of [RevocationBitmap](#RevocationBitmap) - - -### revocationBitmap.toService(serviceId) ⇒ [Service](#Service) -Return a `Service` with: -- the service's id set to `serviceId`, -- of type `RevocationBitmap2022`, -- and with the bitmap embedded in a data url in the service's endpoint. - -**Kind**: instance method of [RevocationBitmap](#RevocationBitmap) - -| Param | Type | -| --- | --- | -| serviceId | [DIDUrl](#DIDUrl) | - - - -### RevocationBitmap.type() ⇒ string -The name of the service type. - -**Kind**: static method of [RevocationBitmap](#RevocationBitmap) - - -### RevocationBitmap.fromEndpoint(service) ⇒ [RevocationBitmap](#RevocationBitmap) -Try to construct a [RevocationBitmap](#RevocationBitmap) from a service -if it is a valid Revocation Bitmap Service. - -**Kind**: static method of [RevocationBitmap](#RevocationBitmap) - -| Param | Type | -| --- | --- | -| service | [Service](#Service) | - - - -## RevocationTimeframeStatus -Information used to determine the current status of a [Credential](#Credential). - -**Kind**: global class - -* [RevocationTimeframeStatus](#RevocationTimeframeStatus) - * [new RevocationTimeframeStatus(id, index, duration, [start_validity])](#new_RevocationTimeframeStatus_new) - * _instance_ - * [.clone()](#RevocationTimeframeStatus+clone) ⇒ [RevocationTimeframeStatus](#RevocationTimeframeStatus) - * [.toJSON()](#RevocationTimeframeStatus+toJSON) ⇒ any - * [.startValidityTimeframe()](#RevocationTimeframeStatus+startValidityTimeframe) ⇒ [Timestamp](#Timestamp) - * [.endValidityTimeframe()](#RevocationTimeframeStatus+endValidityTimeframe) ⇒ [Timestamp](#Timestamp) - * [.id()](#RevocationTimeframeStatus+id) ⇒ string - * [.index()](#RevocationTimeframeStatus+index) ⇒ number \| undefined - * _static_ - * [.fromJSON(json)](#RevocationTimeframeStatus.fromJSON) ⇒ [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - - -### new RevocationTimeframeStatus(id, index, duration, [start_validity]) -Creates a new `RevocationTimeframeStatus`. - - -| Param | Type | -| --- | --- | -| id | string | -| index | number | -| duration | [Duration](#Duration) | -| [start_validity] | [Timestamp](#Timestamp) \| undefined | - - - -### revocationTimeframeStatus.clone() ⇒ [RevocationTimeframeStatus](#RevocationTimeframeStatus) -Deep clones the object. - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### revocationTimeframeStatus.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### revocationTimeframeStatus.startValidityTimeframe() ⇒ [Timestamp](#Timestamp) -Get startValidityTimeframe value. - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### revocationTimeframeStatus.endValidityTimeframe() ⇒ [Timestamp](#Timestamp) -Get endValidityTimeframe value. - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### revocationTimeframeStatus.id() ⇒ string -Return the URL fo the `RevocationBitmapStatus`. - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### revocationTimeframeStatus.index() ⇒ number \| undefined -Return the index of the credential in the issuer's revocation bitmap - -**Kind**: instance method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - - -### RevocationTimeframeStatus.fromJSON(json) ⇒ [RevocationTimeframeStatus](#RevocationTimeframeStatus) -Deserializes an instance from a JSON object. - -**Kind**: static method of [RevocationTimeframeStatus](#RevocationTimeframeStatus) - -| Param | Type | -| --- | --- | -| json | any | - - - -## SdJwt -Representation of an SD-JWT of the format -`~~~...~~`. - -**Kind**: global class - -* [SdJwt](#SdJwt) - * [new SdJwt(jwt, disclosures, [key_binding_jwt])](#new_SdJwt_new) - * _instance_ - * [.presentation()](#SdJwt+presentation) ⇒ string - * [.toString()](#SdJwt+toString) ⇒ string - * [.jwt()](#SdJwt+jwt) ⇒ string - * [.disclosures()](#SdJwt+disclosures) ⇒ Array.<string> - * [.keyBindingJwt()](#SdJwt+keyBindingJwt) ⇒ string \| undefined - * [.clone()](#SdJwt+clone) ⇒ [SdJwt](#SdJwt) - * _static_ - * [.parse(sd_jwt)](#SdJwt.parse) ⇒ [SdJwt](#SdJwt) - - - -### new SdJwt(jwt, disclosures, [key_binding_jwt]) -Creates a new `SdJwt` from its components. - - -| Param | Type | -| --- | --- | -| jwt | string | -| disclosures | Array.<string> | -| [key_binding_jwt] | string \| undefined | - - - -### sdJwt.presentation() ⇒ string -Serializes the components into the final SD-JWT. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### sdJwt.toString() ⇒ string -Serializes the components into the final SD-JWT. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### sdJwt.jwt() ⇒ string -The JWT part. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### sdJwt.disclosures() ⇒ Array.<string> -The disclosures part. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### sdJwt.keyBindingJwt() ⇒ string \| undefined -The optional key binding JWT. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### sdJwt.clone() ⇒ [SdJwt](#SdJwt) -Deep clones the object. - -**Kind**: instance method of [SdJwt](#SdJwt) - - -### SdJwt.parse(sd_jwt) ⇒ [SdJwt](#SdJwt) -Parses an SD-JWT into its components as [`SdJwt`]. - -## Error -Returns `DeserializationError` if parsing fails. - -**Kind**: static method of [SdJwt](#SdJwt) - -| Param | Type | -| --- | --- | -| sd_jwt | string | - - - -## SdJwtCredentialValidator -A type for decoding and validating [Credential](#Credential). - -**Kind**: global class - -* [SdJwtCredentialValidator](#SdJwtCredentialValidator) - * [new SdJwtCredentialValidator([signatureVerifier])](#new_SdJwtCredentialValidator_new) - * [.validateCredential(sd_jwt, issuer, options, fail_fast)](#SdJwtCredentialValidator+validateCredential) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) - * [.verifySignature(credential, trustedIssuers, options)](#SdJwtCredentialValidator+verifySignature) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) - * [.validateKeyBindingJwt(sdJwt, holder, options)](#SdJwtCredentialValidator+validateKeyBindingJwt) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) - - - -### new SdJwtCredentialValidator([signatureVerifier]) -Creates a new `SdJwtCredentialValidator`. If a `signatureVerifier` is provided it will be used when -verifying decoded JWS signatures, otherwise the default which is only capable of handling the `EdDSA` -algorithm will be used. - - -| Param | Type | -| --- | --- | -| [signatureVerifier] | IJwsVerifier \| undefined | - - - -### sdJwtCredentialValidator.validateCredential(sd_jwt, issuer, options, fail_fast) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) -Decodes and validates a `Credential` issued as an SD-JWT. A `DecodedJwtCredential` is returned upon success. -The credential is constructed by replacing disclosures following the -[`Selective Disclosure for JWTs (SD-JWT)`](https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html) standard. - -The following properties are validated according to `options`: -- the issuer's signature on the JWS, -- the expiration date, -- the issuance date, -- the semantic structure. - -# Warning -* The key binding JWT is not validated. If needed, it must be validated separately using -`SdJwtValidator::validate_key_binding_jwt`. -* The lack of an error returned from this method is in of itself not enough to conclude that the credential can be -trusted. This section contains more information on additional checks that should be carried out before and after -calling this method. - -## The state of the issuer's DID Document -The caller must ensure that `issuer` represents an up-to-date DID Document. - -## Properties that are not validated - There are many properties defined in [The Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) that are **not** validated, such as: -`proof`, `credentialStatus`, `type`, `credentialSchema`, `refreshService` **and more**. -These should be manually checked after validation, according to your requirements. - -# Errors -An error is returned whenever a validated condition is not satisfied. - -**Kind**: instance method of [SdJwtCredentialValidator](#SdJwtCredentialValidator) - -| Param | Type | -| --- | --- | -| sd_jwt | [SdJwt](#SdJwt) | -| issuer | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| options | [JwtCredentialValidationOptions](#JwtCredentialValidationOptions) | -| fail_fast | [FailFast](#FailFast) | - - - -### sdJwtCredentialValidator.verifySignature(credential, trustedIssuers, options) ⇒ [DecodedJwtCredential](#DecodedJwtCredential) -Decode and verify the JWS signature of a `Credential` issued as an SD-JWT using the DID Document of a trusted -issuer and replaces the disclosures. - -A `DecodedJwtCredential` is returned upon success. - -# Warning -The caller must ensure that the DID Documents of the trusted issuers are up-to-date. - -## Proofs - Only the JWS signature is verified. If the `Credential` contains a `proof` property this will not be verified -by this method. - -# Errors -* If the issuer' URL cannot be parsed. -* If Signature verification fails. -* If SD decoding fails. - -**Kind**: instance method of [SdJwtCredentialValidator](#SdJwtCredentialValidator) - -| Param | Type | -| --- | --- | -| credential | [SdJwt](#SdJwt) | -| trustedIssuers | Array.<(CoreDocument\|IToCoreDocument)> | -| options | [JwsVerificationOptions](#JwsVerificationOptions) | - - - -### sdJwtCredentialValidator.validateKeyBindingJwt(sdJwt, holder, options) ⇒ [KeyBindingJwtClaims](#KeyBindingJwtClaims) -Validates a Key Binding JWT (KB-JWT) according to `https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-07.html#name-key-binding-jwt`. -The Validation process includes: - * Signature validation using public key materials defined in the `holder` document. - * `typ` value in KB-JWT header. - * `sd_hash` claim value in the KB-JWT claim. - * Optional `nonce`, `aud` and issuance date validation. - -**Kind**: instance method of [SdJwtCredentialValidator](#SdJwtCredentialValidator) - -| Param | Type | -| --- | --- | -| sdJwt | [SdJwt](#SdJwt) | -| holder | [CoreDocument](#CoreDocument) \| IToCoreDocument | -| options | [KeyBindingJWTValidationOptions](#KeyBindingJWTValidationOptions) | - - - -## SdObjectDecoder -Substitutes digests in an SD-JWT object by their corresponding plaintext values provided by disclosures. - -**Kind**: global class - -* [SdObjectDecoder](#SdObjectDecoder) - * [new SdObjectDecoder()](#new_SdObjectDecoder_new) - * [.decode(object, disclosures)](#SdObjectDecoder+decode) ⇒ Record.<string, any> - - - -### new SdObjectDecoder() -Creates a new `SdObjectDecoder` with `sha-256` hasher. - - - -### sdObjectDecoder.decode(object, disclosures) ⇒ Record.<string, any> -Decodes an SD-JWT `object` containing by Substituting the digests with their corresponding -plaintext values provided by `disclosures`. - -## Notes -* Claims like `exp` or `iat` are not validated in the process of decoding. -* `_sd_alg` property will be removed if present. - -**Kind**: instance method of [SdObjectDecoder](#SdObjectDecoder) - -| Param | Type | -| --- | --- | -| object | Record.<string, any> | -| disclosures | Array.<string> | - - - -## SdObjectEncoder -Transforms a JSON object into an SD-JWT object by substituting selected values -with their corresponding disclosure digests. - -Note: digests are created using the sha-256 algorithm. - -**Kind**: global class - -* [SdObjectEncoder](#SdObjectEncoder) - * [new SdObjectEncoder(object)](#new_SdObjectEncoder_new) - * [.conceal(path, [salt])](#SdObjectEncoder+conceal) ⇒ [Disclosure](#Disclosure) - * [.addSdAlgProperty()](#SdObjectEncoder+addSdAlgProperty) - * [.encodeToString()](#SdObjectEncoder+encodeToString) ⇒ string - * [.toString()](#SdObjectEncoder+toString) ⇒ string - * [.encodeToObject()](#SdObjectEncoder+encodeToObject) ⇒ Record.<string, any> - * [.toJSON()](#SdObjectEncoder+toJSON) ⇒ any - * [.addDecoys(path, number_of_decoys)](#SdObjectEncoder+addDecoys) - - - -### new SdObjectEncoder(object) -Creates a new `SdObjectEncoder` with `sha-256` hash function. - - -| Param | Type | -| --- | --- | -| object | any | - - - -### sdObjectEncoder.conceal(path, [salt]) ⇒ [Disclosure](#Disclosure) -Substitutes a value with the digest of its disclosure. -If no salt is provided, the disclosure will be created with a random salt value. - -`path` indicates the pointer to the value that will be concealed using the syntax of -[JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901). - -For the following object: - - ``` -{ - "id": "did:value", - "claim1": { - "abc": true - }, - "claim2": ["val_1", "val_2"] -} -``` - -Path "/id" conceals `"id": "did:value"` -Path "/claim1/abc" conceals `"abc": true` -Path "/claim2/0" conceals `val_1` -``` - -## Errors -* `InvalidPath` if pointer is invalid. -* `DataTypeMismatch` if existing SD format is invalid. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - -| Param | Type | -| --- | --- | -| path | string | -| [salt] | string \| undefined | - - - -### sdObjectEncoder.addSdAlgProperty() -Adds the `_sd_alg` property to the top level of the object, with -its value set to "sha-256". - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - - -### sdObjectEncoder.encodeToString() ⇒ string -Returns the modified object as a string. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - - -### sdObjectEncoder.toString() ⇒ string -Returns the modified object as a string. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - - -### sdObjectEncoder.encodeToObject() ⇒ Record.<string, any> -Returns the modified object. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - - -### sdObjectEncoder.toJSON() ⇒ any -Returns the modified object. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - - -### sdObjectEncoder.addDecoys(path, number_of_decoys) -Adds a decoy digest to the specified path. -If path is an empty slice, decoys will be added to the top level. - -**Kind**: instance method of [SdObjectEncoder](#SdObjectEncoder) - -| Param | Type | -| --- | --- | -| path | string | -| number_of_decoys | number | - - - -## SelectiveDisclosurePresentation -Used to construct a JwpPresentedBuilder and handle the selective disclosure of attributes -- @context MUST NOT be blinded -- id MUST be blinded -- type MUST NOT be blinded -- issuer MUST NOT be blinded -- issuanceDate MUST be blinded (if Timeframe Revocation mechanism is used) -- expirationDate MUST be blinded (if Timeframe Revocation mechanism is used) -- credentialSubject (User have to choose which attribute must be blinded) -- credentialSchema MUST NOT be blinded -- credentialStatus MUST NOT be blinded -- refreshService MUST NOT be blinded (probably will be used for Timeslot Revocation mechanism) -- termsOfUse NO reason to use it in ZK VC (will be in any case blinded) -- evidence (User have to choose which attribute must be blinded) - -**Kind**: global class - -* [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) - * [new SelectiveDisclosurePresentation(issued_jwp)](#new_SelectiveDisclosurePresentation_new) - * [.concealInSubject(path)](#SelectiveDisclosurePresentation+concealInSubject) - * [.concealInEvidence(path)](#SelectiveDisclosurePresentation+concealInEvidence) - * [.setPresentationHeader(header)](#SelectiveDisclosurePresentation+setPresentationHeader) - - - -### new SelectiveDisclosurePresentation(issued_jwp) -Initialize a presentation starting from an Issued JWP. -The properties `jti`, `nbf`, `issuanceDate`, `expirationDate` and `termsOfUse` are concealed by default. - - -| Param | Type | -| --- | --- | -| issued_jwp | [JwpIssued](#JwpIssued) | - - - -### selectiveDisclosurePresentation.concealInSubject(path) -Selectively disclose "credentialSubject" attributes. -# Example -``` -{ - "id": 1234, - "name": "Alice", - "mainCourses": ["Object-oriented Programming", "Mathematics"], - "degree": { - "type": "BachelorDegree", - "name": "Bachelor of Science and Arts", - }, - "GPA": "4.0", -} -``` -If you want to undisclose for example the Mathematics course and the name of the degree: -``` -undisclose_subject("mainCourses[1]"); -undisclose_subject("degree.name"); -``` - -**Kind**: instance method of [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) - -| Param | Type | -| --- | --- | -| path | string | - - - -### selectiveDisclosurePresentation.concealInEvidence(path) -Undiscloses "evidence" attributes. - -**Kind**: instance method of [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) - -| Param | Type | -| --- | --- | -| path | string | - - - -### selectiveDisclosurePresentation.setPresentationHeader(header) -Sets presentation protected header. - -**Kind**: instance method of [SelectiveDisclosurePresentation](#SelectiveDisclosurePresentation) - -| Param | Type | -| --- | --- | -| header | [PresentationProtectedHeader](#PresentationProtectedHeader) | - - - -## Service -A DID Document Service used to enable trusted interactions associated with a DID subject. - -**Kind**: global class - -* [Service](#Service) - * [new Service(service)](#new_Service_new) - * _instance_ - * [.id()](#Service+id) ⇒ [DIDUrl](#DIDUrl) - * [.type()](#Service+type) ⇒ Array.<string> - * [.serviceEndpoint()](#Service+serviceEndpoint) ⇒ string \| Array.<string> \| Map.<string, Array.<string>> - * [.properties()](#Service+properties) ⇒ Map.<string, any> - * [.toJSON()](#Service+toJSON) ⇒ any - * [.clone()](#Service+clone) ⇒ [Service](#Service) - * _static_ - * [.fromJSON(json)](#Service.fromJSON) ⇒ [Service](#Service) - - - -### new Service(service) - -| Param | Type | -| --- | --- | -| service | IService | - - - -### service.id() ⇒ [DIDUrl](#DIDUrl) -Returns a copy of the [Service](#Service) id. - -**Kind**: instance method of [Service](#Service) - - -### service.type() ⇒ Array.<string> -Returns a copy of the [Service](#Service) type. - -**Kind**: instance method of [Service](#Service) - - -### service.serviceEndpoint() ⇒ string \| Array.<string> \| Map.<string, Array.<string>> -Returns a copy of the [Service](#Service) endpoint. - -**Kind**: instance method of [Service](#Service) - - -### service.properties() ⇒ Map.<string, any> -Returns a copy of the custom properties on the [Service](#Service). - -**Kind**: instance method of [Service](#Service) - - -### service.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Service](#Service) - - -### service.clone() ⇒ [Service](#Service) -Deep clones the object. - -**Kind**: instance method of [Service](#Service) - - -### Service.fromJSON(json) ⇒ [Service](#Service) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Service](#Service) - -| Param | Type | -| --- | --- | -| json | any | - - - -## StatusList2021 -StatusList2021 data structure as described in [W3C's VC status list 2021](https://www.w3.org/TR/2023/WD-vc-status-list-20230427/). - -**Kind**: global class - -* [StatusList2021](#StatusList2021) - * [new StatusList2021([size])](#new_StatusList2021_new) - * _instance_ - * [.clone()](#StatusList2021+clone) ⇒ [StatusList2021](#StatusList2021) - * [.len()](#StatusList2021+len) ⇒ number - * [.get(index)](#StatusList2021+get) ⇒ boolean - * [.set(index, value)](#StatusList2021+set) - * [.intoEncodedStr()](#StatusList2021+intoEncodedStr) ⇒ string - * _static_ - * [.fromEncodedStr(s)](#StatusList2021.fromEncodedStr) ⇒ [StatusList2021](#StatusList2021) - - - -### new StatusList2021([size]) -Creates a new [StatusList2021](#StatusList2021) of `size` entries. - - -| Param | Type | -| --- | --- | -| [size] | number \| undefined | - - - -### statusList2021.clone() ⇒ [StatusList2021](#StatusList2021) -Deep clones the object. - -**Kind**: instance method of [StatusList2021](#StatusList2021) - - -### statusList2021.len() ⇒ number -Returns the number of entries in this [StatusList2021](#StatusList2021). - -**Kind**: instance method of [StatusList2021](#StatusList2021) - - -### statusList2021.get(index) ⇒ boolean -Returns whether the entry at `index` is set. - -**Kind**: instance method of [StatusList2021](#StatusList2021) - -| Param | Type | -| --- | --- | -| index | number | - - - -### statusList2021.set(index, value) -Sets the value of the `index`-th entry. - -**Kind**: instance method of [StatusList2021](#StatusList2021) - -| Param | Type | -| --- | --- | -| index | number | -| value | boolean | - - - -### statusList2021.intoEncodedStr() ⇒ string -Encodes this [StatusList2021](#StatusList2021) into its compressed -base64 string representation. - -**Kind**: instance method of [StatusList2021](#StatusList2021) - - -### StatusList2021.fromEncodedStr(s) ⇒ [StatusList2021](#StatusList2021) -Attempts to decode a [StatusList2021](#StatusList2021) from a string. - -**Kind**: static method of [StatusList2021](#StatusList2021) - -| Param | Type | -| --- | --- | -| s | string | - - - -## StatusList2021Credential -A parsed [StatusList2021Credential](https://www.w3.org/TR/2023/WD-vc-status-list-20230427/#statuslist2021credential). - -**Kind**: global class - -* [StatusList2021Credential](#StatusList2021Credential) - * [new StatusList2021Credential(credential)](#new_StatusList2021Credential_new) - * _instance_ - * [.id()](#StatusList2021Credential+id) ⇒ string - * [.setCredentialStatus(credential, index, revoked_or_suspended)](#StatusList2021Credential+setCredentialStatus) ⇒ [StatusList2021Entry](#StatusList2021Entry) - * [.purpose()](#StatusList2021Credential+purpose) ⇒ [StatusPurpose](#StatusPurpose) - * [.entry(index)](#StatusList2021Credential+entry) ⇒ [CredentialStatus](#CredentialStatus) - * [.clone()](#StatusList2021Credential+clone) ⇒ [StatusList2021Credential](#StatusList2021Credential) - * [.toJSON()](#StatusList2021Credential+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#StatusList2021Credential.fromJSON) ⇒ [StatusList2021Credential](#StatusList2021Credential) - - - -### new StatusList2021Credential(credential) -Creates a new [StatusList2021Credential](#StatusList2021Credential). - - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | - - - -### statusList2021Credential.id() ⇒ string -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - - -### statusList2021Credential.setCredentialStatus(credential, index, revoked_or_suspended) ⇒ [StatusList2021Entry](#StatusList2021Entry) -Sets the given credential's status using the `index`-th entry of this status list. -Returns the created `credentialStatus`. - -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - -| Param | Type | -| --- | --- | -| credential | [Credential](#Credential) | -| index | number | -| revoked_or_suspended | boolean | - - - -### statusList2021Credential.purpose() ⇒ [StatusPurpose](#StatusPurpose) -Returns the [StatusPurpose](#StatusPurpose) of this [StatusList2021Credential](#StatusList2021Credential). - -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - - -### statusList2021Credential.entry(index) ⇒ [CredentialStatus](#CredentialStatus) -Returns the state of the `index`-th entry, if any. - -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - -| Param | Type | -| --- | --- | -| index | number | - - - -### statusList2021Credential.clone() ⇒ [StatusList2021Credential](#StatusList2021Credential) -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - - -### statusList2021Credential.toJSON() ⇒ any -**Kind**: instance method of [StatusList2021Credential](#StatusList2021Credential) - - -### StatusList2021Credential.fromJSON(json) ⇒ [StatusList2021Credential](#StatusList2021Credential) -**Kind**: static method of [StatusList2021Credential](#StatusList2021Credential) - -| Param | Type | -| --- | --- | -| json | any | - - - -## StatusList2021CredentialBuilder -Builder type to construct valid [StatusList2021Credential](#StatusList2021Credential) istances. - -**Kind**: global class - -* [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [new StatusList2021CredentialBuilder([status_list])](#new_StatusList2021CredentialBuilder_new) - * [.purpose(purpose)](#StatusList2021CredentialBuilder+purpose) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.subjectId(id)](#StatusList2021CredentialBuilder+subjectId) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.expirationDate(time)](#StatusList2021CredentialBuilder+expirationDate) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.issuer(issuer)](#StatusList2021CredentialBuilder+issuer) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.context(context)](#StatusList2021CredentialBuilder+context) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.type(t)](#StatusList2021CredentialBuilder+type) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.proof(proof)](#StatusList2021CredentialBuilder+proof) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - * [.build()](#StatusList2021CredentialBuilder+build) ⇒ [StatusList2021Credential](#StatusList2021Credential) - - - -### new StatusList2021CredentialBuilder([status_list]) -Creates a new [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder). - - -| Param | Type | -| --- | --- | -| [status_list] | [StatusList2021](#StatusList2021) \| undefined | - - - -### statusList2021CredentialBuilder.purpose(purpose) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Sets the purpose of the [StatusList2021Credential](#StatusList2021Credential) that is being created. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| purpose | [StatusPurpose](#StatusPurpose) | - - - -### statusList2021CredentialBuilder.subjectId(id) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Sets `credentialSubject.id`. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| id | string | - - - -### statusList2021CredentialBuilder.expirationDate(time) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Sets the expiration date of the credential. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| time | [Timestamp](#Timestamp) | - - - -### statusList2021CredentialBuilder.issuer(issuer) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Sets the issuer of the credential. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| issuer | string | - - - -### statusList2021CredentialBuilder.context(context) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Sets the context of the credential. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| context | string | - - - -### statusList2021CredentialBuilder.type(t) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Adds a credential type. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| t | string | - - - -### statusList2021CredentialBuilder.proof(proof) ⇒ [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) -Adds a credential's proof. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - -| Param | Type | -| --- | --- | -| proof | [Proof](#Proof) | - - - -### statusList2021CredentialBuilder.build() ⇒ [StatusList2021Credential](#StatusList2021Credential) -Attempts to build a valid [StatusList2021Credential](#StatusList2021Credential) with the previously provided data. - -**Kind**: instance method of [StatusList2021CredentialBuilder](#StatusList2021CredentialBuilder) - - -## StatusList2021Entry -[StatusList2021Entry](https://www.w3.org/TR/2023/WD-vc-status-list-20230427/#statuslist2021entry) implementation. - -**Kind**: global class - -* [StatusList2021Entry](#StatusList2021Entry) - * [new StatusList2021Entry(status_list, purpose, index, [id])](#new_StatusList2021Entry_new) - * _instance_ - * [.id()](#StatusList2021Entry+id) ⇒ string - * [.purpose()](#StatusList2021Entry+purpose) ⇒ [StatusPurpose](#StatusPurpose) - * [.index()](#StatusList2021Entry+index) ⇒ number - * [.statusListCredential()](#StatusList2021Entry+statusListCredential) ⇒ string - * [.toStatus()](#StatusList2021Entry+toStatus) ⇒ Status - * [.clone()](#StatusList2021Entry+clone) ⇒ [StatusList2021Entry](#StatusList2021Entry) - * [.toJSON()](#StatusList2021Entry+toJSON) ⇒ any - * _static_ - * [.fromJSON(json)](#StatusList2021Entry.fromJSON) ⇒ [StatusList2021Entry](#StatusList2021Entry) - - - -### new StatusList2021Entry(status_list, purpose, index, [id]) -Creates a new [StatusList2021Entry](#StatusList2021Entry). - - -| Param | Type | -| --- | --- | -| status_list | string | -| purpose | [StatusPurpose](#StatusPurpose) | -| index | number | -| [id] | string \| undefined | - - - -### statusList2021Entry.id() ⇒ string -Returns this `credentialStatus`'s `id`. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.purpose() ⇒ [StatusPurpose](#StatusPurpose) -Returns the purpose of this entry. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.index() ⇒ number -Returns the index of this entry. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.statusListCredential() ⇒ string -Returns the referenced [StatusList2021Credential](#StatusList2021Credential)'s url. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.toStatus() ⇒ Status -Downcasts [this](this) to [Status](Status) - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.clone() ⇒ [StatusList2021Entry](#StatusList2021Entry) -Deep clones the object. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### statusList2021Entry.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [StatusList2021Entry](#StatusList2021Entry) - - -### StatusList2021Entry.fromJSON(json) ⇒ [StatusList2021Entry](#StatusList2021Entry) -Deserializes an instance from a JSON object. - -**Kind**: static method of [StatusList2021Entry](#StatusList2021Entry) - -| Param | Type | -| --- | --- | -| json | any | - - - -## Storage -A type wrapping a `JwkStorage` and `KeyIdStorage` that should always be used together when -working with storage backed DID documents. - -**Kind**: global class - -* [Storage](#Storage) - * [new Storage(jwkStorage, keyIdStorage)](#new_Storage_new) - * [.keyIdStorage()](#Storage+keyIdStorage) ⇒ KeyIdStorage - * [.keyStorage()](#Storage+keyStorage) ⇒ JwkStorage - - - -### new Storage(jwkStorage, keyIdStorage) -Constructs a new `Storage`. - - -| Param | Type | -| --- | --- | -| jwkStorage | JwkStorage | -| keyIdStorage | KeyIdStorage | - - - -### storage.keyIdStorage() ⇒ KeyIdStorage -Obtain the wrapped `KeyIdStorage`. - -**Kind**: instance method of [Storage](#Storage) - - -### storage.keyStorage() ⇒ JwkStorage -Obtain the wrapped `JwkStorage`. - -**Kind**: instance method of [Storage](#Storage) - - -## Timestamp -**Kind**: global class - -* [Timestamp](#Timestamp) - * [new Timestamp()](#new_Timestamp_new) - * _instance_ - * [.toRFC3339()](#Timestamp+toRFC3339) ⇒ string - * [.checkedAdd(duration)](#Timestamp+checkedAdd) ⇒ [Timestamp](#Timestamp) \| undefined - * [.checkedSub(duration)](#Timestamp+checkedSub) ⇒ [Timestamp](#Timestamp) \| undefined - * [.toJSON()](#Timestamp+toJSON) ⇒ any - * _static_ - * [.parse(input)](#Timestamp.parse) ⇒ [Timestamp](#Timestamp) - * [.nowUTC()](#Timestamp.nowUTC) ⇒ [Timestamp](#Timestamp) - * [.fromJSON(json)](#Timestamp.fromJSON) ⇒ [Timestamp](#Timestamp) - - - -### new Timestamp() -Creates a new [Timestamp](#Timestamp) with the current date and time. - - - -### timestamp.toRFC3339() ⇒ string -Returns the [Timestamp](#Timestamp) as an RFC 3339 `String`. - -**Kind**: instance method of [Timestamp](#Timestamp) - - -### timestamp.checkedAdd(duration) ⇒ [Timestamp](#Timestamp) \| undefined -Computes `self + duration` - -Returns `null` if the operation leads to a timestamp not in the valid range for [RFC 3339](https://tools.ietf.org/html/rfc3339). - -**Kind**: instance method of [Timestamp](#Timestamp) - -| Param | Type | -| --- | --- | -| duration | [Duration](#Duration) | - - - -### timestamp.checkedSub(duration) ⇒ [Timestamp](#Timestamp) \| undefined -Computes `self - duration` - -Returns `null` if the operation leads to a timestamp not in the valid range for [RFC 3339](https://tools.ietf.org/html/rfc3339). - -**Kind**: instance method of [Timestamp](#Timestamp) - -| Param | Type | -| --- | --- | -| duration | [Duration](#Duration) | - - - -### timestamp.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [Timestamp](#Timestamp) - - -### Timestamp.parse(input) ⇒ [Timestamp](#Timestamp) -Parses a [Timestamp](#Timestamp) from the provided input string. - -**Kind**: static method of [Timestamp](#Timestamp) - -| Param | Type | -| --- | --- | -| input | string | - - - -### Timestamp.nowUTC() ⇒ [Timestamp](#Timestamp) -Creates a new [Timestamp](#Timestamp) with the current date and time. - -**Kind**: static method of [Timestamp](#Timestamp) - - -### Timestamp.fromJSON(json) ⇒ [Timestamp](#Timestamp) -Deserializes an instance from a JSON object. - -**Kind**: static method of [Timestamp](#Timestamp) - -| Param | Type | -| --- | --- | -| json | any | - - - -## UnknownCredential -**Kind**: global class - -* [UnknownCredential](#UnknownCredential) - * _instance_ - * [.tryIntoJwt()](#UnknownCredential+tryIntoJwt) ⇒ [Jwt](#Jwt) \| undefined - * [.tryIntoCredential()](#UnknownCredential+tryIntoCredential) ⇒ [Credential](#Credential) \| undefined - * [.tryIntoRaw()](#UnknownCredential+tryIntoRaw) ⇒ Record.<string, any> \| undefined - * [.toJSON()](#UnknownCredential+toJSON) ⇒ any - * [.clone()](#UnknownCredential+clone) ⇒ [UnknownCredential](#UnknownCredential) - * _static_ - * [.fromJSON(json)](#UnknownCredential.fromJSON) ⇒ [UnknownCredential](#UnknownCredential) - - - -### unknownCredential.tryIntoJwt() ⇒ [Jwt](#Jwt) \| undefined -Returns a [Jwt](#Jwt) if the credential is of type string, `undefined` otherwise. - -**Kind**: instance method of [UnknownCredential](#UnknownCredential) - - -### unknownCredential.tryIntoCredential() ⇒ [Credential](#Credential) \| undefined -Returns a [Credential](#Credential) if the credential is of said type, `undefined` otherwise. - -**Kind**: instance method of [UnknownCredential](#UnknownCredential) - - -### unknownCredential.tryIntoRaw() ⇒ Record.<string, any> \| undefined -Returns the contained value as an Object, if it can be converted, `undefined` otherwise. - -**Kind**: instance method of [UnknownCredential](#UnknownCredential) - - -### unknownCredential.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [UnknownCredential](#UnknownCredential) - - -### unknownCredential.clone() ⇒ [UnknownCredential](#UnknownCredential) -Deep clones the object. - -**Kind**: instance method of [UnknownCredential](#UnknownCredential) - - -### UnknownCredential.fromJSON(json) ⇒ [UnknownCredential](#UnknownCredential) -Deserializes an instance from a JSON object. - -**Kind**: static method of [UnknownCredential](#UnknownCredential) - -| Param | Type | -| --- | --- | -| json | any | - - - -## VerificationMethod -A DID Document Verification Method. - -**Kind**: global class - -* [VerificationMethod](#VerificationMethod) - * [new VerificationMethod(id, controller, type_, data)](#new_VerificationMethod_new) - * _instance_ - * [.id()](#VerificationMethod+id) ⇒ [DIDUrl](#DIDUrl) - * [.setId(id)](#VerificationMethod+setId) - * [.controller()](#VerificationMethod+controller) ⇒ [CoreDID](#CoreDID) - * [.setController(did)](#VerificationMethod+setController) - * [.type()](#VerificationMethod+type) ⇒ [MethodType](#MethodType) - * [.setType(type_)](#VerificationMethod+setType) - * [.data()](#VerificationMethod+data) ⇒ [MethodData](#MethodData) - * [.setData(data)](#VerificationMethod+setData) - * [.properties()](#VerificationMethod+properties) ⇒ Map.<string, any> - * [.setPropertyUnchecked(key, value)](#VerificationMethod+setPropertyUnchecked) - * [.toJSON()](#VerificationMethod+toJSON) ⇒ any - * [.clone()](#VerificationMethod+clone) ⇒ [VerificationMethod](#VerificationMethod) - * _static_ - * [.newFromJwk(did, key, [fragment])](#VerificationMethod.newFromJwk) ⇒ [VerificationMethod](#VerificationMethod) - * [.fromJSON(json)](#VerificationMethod.fromJSON) ⇒ [VerificationMethod](#VerificationMethod) - - - -### new VerificationMethod(id, controller, type_, data) -Create a custom [VerificationMethod](#VerificationMethod). - - -| Param | Type | -| --- | --- | -| id | [DIDUrl](#DIDUrl) | -| controller | [CoreDID](#CoreDID) | -| type_ | [MethodType](#MethodType) | -| data | [MethodData](#MethodData) | - - - -### verificationMethod.id() ⇒ [DIDUrl](#DIDUrl) -Returns a copy of the [DIDUrl](#DIDUrl) of the [VerificationMethod](#VerificationMethod)'s `id`. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.setId(id) -Sets the id of the [VerificationMethod](#VerificationMethod). - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| id | [DIDUrl](#DIDUrl) | - - - -### verificationMethod.controller() ⇒ [CoreDID](#CoreDID) -Returns a copy of the `controller` `DID` of the [VerificationMethod](#VerificationMethod). - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.setController(did) -Sets the `controller` `DID` of the [VerificationMethod](#VerificationMethod) object. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| did | [CoreDID](#CoreDID) | - - - -### verificationMethod.type() ⇒ [MethodType](#MethodType) -Returns a copy of the [VerificationMethod](#VerificationMethod) type. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.setType(type_) -Sets the [VerificationMethod](#VerificationMethod) type. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| type_ | [MethodType](#MethodType) | - - - -### verificationMethod.data() ⇒ [MethodData](#MethodData) -Returns a copy of the [VerificationMethod](#VerificationMethod) public key data. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.setData(data) -Sets [VerificationMethod](#VerificationMethod) public key data. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| data | [MethodData](#MethodData) | - - - -### verificationMethod.properties() ⇒ Map.<string, any> -Get custom properties of the Verification Method. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.setPropertyUnchecked(key, value) -Adds a custom property to the Verification Method. -If the value is set to `null`, the custom property will be removed. - -### WARNING -This method can overwrite existing properties like `id` and result -in an invalid Verification Method. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| key | string | -| value | any | - - - -### verificationMethod.toJSON() ⇒ any -Serializes this to a JSON object. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### verificationMethod.clone() ⇒ [VerificationMethod](#VerificationMethod) -Deep clones the object. - -**Kind**: instance method of [VerificationMethod](#VerificationMethod) - - -### VerificationMethod.newFromJwk(did, key, [fragment]) ⇒ [VerificationMethod](#VerificationMethod) -Creates a new [VerificationMethod](#VerificationMethod) from the given `did` and [Jwk](#Jwk). If `fragment` is not given -the `kid` value of the given `key` will be used, if present, otherwise an error is returned. - -### Recommendations -The following recommendations are essentially taken from the `publicKeyJwk` description from the [DID specification](https://www.w3.org/TR/did-core/#dfn-publickeyjwk): -- It is recommended that verification methods that use `Jwks` to represent their public keys use the value of - `kid` as their fragment identifier. This is -done automatically if `None` is passed in as the fragment. -- It is recommended that [Jwk](#Jwk) kid values are set to the public key fingerprint. - -**Kind**: static method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| did | [CoreDID](#CoreDID) \| IToCoreDID | -| key | [Jwk](#Jwk) | -| [fragment] | string \| undefined | - - - -### VerificationMethod.fromJSON(json) ⇒ [VerificationMethod](#VerificationMethod) -Deserializes an instance from a JSON object. - -**Kind**: static method of [VerificationMethod](#VerificationMethod) - -| Param | Type | -| --- | --- | -| json | any | - - - -## StatusCheck -Controls validation behaviour when checking whether or not a credential has been revoked by its -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status). - -**Kind**: global variable - - -## Strict -Validate the status if supported, reject any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -Only `RevocationBitmap2022` is currently supported. - -This is the default. - -**Kind**: global variable - - -## SkipUnsupported -Validate the status if supported, skip any unsupported -[`credentialStatus`](https://www.w3.org/TR/vc-data-model/#status) types. - -**Kind**: global variable - - -## SkipAll -Skip all status checks. - -**Kind**: global variable - - -## SubjectHolderRelationship -Declares how credential subjects must relate to the presentation holder. - -See also the [Subject-Holder Relationship](https://www.w3.org/TR/vc-data-model/#subject-holder-relationships) section of the specification. - -## CredentialStatus -**Kind**: global variable - - -## encodeB64(data) ⇒ string -Encode the given bytes in url-safe base64. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| data | Uint8Array | - - - -## decodeB64(data) ⇒ Uint8Array -Decode the given url-safe base64-encoded slice into its raw bytes. - -**Kind**: global variable - - -## PresentationProofAlgorithm -**Kind**: global variable - - -## StatusPurpose -Purpose of a [StatusList2021](#StatusList2021). - -**Kind**: global variable - - -## ProofAlgorithm -**Kind**: global variable - - -## CredentialStatus -**Kind**: global variable - - -## FailFast -Declares when validation should return if an error occurs. - -**Kind**: global variable - - -## AllErrors -Return all errors that occur during validation. - -**Kind**: global variable - - -## FirstError -Return after the first error occurs. - -**Kind**: global variable - - -## StateMetadataEncoding -**Kind**: global variable - - -## SerializationType -**Kind**: global variable - - -## PayloadType -**Kind**: global variable - - -## MethodRelationship -**Kind**: global variable - - -## verifyEd25519(alg, signingInput, decodedSignature, publicKey) -Verify a JWS signature secured with the `EdDSA` algorithm and curve `Ed25519`. - -This function is useful when one is composing a `IJwsVerifier` that delegates -`EdDSA` verification with curve `Ed25519` to this function. - -# Warning - -This function does not check whether `alg = EdDSA` in the protected header. Callers are expected to assert this -prior to calling the function. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| alg | JwsAlgorithm | -| signingInput | Uint8Array | -| decodedSignature | Uint8Array | -| publicKey | [Jwk](#Jwk) | - - - -## start() -Initializes the console error panic hook for better error messages - -**Kind**: global function - - -## encodeB64(data) ⇒ string -Encode the given bytes in url-safe base64. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| data | Uint8Array | - - - -## decodeB64(data) ⇒ Uint8Array -Decode the given url-safe base64-encoded slice into its raw bytes. - -**Kind**: global function - -| Param | Type | -| --- | --- | -| data | Uint8Array | - diff --git a/bindings/wasm/package-lock.json b/bindings/wasm/package-lock.json index 37e102a1ce..f70949c608 100644 --- a/bindings/wasm/package-lock.json +++ b/bindings/wasm/package-lock.json @@ -29,6 +29,8 @@ "ts-node": "^10.9.1", "tsconfig-paths": "^4.1.0", "txm": "^8.1.0", + "typedoc": "^0.24.6", + "typedoc-plugin-markdown": "^3.14.0", "typescript": "^4.7.2", "wasm-opt": "^1.3.0" }, @@ -950,6 +952,13 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -3407,6 +3416,13 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -3739,6 +3755,13 @@ "node": ">=10" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -3772,10 +3795,11 @@ } }, "node_modules/marked": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", - "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -5276,6 +5300,19 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -5986,6 +6023,67 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.17.1.tgz", + "integrity": "sha512-QzdU3fj0Kzw2XSdoL15ExLASt2WPqD7FbLeaqwT70+XjKyTshBnUlQA5nNREO1C2P8Uen0CDjsBLMsCQ+zd0lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "handlebars": "^4.7.7" + }, + "peerDependencies": { + "typedoc": ">=0.24.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "4.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", @@ -6203,6 +6301,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true, + "license": "MIT" + }, "node_modules/walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", @@ -7280,6 +7392,12 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9076,6 +9194,12 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true + }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -9317,6 +9441,12 @@ "yallist": "^4.0.0" } }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -9344,9 +9474,9 @@ "requires": {} }, "marked": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", - "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, "mdast-util-from-markdown": { @@ -10349,6 +10479,18 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "requires": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -10874,6 +11016,47 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, + "typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typedoc-plugin-markdown": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.17.1.tgz", + "integrity": "sha512-QzdU3fj0Kzw2XSdoL15ExLASt2WPqD7FbLeaqwT70+XjKyTshBnUlQA5nNREO1C2P8Uen0CDjsBLMsCQ+zd0lw==", + "dev": true, + "requires": { + "handlebars": "^4.7.7" + } + }, "typescript": { "version": "4.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", @@ -11028,6 +11211,18 @@ "unist-util-stringify-position": "^3.0.0" } }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json index 8740706220..085abe22a7 100644 --- a/bindings/wasm/package.json +++ b/bindings/wasm/package.json @@ -15,7 +15,7 @@ "bundle:web": "wasm-bindgen target/wasm32-unknown-unknown/release/identity_wasm.wasm --typescript --weak-refs --target web --out-dir web && node ./build/web && tsc --project ./lib/tsconfig.web.json && node ./build/replace_paths ./lib/tsconfig.web.json web", "build:nodejs": "npm run build:src && npm run bundle:nodejs && wasm-opt -O node/identity_wasm_bg.wasm -o node/identity_wasm_bg.wasm", "build:web": "npm run build:src && npm run bundle:web && wasm-opt -O web/identity_wasm_bg.wasm -o web/identity_wasm_bg.wasm", - "build:docs": "npm run fix_js_doc && node ./build/docs", + "build:docs": "typedoc && npm run fix_docs", "build:examples:web": "tsc --project ./examples/tsconfig.web.json && node ./build/replace_paths ./examples/tsconfig.web.json ./examples/dist resolve", "build": "npm run build:web && npm run build:nodejs && npm run build:docs", "example:node": "ts-node --project tsconfig.node.json -r tsconfig-paths/register ./examples/src/main.ts", @@ -32,7 +32,7 @@ "test:unit:node": "ts-mocha -p tsconfig.node.json ./tests/*.ts --parallel --exit", "cypress": "cypress open", "fmt": "dprint fmt", - "fix_js_doc": "sed -Ei 's/\\((.*)\\)\\[\\]/\\1\\[\\]/' ./node/identity_wasm.js" + "fix_docs": "sed -Ei 's/(\\.md?#([^#]*)?)#/\\1/' ./docs/wasm/**/*.md" }, "config": { "CYPRESS_VERIFY_TIMEOUT": 100000 @@ -71,6 +71,8 @@ "ts-node": "^10.9.1", "tsconfig-paths": "^4.1.0", "txm": "^8.1.0", + "typedoc": "^0.24.6", + "typedoc-plugin-markdown": "^3.14.0", "typescript": "^4.7.2", "wasm-opt": "^1.3.0" }, diff --git a/bindings/wasm/src/sd_jwt/encoder.rs b/bindings/wasm/src/sd_jwt/encoder.rs index 550742b42b..6e912e885e 100644 --- a/bindings/wasm/src/sd_jwt/encoder.rs +++ b/bindings/wasm/src/sd_jwt/encoder.rs @@ -47,7 +47,6 @@ impl WasmSdObjectEncoder { /// Path "/id" conceals `"id": "did:value"` /// Path "/claim1/abc" conceals `"abc": true` /// Path "/claim2/0" conceals `val_1` - /// ``` /// /// ## Errors /// * `InvalidPath` if pointer is invalid. diff --git a/bindings/wasm/tsconfig.typedoc.json b/bindings/wasm/tsconfig.typedoc.json new file mode 100644 index 0000000000..02841974ec --- /dev/null +++ b/bindings/wasm/tsconfig.typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.node.json", + "include": ["node/**/*"] +} diff --git a/bindings/wasm/typedoc.json b/bindings/wasm/typedoc.json new file mode 100644 index 0000000000..c6874ebe33 --- /dev/null +++ b/bindings/wasm/typedoc.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "disableSources": true, + "excludePrivate": true, + "excludeInternal": true, + "excludeNotDocumented": true, + "excludeExternals": true, + "entryPoints": ["./node/"], + "entryPointStrategy": "expand", + "tsconfig": "./tsconfig.typedoc.json", + "out": "./docs/wasm", + "plugin": ["typedoc-plugin-markdown"], + "readme": "none", + "githubPages": false, + "theme": "markdown", + "entryDocument": "api_ref.md", + "hideBreadcrumbs": true, + "hideGenerator": true, + "sort": ["source-order"], + "compilerOptions": { + "skipLibCheck": true, + } +} From 13acb23ac45cf7425fa657fc8f33c019220817cd Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Fri, 13 Sep 2024 03:39:10 +0200 Subject: [PATCH 22/22] Remove dependency on `identity_core` default features (#1408) * Remove dependency on `identity_core` default features `identity_did` and `identity_document` depend on `identity_core` but do not turn off default features. This means that these crates cannot be compiled for `wasm32-unknown-unknown` without a dependency on `js-sys`. Given the default features are not required, removing them makes these crates compatible across a wider range of compilation targets. * chore: enable default feature for identity core * chore: fmt --------- Co-authored-by: Yasir --- identity_did/Cargo.toml | 2 +- identity_document/Cargo.toml | 2 +- identity_jose/Cargo.toml | 2 +- identity_verification/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/identity_did/Cargo.toml b/identity_did/Cargo.toml index 18b32330ca..e1025a9fcd 100644 --- a/identity_did/Cargo.toml +++ b/identity_did/Cargo.toml @@ -13,7 +13,7 @@ description = "Agnostic implementation of the Decentralized Identifiers (DID) st [dependencies] 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.3.1", path = "../identity_core" } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } identity_jose = { version = "=1.3.1", path = "../identity_jose" } serde.workspace = true strum.workspace = true diff --git a/identity_document/Cargo.toml b/identity_document/Cargo.toml index 456323707d..f87fc86c33 100644 --- a/identity_document/Cargo.toml +++ b/identity_document/Cargo.toml @@ -13,7 +13,7 @@ description = "Method-agnostic implementation of the Decentralized Identifiers ( [dependencies] did_url_parser = { version = "0.2.0", features = ["std", "serde"] } -identity_core = { version = "=1.3.1", path = "../identity_core" } +identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } identity_did = { version = "=1.3.1", path = "../identity_did" } identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false } indexmap = { version = "2.0", default-features = false, features = ["std", "serde"] } diff --git a/identity_jose/Cargo.toml b/identity_jose/Cargo.toml index da8ddba3d2..1dbcb2781f 100644 --- a/identity_jose/Cargo.toml +++ b/identity_jose/Cargo.toml @@ -13,7 +13,7 @@ description = "A library for JOSE (JSON Object Signing and Encryption)" [dependencies] bls12_381_plus.workspace = true -identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false } +identity_core = { version = "=1.3.1", path = "../identity_core" } iota-crypto = { version = "0.23.2", default-features = false, features = ["std", "sha"] } json-proof-token.workspace = true serde.workspace = true diff --git a/identity_verification/Cargo.toml b/identity_verification/Cargo.toml index 2ff4fb1e9b..8990dd96e0 100644 --- a/identity_verification/Cargo.toml +++ b/identity_verification/Cargo.toml @@ -10,7 +10,7 @@ rust-version.workspace = true description = "Verification data types and functionality for identity.rs" [dependencies] -identity_core = { version = "=1.3.1", path = "./../identity_core", default-features = false } +identity_core = { version = "=1.3.1", path = "./../identity_core" } identity_did = { version = "=1.3.1", path = "./../identity_did", default-features = false } identity_jose = { version = "=1.3.1", path = "./../identity_jose", default-features = false } serde.workspace = true