From 22743100c656a1421d48285abf7b6f99526cff31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 19:47:50 -0500 Subject: [PATCH 01/24] feat: add cargo workpaces + add `pass-webauthn` --- Cargo.toml | 43 +++++++++++++++++++++++-------- README.md | 5 ++-- pass-webauthn/Cargo.toml | 50 ++++++++++++++++++++++++++++++++++++ pass-webauthn/src/lib.rs | 1 + verifier/Cargo.toml | 20 +++++++++++++++ {src => verifier/src}/lib.rs | 13 +++++----- 6 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 pass-webauthn/Cargo.toml create mode 100644 pass-webauthn/src/lib.rs create mode 100644 verifier/Cargo.toml rename {src => verifier/src}/lib.rs (96%) diff --git a/Cargo.toml b/Cargo.toml index f71e7f6..7cec7b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,39 @@ -[package] -name = "webauthn_verifier" -version = "0.1.0" +[workspace.package] +authors = ["Virto Team "] edition = "2021" -resolver = "2" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license = "GPL-3.0-only" +version = "0.1.0" +repository = "https://github.com/virto-network/webauthn" -[dependencies] +[workspace.dependencies] +# WebAuthN Verifier coset = { version = "0.3.0", default-features = false } p256 = { version = "0.13.2", default-features = false } -passkey = { version = "0.3.0", default-features = false } +passkey-authenticator = { version = "0.3.0", default-features = false } sha2 = { version = "0.10.8", default-features = false } - -[dev-dependencies] rand = "0.8.5" + +# FRAME +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.11.3", default-features = false, features = [ + "derive", +] } +frame-support = { git = "https://github.com/virto-network/polkadot-sdk", branch = "release-virto-v1.13.0", default-features = false } +frame-system = { git = "https://github.com/virto-network/polkadot-sdk", branch = "release-virto-v1.13.0", default-features = false } +pallet-balances = { git = "https://github.com/virto-network/polkadot-sdk", branch = "release-virto-v1.13.0", default-features = false } +sp-io = { git = "https://github.com/virto-network/polkadot-sdk", branch = "release-virto-v1.13.0", default-features = false } +sp-runtime = { git = "https://github.com/virto-network/polkadot-sdk", branch = "release-virto-v1.13.0", default-features = false } + +# FRAME Contrib +traits-authn = { git = "https://github.com/virto-network/frame-contrib", package = "fc-traits-authn", default-features = false } +pallet-pass = { git = "https://github.com/virto-network/frame-contrib", package = "fc-pallet-pass", default-features = false } + +# Local Crates +verifier = { path = "verifier", default-features = false } +pass-webauthn = { path = "pass-webauthn", default-features = false } + +[workspace] +members = ["pass-webauthn", "verifier"] +resolver = "2" diff --git a/README.md b/README.md index 2544d35..0a200d1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ -# webauthn_verifier -Simple WebAuthn PoC that can be compiled to WASM +# WebAuthn by Virto + +WebAuthn verifiers specifically designed for working with WASM and Substrate environments. diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml new file mode 100644 index 0000000..c48508b --- /dev/null +++ b/pass-webauthn/Cargo.toml @@ -0,0 +1,50 @@ +[package] +authors.workspace = true +edition.workspace = true +license.workspace = true +name = "pass-webauthn" +repository.workspace = true +version = "0.1.0" + +[dependencies] +codec.workspace = true +frame-support.workspace = true +frame-system.workspace = true +scale-info.workspace = true +traits-authn.workspace = true +verifier.workspace = true + +[dev-dependencies] +pallet-balances.workspace = true +pallet-pass.workspace = true +sp-io.workspace = true +sp-runtime.workspace = true + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-pass/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-pass/std", + "scale-info/std", + "sp-io/std", + "sp-runtime/std", + "traits-authn/std", + "verifier/std", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-pass/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs new file mode 100644 index 0000000..8731421 --- /dev/null +++ b/pass-webauthn/src/lib.rs @@ -0,0 +1 @@ +#![cfg_attr(not(feature = "std"), no_std)] diff --git a/verifier/Cargo.toml b/verifier/Cargo.toml new file mode 100644 index 0000000..4c38492 --- /dev/null +++ b/verifier/Cargo.toml @@ -0,0 +1,20 @@ +[package] +authors.workspace = true +edition.workspace = true +license.workspace = true +name = "verifier" +repository.workspace = true +version = "0.1.0" + +[dependencies] +coset.workspace = true +p256.workspace = true +passkey-authenticator.workspace = true +sha2.workspace = true + +[dev-dependencies] +rand.workspace = true + +[features] +default = ["std"] +std = ["coset/std", "p256/std", "sha2/std", "rand/std"] diff --git a/src/lib.rs b/verifier/src/lib.rs similarity index 96% rename from src/lib.rs rename to verifier/src/lib.rs index 07e6b86..dc95995 100644 --- a/src/lib.rs +++ b/verifier/src/lib.rs @@ -1,4 +1,5 @@ -#![cfg_attr(not(test), no_std)] +#![cfg_attr(not(any(feature = "std", test)), no_std)] + //! Verifies a WebAuthn response signature. //! //! This function validates the signature of a WebAuthn authentication response by: @@ -53,7 +54,7 @@ use p256::{ pkcs8::DecodePublicKey, NistP256, }; -use passkey::authenticator; +use passkey_authenticator::public_key_der_from_cose_key; use sha2::{Digest, Sha256}; fn concatenate_data( @@ -73,7 +74,7 @@ fn concatenate_data( Ok(message) } -pub fn verify_webauthn_response( +pub fn webauthn_verify( authenticator_data: &[u8], client_data_json: &[u8], signature_der: &[u8], @@ -100,7 +101,7 @@ pub fn verify_webauthn_response( } }; - let public_key_der = match authenticator::public_key_der_from_cose_key(&public_key_cose) { + let public_key_der = match public_key_der_from_cose_key(&public_key_cose) { Ok(der) => der, Err(_e) => { // eprintln!("Failed to convert COSE key to DER format: {:?}", e); @@ -192,7 +193,7 @@ mod tests { let signature_der = signature.to_der(); // Step 7: Verify the signature - let is_valid = verify_webauthn_response( + let is_valid = webauthn_verify( authenticator_data, client_data_json, signature_der.as_bytes(), @@ -247,7 +248,7 @@ mod tests { tampered_signature_der[0] ^= 0xFF; // Flip some bits // Step 8: Verify the signature (should fail) - let is_valid = verify_webauthn_response( + let is_valid = webauthn_verify( authenticator_data, client_data_json, &tampered_signature_der, From c6b18155f6eb56fffc863969bdbbe3a6bcdb9456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 20:24:02 -0500 Subject: [PATCH 02/24] change(verifier): use result for `verify`, input `der` directly --- verifier/Cargo.toml | 4 +- verifier/src/lib.rs | 132 ++++++++++++++------------------------------ 2 files changed, 44 insertions(+), 92 deletions(-) diff --git a/verifier/Cargo.toml b/verifier/Cargo.toml index 4c38492..9e22efc 100644 --- a/verifier/Cargo.toml +++ b/verifier/Cargo.toml @@ -7,12 +7,12 @@ repository.workspace = true version = "0.1.0" [dependencies] -coset.workspace = true p256.workspace = true -passkey-authenticator.workspace = true sha2.workspace = true [dev-dependencies] +coset.workspace = true +passkey-authenticator.workspace = true rand.workspace = true [features] diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index dc95995..a839007 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -47,96 +47,47 @@ //! * https://www.w3.org/TR/webauthn/#fig-signature //! * https://www.w3.org/TR/webauthn/images/fido-signature-formats-figure2.svg -use coset::{CborSerializable, CoseKey}; +extern crate alloc; use p256::{ ecdsa::{signature::Verifier, Signature, VerifyingKey}, elliptic_curve::PublicKey, pkcs8::DecodePublicKey, NistP256, }; -use passkey_authenticator::public_key_der_from_cose_key; use sha2::{Digest, Sha256}; -fn concatenate_data( - authenticator_data: &[u8], - client_data_hash: &[u8], -) -> Result<[u8; 512], &'static str> { - let total_len = authenticator_data.len() + client_data_hash.len(); - - if total_len > 512 { - return Err("Buffer overflow"); - } - - let mut message = [0u8; 512]; - message[..authenticator_data.len()].copy_from_slice(authenticator_data); - message[authenticator_data.len()..total_len].copy_from_slice(client_data_hash); - - Ok(message) +#[derive(Debug)] +pub enum VerifyError { + ExtractPublicKey, + ParseSignature, + VerifySignature, } pub fn webauthn_verify( authenticator_data: &[u8], client_data_json: &[u8], signature_der: &[u8], - credential_public_key_cbor: &[u8], -) -> bool { + credential_public_key_der: &[u8], +) -> Result<(), VerifyError> { // Step 1: Compute the SHA-256 hash of the client data JSON let client_data_hash: [u8; 32] = Sha256::digest(client_data_json).into(); // Step 2: Concatenate authenticator data and client data hash - let message = match concatenate_data(authenticator_data, &client_data_hash) { - Ok(msg) => msg, - Err(_e) => { - // eprintln!("Failed to concatenate data: {:?}", e); - return false; - } - }; - - // Step 3: Parse the COSE public key, convert it to DER format, and parse it - let public_key_cose = match CoseKey::from_slice(credential_public_key_cbor) { - Ok(key) => key, - Err(_e) => { - // eprintln!("Failed to parse COSE public key: {:?}", e); - return false; - } - }; + let message = vec![authenticator_data, &client_data_hash].concat(); - let public_key_der = match public_key_der_from_cose_key(&public_key_cose) { - Ok(der) => der, - Err(_e) => { - // eprintln!("Failed to convert COSE key to DER format: {:?}", e); - return false; - } - }; - - let public_key = match PublicKey::::from_public_key_der(&public_key_der) { - Ok(key) => key, - Err(_e) => { - // eprintln!("Failed to parse public key DER: {:?}", e); - return false; - } - }; + let public_key = PublicKey::::from_public_key_der(credential_public_key_der) + .map_err(|_| VerifyError::ExtractPublicKey)?; let verifying_key = VerifyingKey::from(public_key); // Step 4: Parse the DER signature - let signature = match Signature::from_der(signature_der) { - Ok(sig) => sig, - Err(_e) => { - // eprintln!("Failed to parse signature DER: {:?}", e); - return false; - } - }; + let signature = Signature::from_der(signature_der).map_err(|_| VerifyError::ParseSignature)?; // Step 5: Verify the signature - if verifying_key.verify(&message, &signature).is_err() { - // eprintln!("Signature verification failed"); - return false; - } - - // println!("Signature verification succeeded"); - - true + verifying_key + .verify(&message, &signature) + .map(|_| ()) + .map_err(|_| VerifyError::VerifySignature) } #[cfg(test)] @@ -144,9 +95,10 @@ mod tests { use super::*; use coset::{ iana::{Algorithm, EllipticCurve}, - CborSerializable, CoseKeyBuilder, + CoseKeyBuilder, }; use p256::ecdsa::{signature::Signer, Signature, SigningKey}; + use passkey_authenticator::public_key_der_from_cose_key; use rand::rngs::OsRng; use sha2::{Digest, Sha256}; @@ -174,10 +126,12 @@ mod tests { .algorithm(Algorithm::ES256) .build(); - // Step 4: Serialize the COSE key pair - let public_key_cbor = public_key_cose - .to_vec() - .expect("Failed to serialize COSE key"); + // Step 4: Convert to DER from COSE + // TODO: Is this conversion from COSE really necessary? Or is it possible to build the DER key from + // scratch using another library? + let public_key_der = public_key_der_from_cose_key(&public_key_cose) + .map_err(|_| VerifyError::ExtractPublicKey) + .expect("Conversion from COSE to DER failed"); // Step 5: Compute client_data_hash and message let client_data_hash = Sha256::digest(client_data_json); @@ -193,17 +147,13 @@ mod tests { let signature_der = signature.to_der(); // Step 7: Verify the signature - let is_valid = webauthn_verify( + webauthn_verify( authenticator_data, client_data_json, signature_der.as_bytes(), - public_key_cbor.as_slice(), - ); - - assert!( - is_valid, - "The signature should be valid with the generated sample data." - ); + public_key_der.as_slice(), + ) + .expect("Verifying signature failed"); } #[test] @@ -228,10 +178,12 @@ mod tests { .algorithm(Algorithm::ES256) .build(); - // Step 4: Serialize the COSE key pair - let public_key_cbor = public_key_cose - .to_vec() - .expect("Failed to serialize COSE key"); + // Step 4: Convert to DER from COSE + // TODO: Is this conversion from COSE really necessary? Or is it possible to build the DER key from + // scratch using another library? + let public_key_der = public_key_der_from_cose_key(&public_key_cose) + .map_err(|_| VerifyError::ExtractPublicKey) + .expect("Conversion from COSE to DER failed"); // Step 5: Compute client_data_hash and message let client_data_hash = Sha256::digest(client_data_json); @@ -248,16 +200,16 @@ mod tests { tampered_signature_der[0] ^= 0xFF; // Flip some bits // Step 8: Verify the signature (should fail) - let is_valid = webauthn_verify( + if let Ok(()) = webauthn_verify( authenticator_data, client_data_json, &tampered_signature_der, - public_key_cbor.as_slice(), - ); - - assert!( - !is_valid, - "The signature verification should fail with an invalid signature." - ); + public_key_der.as_slice(), + ) { + assert!( + false, + "The signature verification should fail with an invalid signature." + ); + } } } From abcf97b1bc9f59fd16711670ceec92c0cdc0a012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 20:53:19 -0500 Subject: [PATCH 03/24] change(verifier): adjust dependencies --- verifier/Cargo.toml | 1 + verifier/src/lib.rs | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/verifier/Cargo.toml b/verifier/Cargo.toml index 9e22efc..56f68dd 100644 --- a/verifier/Cargo.toml +++ b/verifier/Cargo.toml @@ -8,6 +8,7 @@ version = "0.1.0" [dependencies] p256.workspace = true +p256.features = ["ecdsa", "pkcs8"] sha2.workspace = true [dev-dependencies] diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index a839007..fe661ce 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -44,12 +44,12 @@ //! //! * [Web Authentication: An API for accessing Public Key Credentials Level 2 - ยง7.2. Verifying an Authentication Assertion](https://www.w3.org/TR/webauthn/#sctn-verifying-assertion) //! * "20. Using credentialPublicKey, verify that sig is a valid signature over the binary concatenation of authData and hash." -//! * https://www.w3.org/TR/webauthn/#fig-signature -//! * https://www.w3.org/TR/webauthn/images/fido-signature-formats-figure2.svg +//! * +//! * extern crate alloc; use p256::{ - ecdsa::{signature::Verifier, Signature, VerifyingKey}, + ecdsa::{signature::Verifier, DerSignature, VerifyingKey}, elliptic_curve::PublicKey, pkcs8::DecodePublicKey, NistP256, @@ -75,13 +75,16 @@ pub fn webauthn_verify( // Step 2: Concatenate authenticator data and client data hash let message = vec![authenticator_data, &client_data_hash].concat(); - let public_key = PublicKey::::from_public_key_der(credential_public_key_der) - .map_err(|_| VerifyError::ExtractPublicKey)?; + // Step 3: Extract public key from DER format + let public_key: PublicKey = + DecodePublicKey::from_public_key_der(credential_public_key_der) + .map_err(|_| VerifyError::ExtractPublicKey)?; let verifying_key = VerifyingKey::from(public_key); // Step 4: Parse the DER signature - let signature = Signature::from_der(signature_der).map_err(|_| VerifyError::ParseSignature)?; + let signature = + DerSignature::try_from(signature_der).map_err(|_| VerifyError::ParseSignature)?; // Step 5: Verify the signature verifying_key From 8bd1d292b60f9d26ddac283b2d7d2da88a410fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 20:58:18 -0500 Subject: [PATCH 04/24] feat: add some github actions --- .github/workflows/ci.yml | 84 +++++++++++++++++++++++++++++++++++ .github/workflows/lint-pr.yml | 20 +++++++++ 2 files changed, 104 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/lint-pr.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3637c56 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +name: Lint, check, clippy and test + +on: + push: + branches: [ main ] + pull_request: + types: [ opened, synchronize, reopened, ready_for_review ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check formatting + run: cargo fmt --all -- --check + + check: + needs: lint + runs-on: ubuntu-latest + steps: + - name: Setup Ubuntu dependencies + shell: bash + run: sudo apt update && sudo apt install -y protobuf-compiler + + - uses: actions/checkout@v4 + + - name: Rust Cache + uses: Swatinem/rust-cache@v2.7.3 + with: + cache-on-failure: true + cache-all-crates: true + key: check + + - name: Check Build + run: | + cargo check --release --locked --all-features --workspace + + clippy: + needs: lint + runs-on: ubuntu-latest + permissions: + checks: write + env: + SKIP_WASM_BUILD: 1 + steps: + - name: Setup Ubuntu dependencies + shell: bash + run: sudo apt update && sudo apt install -y protobuf-compiler + + - uses: actions/checkout@v4 + + - name: Rust Cache + uses: Swatinem/rust-cache@v2.7.3 + with: + cache-on-failure: true + cache-all-crates: true + key: check + + - name: Annotate with Clippy warnings + uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --release --locked --all-features --workspace + + test: + needs: lint + runs-on: ubuntu-latest + steps: + - name: Setup Ubuntu dependencies + shell: bash + run: sudo apt update && sudo apt install -y protobuf-compiler + + - uses: actions/checkout@v4 + + - name: Rust Cache + uses: Swatinem/rust-cache@v2.7.3 + with: + cache-on-failure: true + cache-all-crates: true + key: test + + - name: Run tests + run: cargo test --release --locked --all-features --workspace diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml new file mode 100644 index 0000000..047030c --- /dev/null +++ b/.github/workflows/lint-pr.yml @@ -0,0 +1,20 @@ +name: "Lint PR" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +permissions: + pull-requests: read + +jobs: + lint: + name: Validate PR title for conventional commit compliance + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From e444d6aa0d0aa7fab979f833f942fd926c6d460f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 21:03:32 -0500 Subject: [PATCH 05/24] fix: add cargo lockfile (needed by ci, and sanity) --- .gitignore | 4 - Cargo.lock | 4221 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 4221 insertions(+), 4 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 0dcb6e4..1530ffa 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,6 @@ debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..5b3b465 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4221 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "aquamarine" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-377-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c7021f180a0cbea0380eba97c2af3c57074cdaffe0eef7e840e1c9f2841e55" +dependencies = [ + "ark-bls12-377", + "ark-ec", + "ark-models-ext", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-bls12-381-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1dc4b3d08f19e8ec06e949712f95b8361e43f1391d94f65e4234df03480631c" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-models-ext", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-bw6-761" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e0605daf0cc5aa2034b78d008aaf159f56901d92a52ee4f6ecdfdac4f426700" +dependencies = [ + "ark-bls12-377", + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bw6-761-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccee5fba47266f460067588ee1bf070a9c760bf2050c1c509982c5719aadb4f2" +dependencies = [ + "ark-bw6-761", + "ark-ec", + "ark-ff", + "ark-models-ext", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ed-on-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10d901b9ac4b38f9c32beacedfadcdd64e46f8d7f8e88c1ae1060022cf6f6c6" +dependencies = [ + "ark-bls12-377", + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ed-on-bls12-377-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524a4fb7540df2e1a8c2e67a83ba1d1e6c3947f4f9342cc2359fc2e789ad731d" +dependencies = [ + "ark-ec", + "ark-ed-on-bls12-377", + "ark-ff", + "ark-models-ext", + "ark-std", +] + +[[package]] +name = "ark-ed-on-bls12-381-bandersnatch" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ed-on-bls12-381-bandersnatch-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15185f1acb49a07ff8cbe5f11a1adc5a93b19e211e325d826ae98e98e124346" +dependencies = [ + "ark-ec", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff", + "ark-models-ext", + "ark-std", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-models-ext" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9eab5d4b5ff2f228b763d38442adc9b084b0a465409b059fac5c2308835ec2" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-scale" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ark-secret-scalar" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=e9782f9#e9782f938629c90f3adb3fff2358bc8d1386af3e" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "ark-transcript 0.0.2 (git+https://github.com/w3f/ring-vrf?rev=e9782f9)", + "digest 0.10.7", + "getrandom_or_panic", + "zeroize", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", + "rayon", +] + +[[package]] +name = "ark-transcript" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563084372d89271122bd743ef0a608179726f5fad0566008ba55bd0f756489b8" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "digest 0.10.7", + "rand_core", + "sha3", +] + +[[package]] +name = "ark-transcript" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=e9782f9#e9782f938629c90f3adb3fff2358bc8d1386af3e" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "digest 0.10.7", + "rand_core", + "sha3", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bandersnatch_vrfs" +version = "0.0.4" +source = "git+https://github.com/w3f/ring-vrf?rev=e9782f9#e9782f938629c90f3adb3fff2358bc8d1386af3e" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff", + "ark-serialize", + "ark-std", + "dleq_vrf", + "fflonk", + "merlin", + "rand_chacha", + "rand_core", + "ring", + "sha2 0.10.8", + "sp-ark-bls12-381", + "sp-ark-ed-on-bls12-381-bandersnatch", + "zeroize", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-collections" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db436177db0d505b1507f03aca56a41442ae6efdf8b6eaa855d73e52c5b078dc" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "bytemuck" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "common" +version = "0.1.0" +source = "git+https://github.com/w3f/ring-proof#652286c32f96beb9ce7f5793f5e2c2c923f63b73" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "fflonk", + "getrandom_or_panic", + "rand_core", +] + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "coset" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8cc80f631f8307b887faca24dcc3abc427cd0367f6eb6188f6e8f5b7ad8fb" +dependencies = [ + "ciborium", + "ciborium-io", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dleq_vrf" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=e9782f9#e9782f938629c90f3adb3fff2358bc8d1386af3e" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-scale", + "ark-secret-scalar", + "ark-serialize", + "ark-std", + "ark-transcript 0.0.2 (git+https://github.com/w3f/ring-vrf?rev=e9782f9)", + "arrayvec", + "zeroize", +] + +[[package]] +name = "docify" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.79", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "base64ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "serde_json", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "expander" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +dependencies = [ + "blake2", + "file-guard", + "fs-err", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "fc-pallet-pass" +version = "1.0.0" +source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +dependencies = [ + "fc-traits-authn", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "fc-traits-authn" +version = "0.1.0" +source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +dependencies = [ + "fc-traits-authn-proc", + "frame-support", + "impl-trait-for-tuples", + "parity-scale-codec", + "paste", + "scale-info", +] + +[[package]] +name = "fc-traits-authn-proc" +version = "0.1.0" +source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +dependencies = [ + "quote", + "syn 2.0.79", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fflonk" +version = "0.1.0" +source = "git+https://github.com/w3f/fflonk#1e854f35e9a65d08b11a86291405cdc95baa0a35" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "merlin", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "file-guard" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "frame-benchmarking" +version = "28.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "frame-support", + "frame-support-procedural", + "frame-system", + "linregress", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface 24.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-storage 19.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "static_assertions", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-support" +version = "28.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "aquamarine", + "array-bytes", + "bitflags 1.3.2", + "docify", + "environmental", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log", + "macro_magic", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "serde_json", + "smallvec", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-crypto-hashing-proc-macro", + "sp-debug-derive 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-metadata-ir", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-tracing 16.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-weights", + "static_assertions", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "23.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "expander", + "frame-support-procedural-tools", + "itertools 0.11.0", + "macro_magic", + "proc-macro-warning", + "proc-macro2", + "quote", + "sp-crypto-hashing", + "syn 2.0.79", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "10.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "11.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "frame-system" +version = "28.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "cfg-if", + "docify", + "frame-support", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-version", + "sp-weights", +] + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67aa010c1e3da95bf151bd8b4c059b2ed7e75387cdb969b4f8f2723a43f9941" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-num-traits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint 0.10.0", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", + "serde", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linregress" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de04dcecc58d366391f9920245b85ffa684558a5ef6e7736e754347c3aea9c2" +dependencies = [ + "nalgebra", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "macro_magic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "macro_magic_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "macro_magic_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" +dependencies = [ + "macro_magic_core", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "nalgebra" +version = "0.32.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.8", +] + +[[package]] +name = "pallet-balances" +version = "28.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pass-webauthn" +version = "0.1.0" +dependencies = [ + "fc-pallet-pass", + "fc-traits-authn", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "verifier", +] + +[[package]] +name = "passkey-authenticator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715c1f0ea11f032db84f08978f5d25220098ac6965dd84d5d53501b4f0156167" +dependencies = [ + "async-trait", + "coset", + "log", + "p256", + "passkey-types", + "rand", +] + +[[package]] +name = "passkey-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5d3d17d8ad54ba7c7574595f026244ab06ee44f0524379c1575a95aab4c030" +dependencies = [ + "bitflags 2.6.0", + "ciborium", + "coset", + "data-encoding", + "getrandom", + "hmac 0.12.1", + "indexmap", + "rand", + "serde", + "serde_json", + "sha2 0.10.8", + "strum", + "typeshare", + "zeroize", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.79", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn 2.0.79", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec 0.6.0", + "impl-serde", + "scale-info", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "impl-codec 0.7.0", + "impl-num-traits", + "uint 0.10.0", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-warning" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "proc-macro2" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "ring" +version = "0.1.0" +source = "git+https://github.com/w3f/ring-proof#652286c32f96beb9ce7f5793f5e2c2c923f63b73" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "ark-transcript 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "blake2", + "common", + "fflonk", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "safe_arch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "simple-mermaid" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "620a1d43d70e142b1d46a929af51d44f383db9c7a2ec122de2cd992ccfcf3c18" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sp-api" +version = "26.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro", + "sp-core", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-metadata-ir", + "sp-runtime", + "sp-runtime-interface 24.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-state-machine", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-trie", + "sp-version", + "thiserror", +] + +[[package]] +name = "sp-api-proc-macro" +version = "15.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "Inflector", + "blake2", + "expander", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-application-crypto" +version = "30.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "sp-arithmetic" +version = "23.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "static_assertions", +] + +[[package]] +name = "sp-ark-bls12-381" +version = "0.4.2" +source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" +dependencies = [ + "ark-bls12-381-ext", + "sp-crypto-ec-utils", +] + +[[package]] +name = "sp-ark-ed-on-bls12-381-bandersnatch" +version = "0.4.2" +source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" +dependencies = [ + "ark-ed-on-bls12-381-bandersnatch-ext", + "sp-crypto-ec-utils", +] + +[[package]] +name = "sp-core" +version = "28.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "array-bytes", + "bandersnatch_vrfs", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types 0.12.2", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-storage 19.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-ec-utils" +version = "0.10.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "ark-bls12-377", + "ark-bls12-377-ext", + "ark-bls12-381", + "ark-bls12-381-ext", + "ark-bw6-761", + "ark-bw6-761-ext", + "ark-ec", + "ark-ed-on-bls12-377", + "ark-ed-on-bls12-377-ext", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ed-on-bls12-381-bandersnatch-ext", + "ark-scale", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk)", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-crypto-hashing-proc-macro" +version = "0.1.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "quote", + "sp-crypto-hashing", + "syn 2.0.79", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-externalities" +version = "0.25.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage 19.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "sp-externalities" +version = "0.25.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk)", +] + +[[package]] +name = "sp-genesis-builder" +version = "0.8.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde_json", + "sp-api", + "sp-runtime", +] + +[[package]] +name = "sp-inherents" +version = "26.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sp-io" +version = "30.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-keystore", + "sp-runtime-interface 24.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-state-machine", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-tracing 16.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.34.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.6.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "31.0.1" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "num-traits", + "parity-scale-codec", + "paste", + "rand", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "24.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types 0.12.2", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-storage 19.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-tracing 16.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface" +version = "24.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types 0.13.1", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "17.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-staking" +version = "26.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-state-machine" +version = "0.35.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" + +[[package]] +name = "sp-storage" +version = "19.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "sp-storage" +version = "19.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", +] + +[[package]] +name = "sp-tracing" +version = "16.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-tracing" +version = "16.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "29.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities 0.25.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "29.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-crypto-hashing-proc-macro", + "sp-runtime", + "sp-std 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "13.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sp-wasm-interface" +version = "20.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-wasm-interface" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "27.0.0" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive 14.0.0 (git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0)", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", +] + +[[package]] +name = "substrate-bip39" +version = "0.4.7" +source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto-v1.13.0#b788ee63a311984787af4d37d37c14dcff1c18c3" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "typeshare" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f17399b76c2e743d58eac0635d7686e9c00f48cd4776f00695d9882a7d3187" +dependencies = [ + "chrono", + "serde", + "serde_json", + "typeshare-annotation", +] + +[[package]] +name = "typeshare-annotation" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a615d6c2764852a2e88a4f16e9ce1ea49bb776b5872956309e170d63a042a34f" +dependencies = [ + "quote", + "syn 2.0.79", +] + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "verifier" +version = "0.1.0" +dependencies = [ + "coset", + "p256", + "passkey-authenticator", + "rand", + "sha2 0.10.8", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "w3f-bls" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c5da5fa2c6afa2c9158eaa7cd9aee249765eb32b5fb0c63ad8b9e79336a47ec" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "wide" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] From b64eaa187e584c21940185ff1bec7c09e1382fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 21:41:00 -0500 Subject: [PATCH 06/24] change(pass-webauthn): base structures --- pass-webauthn/src/impls.rs | 39 ++++++++++++++++++++++++++++++++++++++ pass-webauthn/src/lib.rs | 36 +++++++++++++++++++++++++++++++++++ pass-webauthn/src/tests.rs | 0 3 files changed, 75 insertions(+) create mode 100644 pass-webauthn/src/impls.rs create mode 100644 pass-webauthn/src/tests.rs diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs new file mode 100644 index 0000000..a60baba --- /dev/null +++ b/pass-webauthn/src/impls.rs @@ -0,0 +1,39 @@ +use frame_support::Parameter; +use traits_authn::{Challenger, DeviceChallengeResponse, UserChallengeResponse}; +use verifier::webauthn_verify; + +use crate::{Assertions, Attestation}; + +impl AsRef<[u8]> for Assertions { + fn as_ref(&self) -> &[u8] { + // See https://www.w3.org/TR/webauthn/#clientdatajson-serialization for more details + todo!("Concatenate assertions into the desired `authenticator_data`") + } +} + +impl DeviceChallengeResponse for Attestation +where + Cx: Parameter + Copy + 'static, +{ + fn is_valid(&self) -> bool { + webauthn_verify( + self.authenticator_data.as_ref(), + &self.client_data, + &self.signature, + &self.public_key, + ) + .is_ok() + } + + fn used_challenge(&self) -> (Cx, traits_authn::Challenge) { + (self.context, self.authenticator_data.challenge) + } + + fn authority(&self) -> traits_authn::AuthorityId { + self.rp_id + } + + fn device_id(&self) -> &traits_authn::DeviceId { + todo!() + } +} diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index 8731421..2eef0ca 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -1 +1,37 @@ #![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use frame_support::{DebugNoBound, Parameter}; +use scale_info::TypeInfo; +use traits_authn::{AuthorityId, Challenge, Challenger}; + +#[cfg(test)] +mod tests; + +mod impls; + +type CxOf = ::Context; + +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] +pub struct Assertions { + challenge: Challenge, +} + +#[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] +pub struct Attestation { + pub(crate) rp_id: AuthorityId, + pub(crate) context: Cx, + pub(crate) authenticator_data: Assertions, + pub(crate) client_data: Vec, + pub(crate) signature: Vec, + pub(crate) public_key: Vec, +} + +#[derive(Encode, Decode)] +pub struct Credential { + pub(crate) rp_id: AuthorityId, + pub(crate) context: Cx, + pub(crate) authenticator_data: Assertions, + pub(crate) client_data: Vec, + pub(crate) signature: Vec, +} diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs new file mode 100644 index 0000000..e69de29 From 0e85e370ff85959cbd484ccc7884de56ec3b0ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 21:55:16 -0500 Subject: [PATCH 07/24] change(pass-webauthn): base implementations --- pass-webauthn/src/impls.rs | 52 ++++++++++++++++++++++++++++++-------- pass-webauthn/src/lib.rs | 24 ++++++++---------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index a60baba..ec54865 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -1,21 +1,53 @@ use frame_support::Parameter; -use traits_authn::{Challenger, DeviceChallengeResponse, UserChallengeResponse}; +use traits_authn::{DeviceChallengeResponse, UserChallengeResponse}; use verifier::webauthn_verify; -use crate::{Assertions, Attestation}; +use crate::{Attestation, Credential}; -impl AsRef<[u8]> for Assertions { - fn as_ref(&self) -> &[u8] { - // See https://www.w3.org/TR/webauthn/#clientdatajson-serialization for more details - todo!("Concatenate assertions into the desired `authenticator_data`") +impl DeviceChallengeResponse for Attestation +where + Cx: Parameter + Copy + 'static, +{ + fn is_valid(&self) -> bool { + // TODO: Add sanity tests to verify that the information that's in the structure + // (`challenge_info`, `rp_id`, `device_id`) corresponds to the information in + // `authenticator_data` and `client_data`, and all that is congruent. + // + // Note: This might require using a json parsing library? + + webauthn_verify( + self.authenticator_data.as_ref(), + &self.client_data, + &self.signature, + &self.public_key, + ) + .is_ok() + } + + fn used_challenge(&self) -> (Cx, traits_authn::Challenge) { + self.challenge_info + } + + fn authority(&self) -> traits_authn::AuthorityId { + self.rp_id + } + + fn device_id(&self) -> &traits_authn::DeviceId { + &self.device_id } } -impl DeviceChallengeResponse for Attestation +impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { fn is_valid(&self) -> bool { + // TODO: Add sanity tests to verify that the information that's in the structure + // (`challenge_info`, `rp_id`, `device_id`) corresponds to the information in + // `authenticator_data` and `client_data`, and all that is congruent. + // + // Note: This might require using a json parsing library? + webauthn_verify( self.authenticator_data.as_ref(), &self.client_data, @@ -26,14 +58,14 @@ where } fn used_challenge(&self) -> (Cx, traits_authn::Challenge) { - (self.context, self.authenticator_data.challenge) + self.challenge_info } fn authority(&self) -> traits_authn::AuthorityId { self.rp_id } - fn device_id(&self) -> &traits_authn::DeviceId { - todo!() + fn user_id(&self) -> traits_authn::HashedUserId { + self.user_id } } diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index 2eef0ca..cc5cb45 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -3,35 +3,31 @@ use codec::{Decode, Encode}; use frame_support::{DebugNoBound, Parameter}; use scale_info::TypeInfo; -use traits_authn::{AuthorityId, Challenge, Challenger}; +use traits_authn::{AuthorityId, Challenge, Challenger, DeviceId, HashedUserId}; #[cfg(test)] mod tests; mod impls; -type CxOf = ::Context; - -#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] -pub struct Assertions { - challenge: Challenge, -} - #[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Attestation { pub(crate) rp_id: AuthorityId, - pub(crate) context: Cx, - pub(crate) authenticator_data: Assertions, + pub(crate) device_id: DeviceId, + pub(crate) challenge_info: (Cx, Challenge), + pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, - pub(crate) signature: Vec, pub(crate) public_key: Vec, + pub(crate) signature: Vec, } -#[derive(Encode, Decode)] +#[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Credential { pub(crate) rp_id: AuthorityId, - pub(crate) context: Cx, - pub(crate) authenticator_data: Assertions, + pub(crate) user_id: HashedUserId, + pub(crate) challenge_info: (Cx, Challenge), + pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, + pub(crate) public_key: Vec, pub(crate) signature: Vec, } From d46053211f9d743c5204bd163a1f77e066051101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 22:15:57 -0500 Subject: [PATCH 08/24] change(pass-webauthn): produce structures for `Authenticator` and `Device`. --- pass-webauthn/src/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index cc5cb45..bf68508 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -1,15 +1,25 @@ #![cfg_attr(not(feature = "std"), no_std)] +use core::marker::PhantomData; + use codec::{Decode, Encode}; use frame_support::{DebugNoBound, Parameter}; use scale_info::TypeInfo; -use traits_authn::{AuthorityId, Challenge, Challenger, DeviceId, HashedUserId}; +use traits_authn::{ + util::{Auth, Dev}, + AuthorityId, Challenge, Challenger, DeviceId, HashedUserId, +}; + +type CxOf = ::Context; #[cfg(test)] mod tests; mod impls; +pub type Authenticator = Auth, Attestation>>; +pub type Device = Dev, A, Ch, Credential>>; + #[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Attestation { pub(crate) rp_id: AuthorityId, @@ -21,6 +31,16 @@ pub struct Attestation { pub(crate) signature: Vec, } +impl From>> for (Vec, PhantomData<(A, Ch, Cred)>) +where + Ch: Challenger, + CxOf: Parameter, +{ + fn from(value: Attestation>) -> Self { + (value.public_key, PhantomData) + } +} + #[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Credential { pub(crate) rp_id: AuthorityId, From dd9dad50951598e33aea75a77af2688eff3b925c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 22:51:42 -0500 Subject: [PATCH 09/24] change(pass-webauthn): make things slightly simpler --- pass-webauthn/Cargo.toml | 3 +- pass-webauthn/src/impls.rs | 93 ++++++++++++++++++++++++++++++-------- pass-webauthn/src/lib.rs | 10 ++-- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index c48508b..c9e9c60 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -21,7 +21,8 @@ sp-io.workspace = true sp-runtime.workspace = true [features] -default = ["std"] +default = ["std", "runtime"] +runtime = [] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index ec54865..ed3b591 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -1,20 +1,47 @@ +use core::marker::PhantomData; + use frame_support::Parameter; -use traits_authn::{DeviceChallengeResponse, UserChallengeResponse}; +use traits_authn::{ + AuthorityId, Challenge, DeviceChallengeResponse, DeviceId, HashedUserId, UserChallengeResponse, +}; use verifier::webauthn_verify; use crate::{Attestation, Credential}; +impl Attestation +where + Cx: Parameter, +{ + pub fn new( + authenticator_data: Vec, + client_data: Vec, + signature: Vec, + public_key: Vec, + ) -> Self { + Self { + __phantom: PhantomData, + authenticator_data, + client_data, + signature, + public_key, + } + } + + fn context(&self) -> Cx { + todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); + } + + fn challenge(&self) -> Challenge { + todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); + } +} + +#[cfg(any(feature = "runtime", test))] impl DeviceChallengeResponse for Attestation where Cx: Parameter + Copy + 'static, { fn is_valid(&self) -> bool { - // TODO: Add sanity tests to verify that the information that's in the structure - // (`challenge_info`, `rp_id`, `device_id`) corresponds to the information in - // `authenticator_data` and `client_data`, and all that is congruent. - // - // Note: This might require using a json parsing library? - webauthn_verify( self.authenticator_data.as_ref(), &self.client_data, @@ -24,16 +51,44 @@ where .is_ok() } - fn used_challenge(&self) -> (Cx, traits_authn::Challenge) { - self.challenge_info + fn used_challenge(&self) -> (Cx, Challenge) { + (self.context(), self.challenge()) + } + + fn authority(&self) -> AuthorityId { + todo!("Extract `rp_id`, format into `AuthorityId` format (that is, [u8; 32])"); + } + + fn device_id(&self) -> &DeviceId { + todo!("Extract `device_id`, format into `DeviceId` format (that is, [u8; 32])"); + } +} + +impl Credential +where + Cx: Parameter, +{ + pub fn new( + authenticator_data: Vec, + client_data: Vec, + signature: Vec, + public_key: Vec, + ) -> Self { + Self { + __phantom: PhantomData, + authenticator_data, + client_data, + signature, + public_key, + } } - fn authority(&self) -> traits_authn::AuthorityId { - self.rp_id + fn context(&self) -> Cx { + todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); } - fn device_id(&self) -> &traits_authn::DeviceId { - &self.device_id + fn challenge(&self) -> Challenge { + todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); } } @@ -57,15 +112,15 @@ where .is_ok() } - fn used_challenge(&self) -> (Cx, traits_authn::Challenge) { - self.challenge_info + fn used_challenge(&self) -> (Cx, Challenge) { + (self.context(), self.challenge()) } - fn authority(&self) -> traits_authn::AuthorityId { - self.rp_id + fn authority(&self) -> AuthorityId { + todo!("Extract `rp_id`, format into `AuthorityId` format (that is, [u8; 32])"); } - fn user_id(&self) -> traits_authn::HashedUserId { - self.user_id + fn user_id(&self) -> HashedUserId { + todo!("Extract `user_id`, format into `HashedUserId` format (that is, [u8; 32])"); } } diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index bf68508..67b307c 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -7,7 +7,7 @@ use frame_support::{DebugNoBound, Parameter}; use scale_info::TypeInfo; use traits_authn::{ util::{Auth, Dev}, - AuthorityId, Challenge, Challenger, DeviceId, HashedUserId, + AuthorityId, Challenge, Challenger, HashedUserId, }; type CxOf = ::Context; @@ -22,9 +22,7 @@ pub type Device = Dev, A, Ch, Credential>>; #[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Attestation { - pub(crate) rp_id: AuthorityId, - pub(crate) device_id: DeviceId, - pub(crate) challenge_info: (Cx, Challenge), + __phantom: PhantomData, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, pub(crate) public_key: Vec, @@ -43,9 +41,7 @@ where #[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] pub struct Credential { - pub(crate) rp_id: AuthorityId, - pub(crate) user_id: HashedUserId, - pub(crate) challenge_info: (Cx, Challenge), + __phantom: PhantomData, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, pub(crate) public_key: Vec, From d1e1f0545f5b94e34e3fe3ff53e2d6616656765e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 23:04:23 -0500 Subject: [PATCH 10/24] fix(pass-webauthn): split declarations that are needed in runtime from the ones that are not --- Cargo.lock | 6 +++--- pass-webauthn/src/impls.rs | 7 +------ pass-webauthn/src/lib.rs | 19 +++++++++++-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b3b465..4ce106e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1133,7 +1133,7 @@ dependencies = [ [[package]] name = "fc-pallet-pass" version = "1.0.0" -source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" dependencies = [ "fc-traits-authn", "frame-benchmarking", @@ -1152,7 +1152,7 @@ dependencies = [ [[package]] name = "fc-traits-authn" version = "0.1.0" -source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" dependencies = [ "fc-traits-authn-proc", "frame-support", @@ -1165,7 +1165,7 @@ dependencies = [ [[package]] name = "fc-traits-authn-proc" version = "0.1.0" -source = "git+https://github.com/virto-network/frame-contrib#24a0a448c7f534b779f6dc734e3a912025038d09" +source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" dependencies = [ "quote", "syn 2.0.79", diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index ed3b591..816e704 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -92,17 +92,12 @@ where } } +#[cfg(any(feature = "runtime", test))] impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { fn is_valid(&self) -> bool { - // TODO: Add sanity tests to verify that the information that's in the structure - // (`challenge_info`, `rp_id`, `device_id`) corresponds to the information in - // `authenticator_data` and `client_data`, and all that is congruent. - // - // Note: This might require using a json parsing library? - webauthn_verify( self.authenticator_data.as_ref(), &self.client_data, diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index 67b307c..ac3918a 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -3,11 +3,11 @@ use core::marker::PhantomData; use codec::{Decode, Encode}; -use frame_support::{DebugNoBound, Parameter}; +use frame_support::Parameter; use scale_info::TypeInfo; use traits_authn::{ util::{Auth, Dev}, - AuthorityId, Challenge, Challenger, HashedUserId, + Challenger, }; type CxOf = ::Context; @@ -17,11 +17,13 @@ mod tests; mod impls; +#[cfg(any(feature = "runtime", test))] pub type Authenticator = Auth, Attestation>>; +#[cfg(any(feature = "runtime", test))] pub type Device = Dev, A, Ch, Credential>>; -#[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] -pub struct Attestation { +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] +pub struct Attestation { __phantom: PhantomData, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, @@ -29,18 +31,19 @@ pub struct Attestation { pub(crate) signature: Vec, } -impl From>> for (Vec, PhantomData<(A, Ch, Cred)>) +#[cfg(any(feature = "runtime", test))] +impl From>> for Device where Ch: Challenger, CxOf: Parameter, { fn from(value: Attestation>) -> Self { - (value.public_key, PhantomData) + Device::new(value.public_key) } } -#[derive(Encode, Decode, TypeInfo, DebugNoBound, PartialEq, Eq, Clone)] -pub struct Credential { +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] +pub struct Credential { __phantom: PhantomData, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, From 8dedcfa01a8bfa787d12b4879ac39501ec21ea50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 10 Oct 2024 23:57:27 -0500 Subject: [PATCH 11/24] change(pass-webauthn): tests --- Cargo.lock | 1 - pass-webauthn/Cargo.toml | 9 +-- pass-webauthn/src/impls.rs | 23 +++++++- pass-webauthn/src/lib.rs | 22 +++---- pass-webauthn/src/tests.rs | 114 +++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ce106e..cd3006b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2228,7 +2228,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-io", - "sp-runtime", "verifier", ] diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index c9e9c60..6632422 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -9,26 +9,25 @@ version = "0.1.0" [dependencies] codec.workspace = true frame-support.workspace = true -frame-system.workspace = true +frame-support.optional = true scale-info.workspace = true traits-authn.workspace = true verifier.workspace = true [dev-dependencies] +frame-system.workspace = true pallet-balances.workspace = true pallet-pass.workspace = true sp-io.workspace = true -sp-runtime.workspace = true [features] default = ["std", "runtime"] -runtime = [] +runtime = ["frame-support"] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-pass/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", ] std = [ "codec/std", @@ -38,7 +37,6 @@ std = [ "pallet-pass/std", "scale-info/std", "sp-io/std", - "sp-runtime/std", "traits-authn/std", "verifier/std", ] @@ -47,5 +45,4 @@ try-runtime = [ "frame-system/try-runtime", "pallet-balances/try-runtime", "pallet-pass/try-runtime", - "sp-runtime/try-runtime", ] diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 816e704..5d6ff8f 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -2,11 +2,12 @@ use core::marker::PhantomData; use frame_support::Parameter; use traits_authn::{ - AuthorityId, Challenge, DeviceChallengeResponse, DeviceId, HashedUserId, UserChallengeResponse, + AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId, + UserChallengeResponse, }; use verifier::webauthn_verify; -use crate::{Attestation, Credential}; +use crate::{Attestation, Credential, CxOf, Device, DeviceInfo}; impl Attestation where @@ -64,6 +65,24 @@ where } } +#[cfg(any(feature = "runtime", test))] +impl From>> for Device +where + Ch: Challenger, + CxOf: Parameter + Copy + 'static, +{ + fn from(value: Attestation>) -> Self { + Device::new(DeviceInfo(value.device_id().clone())) + } +} + +#[cfg(any(feature = "runtime", test))] +impl AsRef for DeviceInfo { + fn as_ref(&self) -> &DeviceId { + &self.0 + } +} + impl Credential where Cx: Parameter, diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index ac3918a..506a6ec 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -2,12 +2,11 @@ use core::marker::PhantomData; -use codec::{Decode, Encode}; -use frame_support::Parameter; +use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use traits_authn::{ util::{Auth, Dev}, - Challenger, + Challenger, DeviceId, }; type CxOf = ::Context; @@ -20,7 +19,11 @@ mod impls; #[cfg(any(feature = "runtime", test))] pub type Authenticator = Auth, Attestation>>; #[cfg(any(feature = "runtime", test))] -pub type Device = Dev, A, Ch, Credential>>; +pub type Device = Dev>>; + +#[cfg(any(feature = "runtime", test))] +#[derive(MaxEncodedLen, TypeInfo, Decode, Encode)] +pub struct DeviceInfo(DeviceId); #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Attestation { @@ -31,17 +34,6 @@ pub struct Attestation { pub(crate) signature: Vec, } -#[cfg(any(feature = "runtime", test))] -impl From>> for Device -where - Ch: Challenger, - CxOf: Parameter, -{ - fn from(value: Attestation>) -> Self { - Device::new(value.public_key) - } -} - #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Credential { __phantom: PhantomData, diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index e69de29..749169d 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -0,0 +1,114 @@ +//! Test environment for pass webauthn. + +use frame_support::{ + assert_noop, assert_ok, derive_impl, parameter_types, + sp_runtime::{str_array as s, traits::Hash}, + traits::ConstU64, + PalletId, +}; +use frame_system::{pallet_prelude::BlockNumberFor, Config, EnsureRootWithSuccess}; +use traits_authn::{util::AuthorityFromPalletId, Challenger, HashedUserId}; + +use crate::{Attestation, Authenticator}; + +#[frame_support::runtime] +pub mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeTask, + RuntimeHoldReason, + RuntimeFreezeReason + )] + pub struct Test; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + #[runtime::pallet_index(1)] + pub type Pass = pallet_pass; + + #[runtime::pallet_index(10)] + pub type Balances = pallet_balances; +} + +pub type Block = frame_system::mocking::MockBlock; +pub type AccountId = ::AccountId; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type Block = Block; + type AccountData = pallet_balances::AccountData; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Test { + type AccountStore = System; +} + +parameter_types! { + pub PassPalletId: PalletId = PalletId(*b"pass/web"); + pub NeverPays: Option> = None; +} + +pub struct BlockChallenger; + +impl Challenger for BlockChallenger { + type Context = BlockNumberFor; + + fn generate(_: &Self::Context) -> traits_authn::Challenge { + ::Hashing::hash(&System::block_number().to_le_bytes()).0 + } +} + +impl pallet_pass::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type Authenticator = Authenticator>; + type PalletsOrigin = OriginCaller; + type PalletId = PassPalletId; + type MaxSessionDuration = ConstU64<10>; + type RegisterOrigin = EnsureRootWithSuccess; + type WeightInfo = (); +} + +fn new_test_ext() -> sp_io::TestExternalities { + let mut t = sp_io::TestExternalities::default(); + t.execute_with(|| { + System::set_block_number(1); + }); + t +} + +const USER: HashedUserId = s("the_user"); + +#[test] +fn registration_fails_if_attestation_is_invalid() { + new_test_ext().execute_with(|| { + // TODO: Fill with garbage data or incorrect signature (whatever works best) + assert_noop!( + Pass::register( + RuntimeOrigin::root(), + USER, + Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec()) + ), + pallet_pass::Error::::DeviceAttestationInvalid, + ); + }) +} + +#[test] +fn registration_works_if_attestation_is_valid() { + new_test_ext().execute_with(|| { + // TODO: Fill with valid data and signature + assert_ok!(Pass::register( + RuntimeOrigin::root(), + USER, + Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec()) + )); + }) +} From dcac66e46f70bf786016b8ea026d21e5f6a677a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Fri, 11 Oct 2024 01:28:13 -0500 Subject: [PATCH 12/24] change(pass-webauthn): complete tests --- Cargo.lock | 170 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 14 ++- pass-webauthn/Cargo.toml | 6 ++ pass-webauthn/src/tests.rs | 90 ++++++++++++++++---- 4 files changed, 263 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd3006b..7bdb920 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -929,6 +929,12 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.9.0" @@ -993,6 +999,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -1222,6 +1234,30 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "frame-benchmarking" version = "28.0.0" @@ -1644,6 +1680,16 @@ dependencies = [ "cc", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -1976,6 +2022,33 @@ dependencies = [ "adler2", ] +[[package]] +name = "mockall" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "nalgebra" version = "0.32.6" @@ -2009,6 +2082,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2224,10 +2303,15 @@ dependencies = [ "fc-traits-authn", "frame-support", "frame-system", + "futures", "pallet-balances", "parity-scale-codec", + "passkey-authenticator", + "passkey-client", + "passkey-types", "scale-info", "sp-io", + "url", "verifier", ] @@ -2240,11 +2324,31 @@ dependencies = [ "async-trait", "coset", "log", + "mockall", "p256", "passkey-types", "rand", ] +[[package]] +name = "passkey-client" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9b2f49d3758a7f3763daa87b3d10c235f093eef2f331de2bf6a1b7df17cb294" +dependencies = [ + "ciborium", + "coset", + "idna", + "mockall", + "passkey-authenticator", + "passkey-types", + "public-suffix", + "serde", + "serde_json", + "typeshare", + "url", +] + [[package]] name = "passkey-types" version = "0.3.0" @@ -2258,6 +2362,7 @@ dependencies = [ "getrandom", "hmac 0.12.1", "indexmap", + "p256", "rand", "serde", "serde_json", @@ -2303,6 +2408,12 @@ dependencies = [ "base64ct", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2377,6 +2488,36 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools 0.10.5", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" + +[[package]] +name = "predicates-tree" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettyplease" version = "0.2.22" @@ -2474,6 +2615,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "public-suffix" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a59553bc595dc1514e7d713e6167cf1c4d68ef6fcc2d10ad834a97a1ca9bc4" + [[package]] name = "quote" version = "1.0.37" @@ -3626,6 +3773,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "thiserror" version = "1.0.64" @@ -3898,6 +4051,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -3919,6 +4078,17 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7cec7b1..1c2ebbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,22 @@ repository = "https://github.com/virto-network/webauthn" [workspace.dependencies] # WebAuthN Verifier coset = { version = "0.3.0", default-features = false } +futures = { version = "0.3.31", default-features = false, features = [ + "executor", +] } p256 = { version = "0.13.2", default-features = false } -passkey-authenticator = { version = "0.3.0", default-features = false } +passkey-authenticator = { version = "0.3.0", default-features = false, features = [ + "testable", +] } +passkey-client = { version = "0.3.0", default-features = false, features = [ + "testable", +] } +passkey-types = { version = "0.3.0", default-features = false, features = [ + "testable", +] } sha2 = { version = "0.10.8", default-features = false } rand = "0.8.5" +url = "2.5.2" # FRAME codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [ diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index 6632422..869d1cb 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -16,9 +16,14 @@ verifier.workspace = true [dev-dependencies] frame-system.workspace = true +futures.workspace = true pallet-balances.workspace = true pallet-pass.workspace = true +passkey-authenticator.workspace = true +passkey-client.workspace = true +passkey-types.workspace = true sp-io.workspace = true +url.workspace = true [features] default = ["std", "runtime"] @@ -33,6 +38,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "futures/std", "pallet-balances/std", "pallet-pass/std", "scale-info/std", diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index 749169d..883326b 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -3,7 +3,7 @@ use frame_support::{ assert_noop, assert_ok, derive_impl, parameter_types, sp_runtime::{str_array as s, traits::Hash}, - traits::ConstU64, + traits::{ConstU64, Get}, PalletId, }; use frame_system::{pallet_prelude::BlockNumberFor, Config, EnsureRootWithSuccess}; @@ -54,13 +54,15 @@ parameter_types! { pub NeverPays: Option> = None; } +type AuthorityId = AuthorityFromPalletId; + pub struct BlockChallenger; impl Challenger for BlockChallenger { type Context = BlockNumberFor; - fn generate(_: &Self::Context) -> traits_authn::Challenge { - ::Hashing::hash(&System::block_number().to_le_bytes()).0 + fn generate(ctx: &Self::Context) -> traits_authn::Challenge { + ::Hashing::hash(&ctx.to_le_bytes()).0 } } @@ -68,7 +70,7 @@ impl pallet_pass::Config for Test { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; type Currency = Balances; - type Authenticator = Authenticator>; + type Authenticator = Authenticator; type PalletsOrigin = OriginCaller; type PalletId = PassPalletId; type MaxSessionDuration = ConstU64<10>; @@ -86,16 +88,73 @@ fn new_test_ext() -> sp_io::TestExternalities { const USER: HashedUserId = s("the_user"); +fn build_attesttation_fields(ctx: &BlockNumberFor) -> (Vec, Vec, Vec, Vec) { + use futures::executor::block_on; + use passkey_authenticator::{ + public_key_der_from_cose_key, Authenticator, MockUserValidationMethod, + }; + use passkey_client::{Client, DefaultClientData}; + use passkey_types::{ + ctap2::Aaguid, + webauthn::{ + AttestationConveyancePreference, CredentialRequestOptions, + PublicKeyCredentialRequestOptions, UserVerificationRequirement, + }, + Passkey, + }; + use url::Url; + + let aaguid = Aaguid::new_empty(); + let rp_id = String::from_utf8(PassPalletId::get().0.to_vec()) + .expect("converting from ascii to utf-8 is guaranteed; qed"); + let origin = + Url::parse(&format!("urn://blockchain/{rp_id}")).expect("urn parses as a valid URL"); + let key = Passkey::mock(rp_id.clone()).build(); + let store = Some(key.clone()); + + let authenticator = Authenticator::new(aaguid, store, MockUserValidationMethod::new()); + let mut client = Client::new(authenticator); + + let request = CredentialRequestOptions { + public_key: PublicKeyCredentialRequestOptions { + challenge: BlockChallenger::generate(ctx).as_slice().into(), + timeout: None, + rp_id: Some(rp_id), + allow_credentials: None, + user_verification: UserVerificationRequirement::default(), + hints: None, + attestation: AttestationConveyancePreference::None, + attestation_formats: None, + extensions: None, + }, + }; + + let authenticated_request = block_on(client.authenticate(&origin, request, DefaultClientData)) + .expect("authenticate works"); + + let authenticator_data = authenticated_request.response.authenticator_data; + let client_data = authenticated_request.response.client_data_json; + let public_key = public_key_der_from_cose_key(&key.key).expect("key conversion works"); + let signature = authenticated_request.response.signature; + + ( + authenticator_data.to_vec(), + client_data.to_vec(), + public_key.to_vec(), + signature.to_vec(), + ) +} + #[test] fn registration_fails_if_attestation_is_invalid() { new_test_ext().execute_with(|| { - // TODO: Fill with garbage data or incorrect signature (whatever works best) + let (authenticator_data, client_data, public_key, signature) = + build_attesttation_fields(&System::block_number()); + let signature = [signature, b"Whoops!".to_vec()].concat(); + let attestation = Attestation::new(authenticator_data, client_data, public_key, signature); + assert_noop!( - Pass::register( - RuntimeOrigin::root(), - USER, - Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec()) - ), + Pass::register(RuntimeOrigin::root(), USER, attestation), pallet_pass::Error::::DeviceAttestationInvalid, ); }) @@ -104,11 +163,10 @@ fn registration_fails_if_attestation_is_invalid() { #[test] fn registration_works_if_attestation_is_valid() { new_test_ext().execute_with(|| { - // TODO: Fill with valid data and signature - assert_ok!(Pass::register( - RuntimeOrigin::root(), - USER, - Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec()) - )); + let (authenticator_data, client_data, public_key, signature) = + build_attesttation_fields(&System::block_number()); + let attestation = Attestation::new(authenticator_data, client_data, public_key, signature); + + assert_ok!(Pass::register(RuntimeOrigin::root(), USER, attestation)); }) } From abb1917e67b9ccb702d2ddb0b4eb8c6a75663caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Fri, 11 Oct 2024 03:38:50 -0500 Subject: [PATCH 13/24] change(pass-webauthn): resolving challenge and authority from input data --- Cargo.lock | 8 ++++++ Cargo.toml | 4 ++- pass-webauthn/Cargo.toml | 4 +++ pass-webauthn/src/impls.rs | 28 +++++++++++++++++--- pass-webauthn/src/tests.rs | 54 ++++++++++++++++++++++++++++++++------ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bdb920..61ae576 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2310,6 +2310,8 @@ dependencies = [ "passkey-client", "passkey-types", "scale-info", + "serde_json", + "simple-base64", "sp-io", "url", "verifier", @@ -3086,6 +3088,12 @@ dependencies = [ "wide", ] +[[package]] +name = "simple-base64" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6385ef05b7bbfddaa8bf6306d059adac087990d659576c73b7da802d9a6ce91f" + [[package]] name = "simple-mermaid" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 1c2ebbc..89af21d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ repository = "https://github.com/virto-network/webauthn" [workspace.dependencies] # WebAuthN Verifier +base64 = { package = "simple-base64", version = "0.23.2", default-features = false } coset = { version = "0.3.0", default-features = false } futures = { version = "0.3.31", default-features = false, features = [ "executor", @@ -21,8 +22,9 @@ passkey-client = { version = "0.3.0", default-features = false, features = [ passkey-types = { version = "0.3.0", default-features = false, features = [ "testable", ] } -sha2 = { version = "0.10.8", default-features = false } rand = "0.8.5" +sha2 = { version = "0.10.8", default-features = false } +serde_json = { version = "1.0.128", default-features = false } url = "2.5.2" # FRAME diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index 869d1cb..a8ad3f3 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -7,10 +7,12 @@ repository.workspace = true version = "0.1.0" [dependencies] +base64.workspace = true codec.workspace = true frame-support.workspace = true frame-support.optional = true scale-info.workspace = true +serde_json.workspace = true traits-authn.workspace = true verifier.workspace = true @@ -35,6 +37,7 @@ runtime-benchmarks = [ "pallet-pass/runtime-benchmarks", ] std = [ + "base64/std", "codec/std", "frame-support/std", "frame-system/std", @@ -42,6 +45,7 @@ std = [ "pallet-balances/std", "pallet-pass/std", "scale-info/std", + "serde_json/std", "sp-io/std", "traits-authn/std", "verifier/std", diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 5d6ff8f..96decc3 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -1,6 +1,8 @@ use core::marker::PhantomData; -use frame_support::Parameter; +use codec::Decode; +use frame_support::{sp_runtime::traits::TrailingZeroInput, Parameter}; +use serde_json::Value; use traits_authn::{ AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId, UserChallengeResponse, @@ -33,7 +35,16 @@ where } fn challenge(&self) -> Challenge { - todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let challenge_str = + base64::decode(client_data_json["challenge"].as_str().ok_or(())?.as_bytes()) + .map_err(|_| ())?; + Decode::decode(&mut TrailingZeroInput::new(&challenge_str)).map_err(|_| ())? + }() + .unwrap_or_default() } } @@ -57,7 +68,18 @@ where } fn authority(&self) -> AuthorityId { - todo!("Extract `rp_id`, format into `AuthorityId` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let origin = client_data_json["origin"].as_str().ok_or(())?; + let (_, domain) = origin.split_once("//").ok_or(())?; + let (rp_id_subdomain, _) = domain.split_once(".").ok_or(())?; + + Decode::decode(&mut TrailingZeroInput::new(rp_id_subdomain.as_bytes())) + .map_err(|_| ())? + }() + .unwrap_or_default() } fn device_id(&self) -> &DeviceId { diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index 883326b..526831f 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -3,13 +3,13 @@ use frame_support::{ assert_noop, assert_ok, derive_impl, parameter_types, sp_runtime::{str_array as s, traits::Hash}, - traits::{ConstU64, Get}, + traits::ConstU64, PalletId, }; use frame_system::{pallet_prelude::BlockNumberFor, Config, EnsureRootWithSuccess}; use traits_authn::{util::AuthorityFromPalletId, Challenger, HashedUserId}; -use crate::{Attestation, Authenticator}; +use crate::{Attestation, Authenticator, Credential}; #[frame_support::runtime] pub mod runtime { @@ -50,7 +50,7 @@ impl pallet_balances::Config for Test { } parameter_types! { - pub PassPalletId: PalletId = PalletId(*b"pass/web"); + pub PassPalletId: PalletId = PalletId(*b"pass_web"); pub NeverPays: Option> = None; } @@ -76,6 +76,27 @@ impl pallet_pass::Config for Test { type MaxSessionDuration = ConstU64<10>; type RegisterOrigin = EnsureRootWithSuccess; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = Helper; +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct Helper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_pass::BenchmarkHelper for Helper { + fn register_origin() -> frame_system::pallet_prelude::OriginFor { + RuntimeOrigin::root() + } + + fn device_attestation(_: traits_authn::DeviceId) -> pallet_pass::DeviceAttestationOf { + let (a, b, c, d) = build_attesttation_fields(&System::block_number()); + Attestation::new(a, b, c, d) + } + + fn credential(_: HashedUserId) -> pallet_pass::CredentialOf { + let (a, b, c, d) = build_attesttation_fields(&System::block_number()); + Credential::new(a, b, c, d) + } } fn new_test_ext() -> sp_io::TestExternalities { @@ -108,18 +129,19 @@ fn build_attesttation_fields(ctx: &BlockNumberFor) -> (Vec, Vec, V let rp_id = String::from_utf8(PassPalletId::get().0.to_vec()) .expect("converting from ascii to utf-8 is guaranteed; qed"); let origin = - Url::parse(&format!("urn://blockchain/{rp_id}")).expect("urn parses as a valid URL"); - let key = Passkey::mock(rp_id.clone()).build(); + Url::parse(&format!("https://{rp_id}.pallet-pass.int")).expect("urn parses as a valid URL"); + let key = Passkey::mock(rp_id).build(); let store = Some(key.clone()); - let authenticator = Authenticator::new(aaguid, store, MockUserValidationMethod::new()); + let authenticator = + Authenticator::new(aaguid, store, MockUserValidationMethod::verified_user(1)); let mut client = Client::new(authenticator); let request = CredentialRequestOptions { public_key: PublicKeyCredentialRequestOptions { challenge: BlockChallenger::generate(ctx).as_slice().into(), timeout: None, - rp_id: Some(rp_id), + rp_id: None, allow_credentials: None, user_verification: UserVerificationRequirement::default(), hints: None, @@ -151,7 +173,23 @@ fn registration_fails_if_attestation_is_invalid() { let (authenticator_data, client_data, public_key, signature) = build_attesttation_fields(&System::block_number()); let signature = [signature, b"Whoops!".to_vec()].concat(); - let attestation = Attestation::new(authenticator_data, client_data, public_key, signature); + + use passkey_types::ctap2::AuthenticatorData; + let raw_authenticator_data = AuthenticatorData::from_slice(&authenticator_data) + .expect("this conversion works both ways"); + + println!( + "authenticator_data = {:?}\nclient_data_json = {}", + &raw_authenticator_data, + &String::from_utf8(client_data.clone()).expect("converting json works") + ); + + let attestation = Attestation::new( + authenticator_data.to_vec(), + client_data, + public_key, + signature, + ); assert_noop!( Pass::register(RuntimeOrigin::root(), USER, attestation), From 1f0edb5058a3da5dc7d2f899e9403c114211728e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Sun, 13 Oct 2024 20:03:53 -0500 Subject: [PATCH 14/24] change(Cargo): import `public-suffix` for `pass-webauthn` test --- Cargo.lock | 59 +++++++++++++++++----------------------- Cargo.toml | 1 + pass-webauthn/Cargo.toml | 2 ++ 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61ae576..ffc2ead 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -614,9 +614,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -632,9 +632,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "shlex", ] @@ -1145,7 +1145,7 @@ dependencies = [ [[package]] name = "fc-pallet-pass" version = "1.0.0" -source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" +source = "git+https://github.com/virto-network/frame-contrib#aee5270ecd5577c0f5a5c700b0127cae9801737a" dependencies = [ "fc-traits-authn", "frame-benchmarking", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "fc-traits-authn" version = "0.1.0" -source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" +source = "git+https://github.com/virto-network/frame-contrib#aee5270ecd5577c0f5a5c700b0127cae9801737a" dependencies = [ "fc-traits-authn-proc", "frame-support", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "fc-traits-authn-proc" version = "0.1.0" -source = "git+https://github.com/virto-network/frame-contrib#fef585072129f142ce1f3bc7401c6a4fb861f0b0" +source = "git+https://github.com/virto-network/frame-contrib#aee5270ecd5577c0f5a5c700b0127cae9801737a" dependencies = [ "quote", "syn 2.0.79", @@ -1896,9 +1896,9 @@ dependencies = [ [[package]] name = "linregress" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de04dcecc58d366391f9920245b85ffa684558a5ef6e7736e754347c3aea9c2" +checksum = "a9eda9dcf4f2a99787827661f312ac3219292549c2ee992bf9a6248ffb066bf7" dependencies = [ "nalgebra", ] @@ -2051,13 +2051,12 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.6" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" +checksum = "3c4b5f057b303842cf3262c27e465f4c303572e7f6b0648f60e16248ac3397f4" dependencies = [ "approx", "matrixmultiply", - "nalgebra-macros", "num-complex", "num-rational", "num-traits", @@ -2065,17 +2064,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "nalgebra-macros" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2148,6 +2136,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ + "num-bigint", "num-integer", "num-traits", ] @@ -2299,6 +2288,7 @@ dependencies = [ name = "pass-webauthn" version = "0.1.0" dependencies = [ + "coset", "fc-pallet-pass", "fc-traits-authn", "frame-support", @@ -2309,6 +2299,7 @@ dependencies = [ "passkey-authenticator", "passkey-client", "passkey-types", + "public-suffix", "scale-info", "serde_json", "simple-base64", @@ -3077,9 +3068,9 @@ dependencies = [ [[package]] name = "simba" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ "approx", "num-complex", @@ -3247,7 +3238,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -3300,7 +3291,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "proc-macro2", "quote", @@ -3320,7 +3311,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "environmental", "parity-scale-codec", @@ -3456,7 +3447,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -3488,7 +3479,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "Inflector", "expander", @@ -3539,7 +3530,7 @@ source = "git+https://github.com/virto-network/polkadot-sdk?branch=release-virto [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" [[package]] name = "sp-storage" @@ -3556,7 +3547,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "impl-serde", "parity-scale-codec", @@ -3579,7 +3570,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "parity-scale-codec", "tracing", @@ -3651,7 +3642,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#439b31ef9bbdf0e0709bbab4804a9590b48ba8f0" +source = "git+https://github.com/paritytech/polkadot-sdk#d1c115b6197bf6c45d5640594f0432e6c2781a4f" dependencies = [ "anyhow", "impl-trait-for-tuples", diff --git a/Cargo.toml b/Cargo.toml index 89af21d..39c4413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ passkey-client = { version = "0.3.0", default-features = false, features = [ passkey-types = { version = "0.3.0", default-features = false, features = [ "testable", ] } +public-suffix = "0.1" rand = "0.8.5" sha2 = { version = "0.10.8", default-features = false } serde_json = { version = "1.0.128", default-features = false } diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index a8ad3f3..feebabb 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -17,6 +17,7 @@ traits-authn.workspace = true verifier.workspace = true [dev-dependencies] +coset.workspace = true frame-system.workspace = true futures.workspace = true pallet-balances.workspace = true @@ -24,6 +25,7 @@ pallet-pass.workspace = true passkey-authenticator.workspace = true passkey-client.workspace = true passkey-types.workspace = true +public-suffix.workspace = true sp-io.workspace = true url.workspace = true From 025f5c9fae0311b631b3b4109555982153d45e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 12:25:51 -0500 Subject: [PATCH 15/24] change(pass-webauthn/tests): adjust test setup --- pass-webauthn/src/tests.rs | 123 ++++--------- .../src/tests/authenticator_client.rs | 169 ++++++++++++++++++ 2 files changed, 199 insertions(+), 93 deletions(-) create mode 100644 pass-webauthn/src/tests/authenticator_client.rs diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index 526831f..53b3d33 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -7,9 +7,14 @@ use frame_support::{ PalletId, }; use frame_system::{pallet_prelude::BlockNumberFor, Config, EnsureRootWithSuccess}; +use sp_io::hashing::blake2_256; use traits_authn::{util::AuthorityFromPalletId, Challenger, HashedUserId}; -use crate::{Attestation, Authenticator, Credential}; +use crate::Authenticator; + +mod authenticator_client; + +use authenticator_client::*; #[frame_support::runtime] pub mod runtime { @@ -89,107 +94,39 @@ impl pallet_pass::BenchmarkHelper for Helper { } fn device_attestation(_: traits_authn::DeviceId) -> pallet_pass::DeviceAttestationOf { - let (a, b, c, d) = build_attesttation_fields(&System::block_number()); - Attestation::new(a, b, c, d) + WebAuthnClient::new("https://helper.pass.int") + .attestation(blake2_256(b"USER_ID"), System::block_number()) + } + + fn credential(user_id: HashedUserId) -> pallet_pass::CredentialOf { + let mut client = WebAuthnClient::new("https://helper.pass.int"); + let attestation = client.attestation(user_id, System::block_number()); + client.credential(attestation.credential_id.as_slice(), System::block_number()) } +} - fn credential(_: HashedUserId) -> pallet_pass::CredentialOf { - let (a, b, c, d) = build_attesttation_fields(&System::block_number()); - Credential::new(a, b, c, d) +struct TestExt(pub sp_io::TestExternalities, pub WebAuthnClient); +impl TestExt { + pub fn execute_with(&mut self, execute: impl FnOnce(&mut WebAuthnClient) -> R) -> R { + self.0.execute_with(|| execute(&mut self.1)) } } -fn new_test_ext() -> sp_io::TestExternalities { +fn new_test_ext() -> TestExt { let mut t = sp_io::TestExternalities::default(); t.execute_with(|| { System::set_block_number(1); }); - t + TestExt(t, WebAuthnClient::new("https://webauthn.pass.int")) } const USER: HashedUserId = s("the_user"); -fn build_attesttation_fields(ctx: &BlockNumberFor) -> (Vec, Vec, Vec, Vec) { - use futures::executor::block_on; - use passkey_authenticator::{ - public_key_der_from_cose_key, Authenticator, MockUserValidationMethod, - }; - use passkey_client::{Client, DefaultClientData}; - use passkey_types::{ - ctap2::Aaguid, - webauthn::{ - AttestationConveyancePreference, CredentialRequestOptions, - PublicKeyCredentialRequestOptions, UserVerificationRequirement, - }, - Passkey, - }; - use url::Url; - - let aaguid = Aaguid::new_empty(); - let rp_id = String::from_utf8(PassPalletId::get().0.to_vec()) - .expect("converting from ascii to utf-8 is guaranteed; qed"); - let origin = - Url::parse(&format!("https://{rp_id}.pallet-pass.int")).expect("urn parses as a valid URL"); - let key = Passkey::mock(rp_id).build(); - let store = Some(key.clone()); - - let authenticator = - Authenticator::new(aaguid, store, MockUserValidationMethod::verified_user(1)); - let mut client = Client::new(authenticator); - - let request = CredentialRequestOptions { - public_key: PublicKeyCredentialRequestOptions { - challenge: BlockChallenger::generate(ctx).as_slice().into(), - timeout: None, - rp_id: None, - allow_credentials: None, - user_verification: UserVerificationRequirement::default(), - hints: None, - attestation: AttestationConveyancePreference::None, - attestation_formats: None, - extensions: None, - }, - }; - - let authenticated_request = block_on(client.authenticate(&origin, request, DefaultClientData)) - .expect("authenticate works"); - - let authenticator_data = authenticated_request.response.authenticator_data; - let client_data = authenticated_request.response.client_data_json; - let public_key = public_key_der_from_cose_key(&key.key).expect("key conversion works"); - let signature = authenticated_request.response.signature; - - ( - authenticator_data.to_vec(), - client_data.to_vec(), - public_key.to_vec(), - signature.to_vec(), - ) -} - #[test] fn registration_fails_if_attestation_is_invalid() { - new_test_ext().execute_with(|| { - let (authenticator_data, client_data, public_key, signature) = - build_attesttation_fields(&System::block_number()); - let signature = [signature, b"Whoops!".to_vec()].concat(); - - use passkey_types::ctap2::AuthenticatorData; - let raw_authenticator_data = AuthenticatorData::from_slice(&authenticator_data) - .expect("this conversion works both ways"); - - println!( - "authenticator_data = {:?}\nclient_data_json = {}", - &raw_authenticator_data, - &String::from_utf8(client_data.clone()).expect("converting json works") - ); - - let attestation = Attestation::new( - authenticator_data.to_vec(), - client_data, - public_key, - signature, - ); + new_test_ext().execute_with(|client| { + let mut attestation = client.attestation(USER, System::block_number()); + attestation.signature = [attestation.signature, b"Whoops!".to_vec()].concat(); assert_noop!( Pass::register(RuntimeOrigin::root(), USER, attestation), @@ -200,11 +137,11 @@ fn registration_fails_if_attestation_is_invalid() { #[test] fn registration_works_if_attestation_is_valid() { - new_test_ext().execute_with(|| { - let (authenticator_data, client_data, public_key, signature) = - build_attesttation_fields(&System::block_number()); - let attestation = Attestation::new(authenticator_data, client_data, public_key, signature); - - assert_ok!(Pass::register(RuntimeOrigin::root(), USER, attestation)); + new_test_ext().execute_with(|client| { + assert_ok!(Pass::register( + RuntimeOrigin::root(), + USER, + client.attestation(USER, System::block_number()) + )); }) } diff --git a/pass-webauthn/src/tests/authenticator_client.rs b/pass-webauthn/src/tests/authenticator_client.rs new file mode 100644 index 0000000..b162340 --- /dev/null +++ b/pass-webauthn/src/tests/authenticator_client.rs @@ -0,0 +1,169 @@ +use codec::Decode; +use frame_support::sp_runtime::traits::TrailingZeroInput; +use frame_system::pallet_prelude::BlockNumberFor; +use futures::executor::block_on; + +use passkey_authenticator::{Authenticator, MockUserValidationMethod}; +use passkey_client::{Client, DefaultClientData}; +use passkey_types::{ctap2::Aaguid, webauthn::*, Bytes, Passkey}; + +use traits_authn::{Challenger, HashedUserId}; +use url::Url; + +use crate::DEREncodedPublicKey; + +use super::{BlockChallenger, Test}; + +pub struct WebAuthnClient { + origin: Url, + client: Client, MockUserValidationMethod, public_suffix::PublicSuffixList>, +} + +impl WebAuthnClient { + pub fn new(origin: &'static str) -> Self { + // Create Authenticator + let authenticator = Authenticator::new( + Aaguid::new_empty(), + None, + MockUserValidationMethod::verified_user(1), + ); + Self { + origin: Url::parse(origin).expect("invalid url provided"), + client: Client::new(authenticator), + } + } + + pub fn create_credential_sync( + &mut self, + user_id: HashedUserId, + challenge: impl Into, + ) -> Result<(Vec, DEREncodedPublicKey), ()> { + let creation_options = CredentialCreationOptions { + public_key: PublicKeyCredentialCreationOptions { + rp: PublicKeyCredentialRpEntity { + id: None, + name: self.origin.domain().unwrap().into(), + }, + user: PublicKeyCredentialUserEntity { + id: user_id.as_slice().into(), + display_name: "".into(), + name: "".into(), + }, + challenge: challenge.into(), + pub_key_cred_params: vec![PublicKeyCredentialParameters { + ty: PublicKeyCredentialType::PublicKey, + alg: coset::iana::Algorithm::ES256, + }], + timeout: None, + exclude_credentials: None, + authenticator_selection: None, + hints: None, + attestation: AttestationConveyancePreference::Direct, + attestation_formats: Some(vec![AttestationStatementFormatIdentifiers::Packed]), + extensions: None, + }, + }; + + // Register the credential and block until result + let result = block_on(self.client.register( + &self.origin, + creation_options, + DefaultClientData, + )) + .map_err(|_| ())?; + + // Extracting required fields + let public_key: DEREncodedPublicKey = result + .response + .public_key + .map(|pk| { + Decode::decode(&mut TrailingZeroInput::new(&*pk)) + .expect("Invalid public key length") + }) + .ok_or(())?; + + Ok((result.raw_id.into(), public_key)) + } + + pub fn authenticate_credential_sync( + &mut self, + credential_id: impl Into, + challenge: impl Into, + ) -> Result<(Vec, Vec, Vec), ()> { + let request_options = CredentialRequestOptions { + public_key: PublicKeyCredentialRequestOptions { + challenge: challenge.into(), // Provided as input + rp_id: Some(self.origin.domain().unwrap().into()), + allow_credentials: Some(vec![PublicKeyCredentialDescriptor { + ty: PublicKeyCredentialType::PublicKey, + id: credential_id.into(), + transports: None, + }]), + timeout: None, + user_verification: UserVerificationRequirement::default(), + hints: None, + attestation: AttestationConveyancePreference::None, + attestation_formats: None, + extensions: None, + }, + }; + + // Assuming you have already initialized `client` + let result = block_on(self.client.authenticate( + &self.origin, + request_options, + DefaultClientData, + )) + .map_err(|_| ())?; + + // Extracting required fields + let authenticator_data = result.response.authenticator_data.to_vec(); + let client_data = result.response.client_data_json.to_vec(); + let signature = result.response.signature.to_vec(); + + Ok((authenticator_data, client_data, signature)) + } + + pub fn attestation( + &mut self, + user_id: HashedUserId, + context: BlockNumberFor, + ) -> crate::Attestation> { + let challenge = BlockChallenger::generate(&context); + + let (credential_id, public_key) = self + .create_credential_sync(user_id, challenge.as_slice()) + .expect("Failed creating credential"); + let (authenticator_data, client_data, signature) = self + .authenticate_credential_sync(credential_id, challenge.as_slice()) + .expect("Failed retrieving credential"); + + crate::Attestation { + credential_id, + context, + authenticator_data, + client_data, + public_key, + signature, + } + } + + pub fn credential( + &mut self, + credential_id: impl Into, + context: BlockNumberFor, + ) -> crate::Credential> { + let challenge = BlockChallenger::generate(&context); + + let (authenticator_data, client_data, signature) = self + .authenticate_credential_sync(credential_id, challenge.as_slice()) + .expect("Failed retrieving credential"); + + crate::Credential { + context, + authenticator_data, + client_data, + signature, + } + } +} From 95fa04264482bcc748a39840492cd83128cbe9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 12:26:17 -0500 Subject: [PATCH 16/24] wip(pass-webauthn): apply changes and leave for finishing `Attestation`. --- pass-webauthn/src/impls.rs | 79 ++++++++++++-------------------------- pass-webauthn/src/lib.rs | 25 ++++++------ 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 96decc3..45260bb 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -1,11 +1,10 @@ -use core::marker::PhantomData; - use codec::Decode; use frame_support::{sp_runtime::traits::TrailingZeroInput, Parameter}; use serde_json::Value; +use sp_io::hashing::blake2_256; use traits_authn::{ - AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId, - UserChallengeResponse, + util::VerifyCredential, AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, + HashedUserId, UserChallengeResponse, }; use verifier::webauthn_verify; @@ -15,25 +14,6 @@ impl Attestation where Cx: Parameter, { - pub fn new( - authenticator_data: Vec, - client_data: Vec, - signature: Vec, - public_key: Vec, - ) -> Self { - Self { - __phantom: PhantomData, - authenticator_data, - client_data, - signature, - public_key, - } - } - - fn context(&self) -> Cx { - todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); - } - fn challenge(&self) -> Challenge { || -> Result { let client_data_json = @@ -64,7 +44,7 @@ where } fn used_challenge(&self) -> (Cx, Challenge) { - (self.context(), self.challenge()) + (self.context, self.challenge()) } fn authority(&self) -> AuthorityId { @@ -83,7 +63,7 @@ where } fn device_id(&self) -> &DeviceId { - todo!("Extract `device_id`, format into `DeviceId` format (that is, [u8; 32])"); + &self.credential_id } } @@ -94,14 +74,29 @@ where CxOf: Parameter + Copy + 'static, { fn from(value: Attestation>) -> Self { - Device::new(DeviceInfo(value.device_id().clone())) + Device::new(DeviceInfo { + device_id: value.device_id().clone(), + public_key: value.public_key, + }) + } +} + +impl VerifyCredential> for DeviceInfo { + fn verify(&self, credential: &Credential) -> Option<()> { + webauthn_verify( + &credential.authenticator_data, + &credential.client_data, + &credential.signature, + &self.public_key, + ) + .ok() } } #[cfg(any(feature = "runtime", test))] impl AsRef for DeviceInfo { fn as_ref(&self) -> &DeviceId { - &self.0 + &self.device_id } } @@ -109,25 +104,6 @@ impl Credential where Cx: Parameter, { - pub fn new( - authenticator_data: Vec, - client_data: Vec, - signature: Vec, - public_key: Vec, - ) -> Self { - Self { - __phantom: PhantomData, - authenticator_data, - client_data, - signature, - public_key, - } - } - - fn context(&self) -> Cx { - todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); - } - fn challenge(&self) -> Challenge { todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); } @@ -138,18 +114,13 @@ impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { + // TODO: @jgutierrezre please check if there are necessary validations involved here. fn is_valid(&self) -> bool { - webauthn_verify( - self.authenticator_data.as_ref(), - &self.client_data, - &self.signature, - &self.public_key, - ) - .is_ok() + true } fn used_challenge(&self) -> (Cx, Challenge) { - (self.context(), self.challenge()) + (self.context, self.challenge()) } fn authority(&self) -> AuthorityId { diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index 506a6ec..f361008 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -1,20 +1,19 @@ #![cfg_attr(not(feature = "std"), no_std)] -use core::marker::PhantomData; - use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use traits_authn::{ util::{Auth, Dev}, - Challenger, DeviceId, + Challenger, DeviceId, HashedUserId, }; type CxOf = ::Context; +mod impls; #[cfg(test)] mod tests; -mod impls; +pub type DEREncodedPublicKey = [u8; 91]; #[cfg(any(feature = "runtime", test))] pub type Authenticator = Auth, Attestation>>; @@ -23,22 +22,26 @@ pub type Device = Dev>>; #[cfg(any(feature = "runtime", test))] #[derive(MaxEncodedLen, TypeInfo, Decode, Encode)] -pub struct DeviceInfo(DeviceId); +pub struct DeviceInfo { + device_id: DeviceId, + //. A DER-encoded public key + public_key: DEREncodedPublicKey, +} #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Attestation { - __phantom: PhantomData, + pub(crate) credential_id: DeviceId, + pub(crate) context: Cx, pub(crate) authenticator_data: Vec, - pub(crate) client_data: Vec, - pub(crate) public_key: Vec, - pub(crate) signature: Vec, + pub(crate) attestation_data: Vec, + pub(crate) public_key: DEREncodedPublicKey, } #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Credential { - __phantom: PhantomData, + pub(crate) user_id: HashedUserId, + pub(crate) context: Cx, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, - pub(crate) public_key: Vec, pub(crate) signature: Vec, } From c55a062bbab43828e6c9c7c4957c95020ce996e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Guti=C3=A9rrez=20Restrepo?= Date: Mon, 14 Oct 2024 14:41:31 -0500 Subject: [PATCH 17/24] change(pass-webauthn): fix impls and work towards registration verification. --- pass-webauthn/src/impls.rs | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 45260bb..15499c0 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -15,7 +15,7 @@ where Cx: Parameter, { fn challenge(&self) -> Challenge { - || -> Result { + || -> Result { let client_data_json = serde_json::from_slice::(&self.client_data).map_err(|_| ())?; @@ -33,14 +33,11 @@ impl DeviceChallengeResponse for Attestation where Cx: Parameter + Copy + 'static, { + // TODO: @pandres95, considering that DeviceChallengeResponse is used for creating a new + // authentication device, webauth_verify wouldn't work here. We need to implement a new + // verification method exclusively for credential creation. fn is_valid(&self) -> bool { - webauthn_verify( - self.authenticator_data.as_ref(), - &self.client_data, - &self.signature, - &self.public_key, - ) - .is_ok() + true } fn used_challenge(&self) -> (Cx, Challenge) { @@ -105,7 +102,17 @@ where Cx: Parameter, { fn challenge(&self) -> Challenge { - todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let challenge_str = + base64::decode(client_data_json["challenge"].as_str().ok_or(())?.as_bytes()) + .map_err(|_| ())?; + + Decode::decode(&mut TrailingZeroInput::new(challenge_str.as_bytes())).map_err(|_| ())? + }() + .unwrap_or_default() } } @@ -114,9 +121,14 @@ impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { - // TODO: @jgutierrezre please check if there are necessary validations involved here. fn is_valid(&self) -> bool { - true + webauthn_verify( + self.authenticator_data.as_ref(), + &self.client_data, + &self.signature, + &self.public_key, + ) + .is_ok() } fn used_challenge(&self) -> (Cx, Challenge) { @@ -124,10 +136,21 @@ where } fn authority(&self) -> AuthorityId { - todo!("Extract `rp_id`, format into `AuthorityId` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let origin = client_data_json["origin"].as_str().ok_or(())?; + let (_, domain) = origin.split_once("//").ok_or(())?; + let (rp_id_subdomain, _) = domain.split_once(".").ok_or(())?; + + Decode::decode(&mut TrailingZeroInput::new(rp_id_subdomain.as_bytes())) + .map_err(|_| ())? + }() + .unwrap_or_default() } fn user_id(&self) -> HashedUserId { - todo!("Extract `user_id`, format into `HashedUserId` format (that is, [u8; 32])"); + &self.user_id } } From ea8ca28adf60459c9f96f9fd7a519edf6c4b163f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:14:46 -0500 Subject: [PATCH 18/24] change(pass-webauthn): minor refactor + complete implementations for supporting structures --- pass-webauthn/Cargo.toml | 6 +- pass-webauthn/src/impls.rs | 156 ------------------ pass-webauthn/src/lib.rs | 30 +++- pass-webauthn/src/runtime_helpers.rs | 39 +++++ pass-webauthn/src/runtime_impls/assertion.rs | 32 ++++ .../src/runtime_impls/attestation.rs | 37 +++++ pass-webauthn/src/runtime_impls/credential.rs | 39 +++++ pass-webauthn/src/runtime_impls/mod.rs | 8 + 8 files changed, 180 insertions(+), 167 deletions(-) delete mode 100644 pass-webauthn/src/impls.rs create mode 100644 pass-webauthn/src/runtime_helpers.rs create mode 100644 pass-webauthn/src/runtime_impls/assertion.rs create mode 100644 pass-webauthn/src/runtime_impls/attestation.rs create mode 100644 pass-webauthn/src/runtime_impls/credential.rs create mode 100644 pass-webauthn/src/runtime_impls/mod.rs diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index feebabb..1453022 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -12,8 +12,9 @@ codec.workspace = true frame-support.workspace = true frame-support.optional = true scale-info.workspace = true -serde_json.workspace = true traits-authn.workspace = true +url.workspace = true +sp-io.workspace = true verifier.workspace = true [dev-dependencies] @@ -26,8 +27,7 @@ passkey-authenticator.workspace = true passkey-client.workspace = true passkey-types.workspace = true public-suffix.workspace = true -sp-io.workspace = true -url.workspace = true +serde_json.workspace = true [features] default = ["std", "runtime"] diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs deleted file mode 100644 index 15499c0..0000000 --- a/pass-webauthn/src/impls.rs +++ /dev/null @@ -1,156 +0,0 @@ -use codec::Decode; -use frame_support::{sp_runtime::traits::TrailingZeroInput, Parameter}; -use serde_json::Value; -use sp_io::hashing::blake2_256; -use traits_authn::{ - util::VerifyCredential, AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, - HashedUserId, UserChallengeResponse, -}; -use verifier::webauthn_verify; - -use crate::{Attestation, Credential, CxOf, Device, DeviceInfo}; - -impl Attestation -where - Cx: Parameter, -{ - fn challenge(&self) -> Challenge { - || -> Result { - let client_data_json = - serde_json::from_slice::(&self.client_data).map_err(|_| ())?; - - let challenge_str = - base64::decode(client_data_json["challenge"].as_str().ok_or(())?.as_bytes()) - .map_err(|_| ())?; - Decode::decode(&mut TrailingZeroInput::new(&challenge_str)).map_err(|_| ())? - }() - .unwrap_or_default() - } -} - -#[cfg(any(feature = "runtime", test))] -impl DeviceChallengeResponse for Attestation -where - Cx: Parameter + Copy + 'static, -{ - // TODO: @pandres95, considering that DeviceChallengeResponse is used for creating a new - // authentication device, webauth_verify wouldn't work here. We need to implement a new - // verification method exclusively for credential creation. - fn is_valid(&self) -> bool { - true - } - - fn used_challenge(&self) -> (Cx, Challenge) { - (self.context, self.challenge()) - } - - fn authority(&self) -> AuthorityId { - || -> Result { - let client_data_json = - serde_json::from_slice::(&self.client_data).map_err(|_| ())?; - - let origin = client_data_json["origin"].as_str().ok_or(())?; - let (_, domain) = origin.split_once("//").ok_or(())?; - let (rp_id_subdomain, _) = domain.split_once(".").ok_or(())?; - - Decode::decode(&mut TrailingZeroInput::new(rp_id_subdomain.as_bytes())) - .map_err(|_| ())? - }() - .unwrap_or_default() - } - - fn device_id(&self) -> &DeviceId { - &self.credential_id - } -} - -#[cfg(any(feature = "runtime", test))] -impl From>> for Device -where - Ch: Challenger, - CxOf: Parameter + Copy + 'static, -{ - fn from(value: Attestation>) -> Self { - Device::new(DeviceInfo { - device_id: value.device_id().clone(), - public_key: value.public_key, - }) - } -} - -impl VerifyCredential> for DeviceInfo { - fn verify(&self, credential: &Credential) -> Option<()> { - webauthn_verify( - &credential.authenticator_data, - &credential.client_data, - &credential.signature, - &self.public_key, - ) - .ok() - } -} - -#[cfg(any(feature = "runtime", test))] -impl AsRef for DeviceInfo { - fn as_ref(&self) -> &DeviceId { - &self.device_id - } -} - -impl Credential -where - Cx: Parameter, -{ - fn challenge(&self) -> Challenge { - || -> Result { - let client_data_json = - serde_json::from_slice::(&self.client_data).map_err(|_| ())?; - - let challenge_str = - base64::decode(client_data_json["challenge"].as_str().ok_or(())?.as_bytes()) - .map_err(|_| ())?; - - Decode::decode(&mut TrailingZeroInput::new(challenge_str.as_bytes())).map_err(|_| ())? - }() - .unwrap_or_default() - } -} - -#[cfg(any(feature = "runtime", test))] -impl UserChallengeResponse for Credential -where - Cx: Parameter + Copy + 'static, -{ - fn is_valid(&self) -> bool { - webauthn_verify( - self.authenticator_data.as_ref(), - &self.client_data, - &self.signature, - &self.public_key, - ) - .is_ok() - } - - fn used_challenge(&self) -> (Cx, Challenge) { - (self.context, self.challenge()) - } - - fn authority(&self) -> AuthorityId { - || -> Result { - let client_data_json = - serde_json::from_slice::(&self.client_data).map_err(|_| ())?; - - let origin = client_data_json["origin"].as_str().ok_or(())?; - let (_, domain) = origin.split_once("//").ok_or(())?; - let (rp_id_subdomain, _) = domain.split_once(".").ok_or(())?; - - Decode::decode(&mut TrailingZeroInput::new(rp_id_subdomain.as_bytes())) - .map_err(|_| ())? - }() - .unwrap_or_default() - } - - fn user_id(&self) -> HashedUserId { - &self.user_id - } -} diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index f361008..a3ca6da 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -9,7 +9,11 @@ use traits_authn::{ type CxOf = ::Context; -mod impls; +#[cfg(any(feature = "runtime", test))] +mod runtime_helpers; +#[cfg(any(feature = "runtime", test))] +pub mod runtime_impls; + #[cfg(test)] mod tests; @@ -18,29 +22,39 @@ pub type DEREncodedPublicKey = [u8; 91]; #[cfg(any(feature = "runtime", test))] pub type Authenticator = Auth, Attestation>>; #[cfg(any(feature = "runtime", test))] -pub type Device = Dev>>; +pub type Device = Dev>>; #[cfg(any(feature = "runtime", test))] #[derive(MaxEncodedLen, TypeInfo, Decode, Encode)] -pub struct DeviceInfo { +pub struct Credential { device_id: DeviceId, //. A DER-encoded public key public_key: DEREncodedPublicKey, } +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone, Copy)] +pub struct AttestationMeta { + pub(crate) device_id: DeviceId, + pub(crate) context: Cx, +} + #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Attestation { - pub(crate) credential_id: DeviceId, - pub(crate) context: Cx, + pub(crate) meta: AttestationMeta, pub(crate) authenticator_data: Vec, - pub(crate) attestation_data: Vec, + pub(crate) client_data: Vec, pub(crate) public_key: DEREncodedPublicKey, } -#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] -pub struct Credential { +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone, Copy)] +pub struct AssertionMeta { pub(crate) user_id: HashedUserId, pub(crate) context: Cx, +} + +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] +pub struct Assertion { + pub(crate) meta: AssertionMeta, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, pub(crate) signature: Vec, diff --git a/pass-webauthn/src/runtime_helpers.rs b/pass-webauthn/src/runtime_helpers.rs new file mode 100644 index 0000000..0bd76cc --- /dev/null +++ b/pass-webauthn/src/runtime_helpers.rs @@ -0,0 +1,39 @@ +use codec::Decode; +use frame_support::sp_runtime::traits::TrailingZeroInput; +use traits_authn::{AuthorityId, Challenge}; +use url::Url; + +pub fn find_challenge_from_client_data(client_data: Vec) -> Option { + get_from_json_then_map(client_data, "challenge", |challenge| { + base64::decode(challenge.as_bytes()).ok() + }) +} + +pub fn find_authority_id_from_client_data(client_data: Vec) -> Option { + get_from_json_then_map(client_data, "origin", |origin| { + Url::parse(&origin) + .ok()? + .domain()? + .split_once(".") + .map(|(authority_id, _)| authority_id.as_bytes().to_vec()) + }) +} + +pub fn get_from_json_then_map( + json: Vec, + key: &str, + map: impl FnOnce(String) -> Option>, +) -> Option +where + T: Decode, +{ + let json = String::from_utf8(json).ok()?; + + let value = json + .split(",") + .find_map(|kv| kv.contains(key).then_some(kv.split_once(":")?.1)) + .map(|v| v.trim().replace("\"", "")) + .and_then(map)?; + + Decode::decode(&mut TrailingZeroInput::new(value.as_ref())).ok() +} diff --git a/pass-webauthn/src/runtime_impls/assertion.rs b/pass-webauthn/src/runtime_impls/assertion.rs new file mode 100644 index 0000000..6d668b7 --- /dev/null +++ b/pass-webauthn/src/runtime_impls/assertion.rs @@ -0,0 +1,32 @@ +use super::*; +use traits_authn::{HashedUserId, UserChallengeResponse}; + +impl Assertion +where + Cx: Parameter, +{ + fn challenge(&self) -> Challenge { + find_challenge_from_client_data(self.client_data.clone()).unwrap_or_default() + } +} + +impl UserChallengeResponse for Assertion +where + Cx: Parameter + Copy + 'static, +{ + fn is_valid(&self) -> bool { + true + } + + fn used_challenge(&self) -> (Cx, Challenge) { + (self.meta.context, self.challenge()) + } + + fn authority(&self) -> AuthorityId { + find_authority_id_from_client_data(self.client_data.clone()).unwrap_or_default() + } + + fn user_id(&self) -> HashedUserId { + self.meta.user_id + } +} diff --git a/pass-webauthn/src/runtime_impls/attestation.rs b/pass-webauthn/src/runtime_impls/attestation.rs new file mode 100644 index 0000000..df5877d --- /dev/null +++ b/pass-webauthn/src/runtime_impls/attestation.rs @@ -0,0 +1,37 @@ +use super::*; + +impl Attestation +where + Cx: Parameter, +{ + fn challenge(&self) -> Challenge { + find_challenge_from_client_data(self.client_data.clone()).unwrap_or_default() + } +} + +#[cfg(any(feature = "runtime", test))] +impl DeviceChallengeResponse for Attestation +where + Cx: Parameter + Copy + 'static, +{ + // TODO: @pandres95, considering that DeviceChallengeResponse is used for creating a new + // authentication device, webauth_verify wouldn't work here. We need to implement a new + // verification method exclusively for credential creation. + fn is_valid(&self) -> bool { + true + } + + fn used_challenge(&self) -> (Cx, Challenge) { + (self.meta.context, self.challenge()) + } + + /// WebAuthn RpID should be a subdomain of the origin that is calling the create credentials request. + /// Therefore, `authority` should be a URL-safe name, so it can be allocated in a valid URL domain. + fn authority(&self) -> AuthorityId { + find_authority_id_from_client_data(self.client_data.clone()).unwrap_or_default() + } + + fn device_id(&self) -> &DeviceId { + &self.meta.device_id + } +} diff --git a/pass-webauthn/src/runtime_impls/credential.rs b/pass-webauthn/src/runtime_impls/credential.rs new file mode 100644 index 0000000..8685d33 --- /dev/null +++ b/pass-webauthn/src/runtime_impls/credential.rs @@ -0,0 +1,39 @@ +use super::*; + +use traits_authn::{util::VerifyCredential, Challenger}; +use verifier::webauthn_verify; + +use crate::{CxOf, Device}; + +#[cfg(any(feature = "runtime", test))] +impl From>> for Device +where + Ch: Challenger, + CxOf: Parameter + Copy + 'static, +{ + fn from(value: Attestation>) -> Self { + Device::new(Credential { + device_id: value.device_id().clone(), + public_key: value.public_key, + }) + } +} + +impl VerifyCredential> for Credential { + fn verify(&self, credential: &Assertion) -> Option<()> { + webauthn_verify( + &credential.authenticator_data, + &credential.client_data, + &credential.signature, + &self.public_key, + ) + .ok() + } +} + +#[cfg(any(feature = "runtime", test))] +impl AsRef for Credential { + fn as_ref(&self) -> &DeviceId { + &self.device_id + } +} diff --git a/pass-webauthn/src/runtime_impls/mod.rs b/pass-webauthn/src/runtime_impls/mod.rs new file mode 100644 index 0000000..83929a3 --- /dev/null +++ b/pass-webauthn/src/runtime_impls/mod.rs @@ -0,0 +1,8 @@ +pub(self) use frame_support::Parameter; +pub(self) use traits_authn::{AuthorityId, Challenge, DeviceChallengeResponse, DeviceId}; + +pub(self) use crate::{runtime_helpers::*, Assertion, Attestation, Credential}; + +pub mod assertion; +pub mod attestation; +pub mod credential; From 62733ee22c9eccaa5207f143c181716b2a19f2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:15:12 -0500 Subject: [PATCH 19/24] change(pass-webauthn): fix implementation of tests --- pass-webauthn/src/tests.rs | 24 +++++--- .../src/tests/authenticator_client.rs | 60 ++++++++++++------- 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index 53b3d33..a0361a9 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -94,14 +94,15 @@ impl pallet_pass::BenchmarkHelper for Helper { } fn device_attestation(_: traits_authn::DeviceId) -> pallet_pass::DeviceAttestationOf { - WebAuthnClient::new("https://helper.pass.int") + WebAuthnClient::new("https://pass_web.pass.int") .attestation(blake2_256(b"USER_ID"), System::block_number()) + .1 } fn credential(user_id: HashedUserId) -> pallet_pass::CredentialOf { let mut client = WebAuthnClient::new("https://helper.pass.int"); - let attestation = client.attestation(user_id, System::block_number()); - client.credential(attestation.credential_id.as_slice(), System::block_number()) + let (credential_id, _) = client.attestation(user_id, System::block_number()); + client.credential(credential_id.as_slice(), System::block_number()) } } @@ -117,7 +118,7 @@ fn new_test_ext() -> TestExt { t.execute_with(|| { System::set_block_number(1); }); - TestExt(t, WebAuthnClient::new("https://webauthn.pass.int")) + TestExt(t, WebAuthnClient::new("https://pass_web.pass.int")) } const USER: HashedUserId = s("the_user"); @@ -125,8 +126,17 @@ const USER: HashedUserId = s("the_user"); #[test] fn registration_fails_if_attestation_is_invalid() { new_test_ext().execute_with(|client| { - let mut attestation = client.attestation(USER, System::block_number()); - attestation.signature = [attestation.signature, b"Whoops!".to_vec()].concat(); + let (_, mut attestation) = client.attestation(USER, System::block_number()); + + // Alters "challenge", so this will fail + attestation.client_data = String::from_utf8(attestation.client_data) + .and_then(|client_data| { + Ok(client_data + .replace("challenge", "chellang") + .as_bytes() + .to_vec()) + }) + .expect("`client_data` is a buffer representation of a utf-8 encoded json"); assert_noop!( Pass::register(RuntimeOrigin::root(), USER, attestation), @@ -141,7 +151,7 @@ fn registration_works_if_attestation_is_valid() { assert_ok!(Pass::register( RuntimeOrigin::root(), USER, - client.attestation(USER, System::block_number()) + client.attestation(USER, System::block_number()).1 )); }) } diff --git a/pass-webauthn/src/tests/authenticator_client.rs b/pass-webauthn/src/tests/authenticator_client.rs index b162340..864036b 100644 --- a/pass-webauthn/src/tests/authenticator_client.rs +++ b/pass-webauthn/src/tests/authenticator_client.rs @@ -7,10 +7,11 @@ use passkey_authenticator::{Authenticator, MockUserValidationMethod}; use passkey_client::{Client, DefaultClientData}; use passkey_types::{ctap2::Aaguid, webauthn::*, Bytes, Passkey}; +use sp_io::hashing::blake2_256; use traits_authn::{Challenger, HashedUserId}; use url::Url; -use crate::DEREncodedPublicKey; +use crate::{AssertionMeta, DEREncodedPublicKey}; use super::{BlockChallenger, Test}; @@ -37,7 +38,7 @@ impl WebAuthnClient { &mut self, user_id: HashedUserId, challenge: impl Into, - ) -> Result<(Vec, DEREncodedPublicKey), ()> { + ) -> Result<(Vec, Vec, Vec, DEREncodedPublicKey), ()> { let creation_options = CredentialCreationOptions { public_key: PublicKeyCredentialCreationOptions { rp: PublicKeyCredentialRpEntity { @@ -72,7 +73,6 @@ impl WebAuthnClient { )) .map_err(|_| ())?; - // Extracting required fields let public_key: DEREncodedPublicKey = result .response .public_key @@ -82,14 +82,19 @@ impl WebAuthnClient { }) .ok_or(())?; - Ok((result.raw_id.into(), public_key)) + Ok(( + result.raw_id.into(), + result.response.authenticator_data.into(), + result.response.client_data_json.into(), + public_key, + )) } pub fn authenticate_credential_sync( &mut self, credential_id: impl Into, challenge: impl Into, - ) -> Result<(Vec, Vec, Vec), ()> { + ) -> Result<(Vec, Vec, Vec, Vec), ()> { let request_options = CredentialRequestOptions { public_key: PublicKeyCredentialRequestOptions { challenge: challenge.into(), // Provided as input @@ -117,50 +122,59 @@ impl WebAuthnClient { .map_err(|_| ())?; // Extracting required fields + let user_handle = result + .response + .user_handle + .map(|user_handle| user_handle.into()) + .ok_or(())?; let authenticator_data = result.response.authenticator_data.to_vec(); let client_data = result.response.client_data_json.to_vec(); let signature = result.response.signature.to_vec(); - Ok((authenticator_data, client_data, signature)) + Ok((user_handle, authenticator_data, client_data, signature)) } pub fn attestation( &mut self, user_id: HashedUserId, context: BlockNumberFor, - ) -> crate::Attestation> { + ) -> (Vec, crate::Attestation>) { let challenge = BlockChallenger::generate(&context); - let (credential_id, public_key) = self + let (credential_id, authenticator_data, client_data, public_key) = self .create_credential_sync(user_id, challenge.as_slice()) .expect("Failed creating credential"); - let (authenticator_data, client_data, signature) = self - .authenticate_credential_sync(credential_id, challenge.as_slice()) - .expect("Failed retrieving credential"); - crate::Attestation { - credential_id, - context, - authenticator_data, - client_data, - public_key, - signature, - } + ( + credential_id.clone(), + crate::Attestation { + meta: crate::AttestationMeta { + device_id: blake2_256(&credential_id), + context, + }, + authenticator_data, + client_data, + public_key, + }, + ) } pub fn credential( &mut self, credential_id: impl Into, context: BlockNumberFor, - ) -> crate::Credential> { + ) -> crate::Assertion> { let challenge = BlockChallenger::generate(&context); - let (authenticator_data, client_data, signature) = self + let (user_handle, authenticator_data, client_data, signature) = self .authenticate_credential_sync(credential_id, challenge.as_slice()) .expect("Failed retrieving credential"); - crate::Credential { - context, + crate::Assertion { + meta: AssertionMeta { + user_id: Decode::decode(&mut TrailingZeroInput::new(&user_handle)).expect("`user_handle` corresponds to the `user_id` inserted when creating credential; qed"), + context, + }, authenticator_data, client_data, signature, From 0a2d029de4c28948fcee2df178772f4918cf4223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:45:45 -0500 Subject: [PATCH 20/24] fix(pass-webauthn): `challenge` should be decoded using `BASE654_URL_SAFE_NO_PAD` engine --- pass-webauthn/src/runtime_helpers.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pass-webauthn/src/runtime_helpers.rs b/pass-webauthn/src/runtime_helpers.rs index 0bd76cc..ee65eb0 100644 --- a/pass-webauthn/src/runtime_helpers.rs +++ b/pass-webauthn/src/runtime_helpers.rs @@ -1,11 +1,14 @@ use codec::Decode; use frame_support::sp_runtime::traits::TrailingZeroInput; + use traits_authn::{AuthorityId, Challenge}; + +use base64::prelude::BASE64_URL_SAFE_NO_PAD; use url::Url; pub fn find_challenge_from_client_data(client_data: Vec) -> Option { get_from_json_then_map(client_data, "challenge", |challenge| { - base64::decode(challenge.as_bytes()).ok() + base64::decode_engine(challenge.as_bytes(), &BASE64_URL_SAFE_NO_PAD).ok() }) } From b2e290c9c38010c78d2b074821a2e319e23eb24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:46:11 -0500 Subject: [PATCH 21/24] fix(pass-webauthn): adjust tests to comply mock's requirements --- pass-webauthn/src/tests.rs | 124 +++++++++++++----- .../src/tests/authenticator_client.rs | 6 +- 2 files changed, 93 insertions(+), 37 deletions(-) diff --git a/pass-webauthn/src/tests.rs b/pass-webauthn/src/tests.rs index a0361a9..2ec587b 100644 --- a/pass-webauthn/src/tests.rs +++ b/pass-webauthn/src/tests.rs @@ -94,15 +94,15 @@ impl pallet_pass::BenchmarkHelper for Helper { } fn device_attestation(_: traits_authn::DeviceId) -> pallet_pass::DeviceAttestationOf { - WebAuthnClient::new("https://pass_web.pass.int") + WebAuthnClient::new("https://pass_web.pass.int", 1) .attestation(blake2_256(b"USER_ID"), System::block_number()) .1 } fn credential(user_id: HashedUserId) -> pallet_pass::CredentialOf { - let mut client = WebAuthnClient::new("https://helper.pass.int"); + let mut client = WebAuthnClient::new("https://helper.pass.int", 2); let (credential_id, _) = client.attestation(user_id, System::block_number()); - client.credential(credential_id.as_slice(), System::block_number()) + client.assertion(credential_id.as_slice(), System::block_number()) } } @@ -113,45 +113,101 @@ impl TestExt { } } -fn new_test_ext() -> TestExt { +fn new_test_ext(times: usize) -> TestExt { let mut t = sp_io::TestExternalities::default(); t.execute_with(|| { System::set_block_number(1); }); - TestExt(t, WebAuthnClient::new("https://pass_web.pass.int")) + TestExt(t, WebAuthnClient::new("https://pass_web.pass.int", times)) } const USER: HashedUserId = s("the_user"); -#[test] -fn registration_fails_if_attestation_is_invalid() { - new_test_ext().execute_with(|client| { - let (_, mut attestation) = client.attestation(USER, System::block_number()); - - // Alters "challenge", so this will fail - attestation.client_data = String::from_utf8(attestation.client_data) - .and_then(|client_data| { - Ok(client_data - .replace("challenge", "chellang") - .as_bytes() - .to_vec()) - }) - .expect("`client_data` is a buffer representation of a utf-8 encoded json"); - - assert_noop!( - Pass::register(RuntimeOrigin::root(), USER, attestation), - pallet_pass::Error::::DeviceAttestationInvalid, - ); - }) +mod attestation { + use super::*; + + #[test] + fn registration_fails_if_attestation_is_invalid() { + new_test_ext(1).execute_with(|client| { + let (_, mut attestation) = client.attestation(USER, System::block_number()); + + // Alters "challenge", so this will fail + attestation.client_data = String::from_utf8(attestation.client_data) + .and_then(|client_data| { + Ok(client_data + .replace("challenge", "chellang") + .as_bytes() + .to_vec()) + }) + .expect("`client_data` is a buffer representation of a utf-8 encoded json"); + + assert_noop!( + Pass::register(RuntimeOrigin::root(), USER, attestation), + pallet_pass::Error::::DeviceAttestationInvalid, + ); + }) + } + + #[test] + fn registration_works_if_attestation_is_valid() { + new_test_ext(1).execute_with(|client| { + assert_ok!(Pass::register( + RuntimeOrigin::root(), + USER, + client.attestation(USER, System::block_number()).1 + )); + }) + } } -#[test] -fn registration_works_if_attestation_is_valid() { - new_test_ext().execute_with(|client| { - assert_ok!(Pass::register( - RuntimeOrigin::root(), - USER, - client.attestation(USER, System::block_number()).1 - )); - }) +mod assertion { + use traits_authn::DeviceChallengeResponse; + + use super::*; + + #[test] + fn authentication_fails_if_credentials_are_invalid() { + new_test_ext(2).execute_with(|client| { + let (credential_id, attestation) = client.attestation(USER, System::block_number()); + + assert_ok!(Pass::register( + RuntimeOrigin::root(), + USER, + attestation.clone() + )); + + let mut assertion = client.assertion(credential_id, System::block_number()); + assertion.signature = [assertion.signature, b"Whoops".to_vec()].concat(); + + assert_noop!( + Pass::authenticate( + RuntimeOrigin::signed(1), + *(attestation.device_id()), + assertion, + None + ), + pallet_pass::Error::::CredentialInvalid + ); + }) + } + + #[test] + fn authentication_works_if_credentials_are_valid() { + new_test_ext(2).execute_with(|client| { + let (credential_id, attestation) = client.attestation(USER, System::block_number()); + + assert_ok!(Pass::register( + RuntimeOrigin::root(), + USER, + attestation.clone() + )); + + assert_ok!(Pass::authenticate( + RuntimeOrigin::signed(1), + *(attestation.device_id()), + client.assertion(credential_id, System::block_number()), + None + )); + }) + } } diff --git a/pass-webauthn/src/tests/authenticator_client.rs b/pass-webauthn/src/tests/authenticator_client.rs index 864036b..b496c3d 100644 --- a/pass-webauthn/src/tests/authenticator_client.rs +++ b/pass-webauthn/src/tests/authenticator_client.rs @@ -21,12 +21,12 @@ pub struct WebAuthnClient { } impl WebAuthnClient { - pub fn new(origin: &'static str) -> Self { + pub fn new(origin: &'static str, times: usize) -> Self { // Create Authenticator let authenticator = Authenticator::new( Aaguid::new_empty(), None, - MockUserValidationMethod::verified_user(1), + MockUserValidationMethod::verified_user(times), ); Self { origin: Url::parse(origin).expect("invalid url provided"), @@ -159,7 +159,7 @@ impl WebAuthnClient { ) } - pub fn credential( + pub fn assertion( &mut self, credential_id: impl Into, context: BlockNumberFor, From ddbd57a1983f36209882fd5cac3484f71e292b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:47:05 -0500 Subject: [PATCH 22/24] fix: make clippy happy --- pass-webauthn/src/runtime_impls/credential.rs | 2 +- pass-webauthn/src/runtime_impls/mod.rs | 6 +++--- verifier/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pass-webauthn/src/runtime_impls/credential.rs b/pass-webauthn/src/runtime_impls/credential.rs index 8685d33..9b65c92 100644 --- a/pass-webauthn/src/runtime_impls/credential.rs +++ b/pass-webauthn/src/runtime_impls/credential.rs @@ -13,7 +13,7 @@ where { fn from(value: Attestation>) -> Self { Device::new(Credential { - device_id: value.device_id().clone(), + device_id: *value.device_id(), public_key: value.public_key, }) } diff --git a/pass-webauthn/src/runtime_impls/mod.rs b/pass-webauthn/src/runtime_impls/mod.rs index 83929a3..f19a8eb 100644 --- a/pass-webauthn/src/runtime_impls/mod.rs +++ b/pass-webauthn/src/runtime_impls/mod.rs @@ -1,7 +1,7 @@ -pub(self) use frame_support::Parameter; -pub(self) use traits_authn::{AuthorityId, Challenge, DeviceChallengeResponse, DeviceId}; +use frame_support::Parameter; +use traits_authn::{AuthorityId, Challenge, DeviceChallengeResponse, DeviceId}; -pub(self) use crate::{runtime_helpers::*, Assertion, Attestation, Credential}; +use crate::{runtime_helpers::*, Assertion, Attestation, Credential}; pub mod assertion; pub mod attestation; diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index fe661ce..3eb5776 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -73,7 +73,7 @@ pub fn webauthn_verify( let client_data_hash: [u8; 32] = Sha256::digest(client_data_json).into(); // Step 2: Concatenate authenticator data and client data hash - let message = vec![authenticator_data, &client_data_hash].concat(); + let message = [authenticator_data, &client_data_hash].concat(); // Step 3: Extract public key from DER format let public_key: PublicKey = From 7c4a9e26f3dd128bdafc09559e2a2f4e8d44786c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 22:55:22 -0500 Subject: [PATCH 23/24] change(pass-webauthn): trim unused dependencies --- Cargo.lock | 1 - Cargo.toml | 1 - pass-webauthn/Cargo.toml | 4 +--- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffc2ead..ac75cee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2301,7 +2301,6 @@ dependencies = [ "passkey-types", "public-suffix", "scale-info", - "serde_json", "simple-base64", "sp-io", "url", diff --git a/Cargo.toml b/Cargo.toml index 39c4413..6f7adc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ passkey-types = { version = "0.3.0", default-features = false, features = [ public-suffix = "0.1" rand = "0.8.5" sha2 = { version = "0.10.8", default-features = false } -serde_json = { version = "1.0.128", default-features = false } url = "2.5.2" # FRAME diff --git a/pass-webauthn/Cargo.toml b/pass-webauthn/Cargo.toml index 1453022..950bd34 100644 --- a/pass-webauthn/Cargo.toml +++ b/pass-webauthn/Cargo.toml @@ -14,7 +14,6 @@ frame-support.optional = true scale-info.workspace = true traits-authn.workspace = true url.workspace = true -sp-io.workspace = true verifier.workspace = true [dev-dependencies] @@ -27,7 +26,7 @@ passkey-authenticator.workspace = true passkey-client.workspace = true passkey-types.workspace = true public-suffix.workspace = true -serde_json.workspace = true +sp-io.workspace = true [features] default = ["std", "runtime"] @@ -47,7 +46,6 @@ std = [ "pallet-balances/std", "pallet-pass/std", "scale-info/std", - "serde_json/std", "sp-io/std", "traits-authn/std", "verifier/std", From 99b86b8e9b5de9ef864c398e6e73cb34acd4546f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Tue, 15 Oct 2024 13:53:57 -0500 Subject: [PATCH 24/24] change(pass-webauthn): perf improvements over `get_from_json_then_map` --- pass-webauthn/src/runtime_helpers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pass-webauthn/src/runtime_helpers.rs b/pass-webauthn/src/runtime_helpers.rs index ee65eb0..b44aa82 100644 --- a/pass-webauthn/src/runtime_helpers.rs +++ b/pass-webauthn/src/runtime_helpers.rs @@ -25,7 +25,7 @@ pub fn find_authority_id_from_client_data(client_data: Vec) -> Option( json: Vec, key: &str, - map: impl FnOnce(String) -> Option>, + map: impl FnOnce(&str) -> Option>, ) -> Option where T: Decode, @@ -35,7 +35,7 @@ where let value = json .split(",") .find_map(|kv| kv.contains(key).then_some(kv.split_once(":")?.1)) - .map(|v| v.trim().replace("\"", "")) + .map(|v| v.trim_matches(|c: char| c.eq(&' ') || c.eq(&'"'))) .and_then(map)?; Decode::decode(&mut TrailingZeroInput::new(value.as_ref())).ok()