From 62ce00088ca1408ed2fabae0a1602902a9a0ed8b Mon Sep 17 00:00:00 2001 From: James Ebert Date: Tue, 10 Dec 2024 23:41:53 -0800 Subject: [PATCH 1/2] Adjust Rust toolchain, clippy, and minor ci changes (#1311) * chore: adjust toolchain, clippy, and ci Signed-off-by: James Ebert * chore: adjust clippy instructions Signed-off-by: James Ebert * chore: adjust justfile, update clippy ci tasks Signed-off-by: James Ebert * chore: remove unstable feature code formatting rules Signed-off-by: James Ebert --------- Signed-off-by: James Ebert --- .github/actions/setup-codecov-rust/action.yml | 31 ---------- .github/workflows/main.yml | 57 ++++++------------- .rustfmt.toml | 22 ++++--- Cargo.toml | 1 + README.md | 49 +++++++++++----- .../protocols/cred_issuance/v1/mod.rs | 17 +++--- .../protocols/cred_issuance/v2/mod.rs | 17 +++--- aries/wrappers/uniffi-aries-vcx/README.md | 2 +- codecov.yml | 4 -- .../src/peer_did/numalgos/numalgo2/helpers.rs | 14 ++--- justfile | 12 ++-- rust-toolchain.toml | 2 + 12 files changed, 94 insertions(+), 134 deletions(-) delete mode 100644 .github/actions/setup-codecov-rust/action.yml delete mode 100644 codecov.yml create mode 100644 rust-toolchain.toml diff --git a/.github/actions/setup-codecov-rust/action.yml b/.github/actions/setup-codecov-rust/action.yml deleted file mode 100644 index a4c4620230..0000000000 --- a/.github/actions/setup-codecov-rust/action.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: "setup-codecov-rust" -description: 'Setup host environment for measuring rust code coverage' - -inputs: - skip-docker-setup: - description: 'If true, skip spinning up docker containers' - required: false - default: false - -runs: - using: "composite" - steps: - - name: Install nightly 1.72 - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly-2023-08-24 - override: true - - uses: Swatinem/rust-cache@v2 - - name: "Install dependencies" - shell: bash - run: | - sudo apt-get update -y - sudo apt-get install -y libsodium-dev libssl-dev libzmq3-dev - cargo install grcov --version 0.8.9 - - name: "Setup environment" - if: ${{ inputs.skip-docker-setup != 'true' }} - shell: bash - run: | - docker run --rm -d --name mysql --network host -e MYSQL_ROOT_PASSWORD=mysecretpassword mysql:5.7.35 - docker run --rm -d --name indypool --network host ${{ env.DOCKER_IMAGE_POOL }} - sleep 5 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 276634dd93..339ae53cbe 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ env: DOCKER_REPO_LOCAL_VDRPROXY: vdrproxy DOCKER_REPO_LOCAL_AATH: aath-backchannel - RUST_TOOLCHAIN_VERSION: 1.79.0 + RUST_TOOLCHAIN_VERSION: 1.79 NODE_VERSION: 18.x jobs: @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2023-05-08 + toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} components: rustfmt override: true - name: "Install just" @@ -97,11 +97,8 @@ jobs: echo "DOCKER_IMG_CACHED_VDRPROXY ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }}" echo "DOCKER_IMG_CACHED_AATH ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_AATH }}" - workspace_clippy: + clippy: runs-on: ubuntu-20.04 - strategy: - matrix: - wallet: ["askar_wallet"] steps: - name: "Git checkout" uses: actions/checkout@v3 @@ -117,29 +114,7 @@ jobs: sudo apt-get install -y libsodium-dev libssl-dev libzmq3-dev sudo snap install --edge --classic just - name: "Verify clippy across the entire workspace" - run: just clippy-workspace ${{ matrix.wallet }} - - aries_vcx_clippy: - runs-on: ubuntu-20.04 - strategy: - matrix: - backend: ["anoncreds,askar_wallet", "vdr_proxy_ledger,askar_wallet"] - steps: - - name: "Git checkout" - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }} - default: true - components: clippy - - name: "Install dependencies" - shell: bash - run: | - sudo apt-get update -y - sudo apt-get install -y libsodium-dev libssl-dev libzmq3-dev - sudo snap install --edge --classic just - - name: "Verify clippy across the entire workspace with default features" - run: just clippy-aries-vcx ${{ matrix.backend }} + run: just clippy ########################################################################################## ############################## DOCKER BUILD ########################################## @@ -150,7 +125,7 @@ jobs: permissions: contents: read packages: write - needs: [ workflow-setup ] + needs: [workflow-setup] if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }} @@ -183,7 +158,7 @@ jobs: permissions: contents: read packages: write - needs: [ workflow-setup ] + needs: [workflow-setup] if: ${{ needs.workflow-setup.outputs.IS_MAIN_BRANCH == 'true' }} env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_AATH }} @@ -218,7 +193,7 @@ jobs: permissions: contents: read packages: write - needs: [ workflow-setup, build-docker-vdrproxy ] + needs: [workflow-setup, build-docker-vdrproxy] if: ${{ needs.workflow-setup.outputs.SKIP_CI != 'true' }} env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_VDRPROXY }} @@ -249,7 +224,7 @@ jobs: permissions: contents: read packages: write - needs: [ workflow-setup, build-docker-aath-backchannel ] + needs: [workflow-setup, build-docker-aath-backchannel] if: ${{ needs.workflow-setup.outputs.RELEASE == 'true' || needs.workflow-setup.outputs.PRERELEASE == 'true' }} env: DOCKER_IMG_CACHED: ${{ needs.workflow-setup.outputs.DOCKER_IMG_CACHED_AATH }} @@ -391,14 +366,14 @@ jobs: breakingLabels: backwards-incompatible,breaking deprecatedLabels: deprecated headerLabel: "# Changelog" - breakingLabel: '### Breaking changes' - enhancementLabel: '### Enhancements' - bugsLabel: '### Bug fixes' - deprecatedLabel: '### Deprecations' - removedLabel: '### Removals' - securityLabel: '### Security fixes' - issuesLabel: '### Other issues' - prLabel: '### Other pull requests' + breakingLabel: "### Breaking changes" + enhancementLabel: "### Enhancements" + bugsLabel: "### Bug fixes" + deprecatedLabel: "### Deprecations" + removedLabel: "### Removals" + securityLabel: "### Security fixes" + issuesLabel: "### Other issues" + prLabel: "### Other pull requests" addSections: '{"ci":{"prefix":"### CI changes","labels":["ci"]},"wrappers":{"prefix":"### Wrapper changes","labels":["wrappers"]},"agents":{"prefix":"### Changes to agents","labels":["agents"]},"features":{"prefix":"### Features","labels":["features"]},"hotfix":{"prefix":"### Hotfixes","labels":["hotfix"]},"security":{"prefix":"### Security fixes","labels":["security"]},"refactoring":{"prefix":"### Refactoring","labels":["refactoring"]},"tests":{"prefix":"### Tests","labels":["tests"]},"update":{"prefix":"### Updates","labels":["update"]}}' excludeTagsRegex: '^((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))+)?)$' diff --git a/.rustfmt.toml b/.rustfmt.toml index 7227a01f05..e8d3747f08 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -3,12 +3,16 @@ # "rust-analyzer.rustfmt.extraArgs": [ # "+nightly" # ], -unstable_features = true -group_imports = "StdExternalCrate" -imports_granularity = "Crate" -format_code_in_doc_comments = true -format_macro_bodies = true -format_macro_matchers = true -format_strings = true -comment_width = 100 -wrap_comments = true \ No newline at end of file + +# The following have been commented out as we are no longer targeting nightly, +# therefore these are no longer accessible: +# +# unstable_features = true +# group_imports = "StdExternalCrate" +# imports_granularity = "Crate" +# format_code_in_doc_comments = true +# format_macro_bodies = true +# format_macro_matchers = true +# format_strings = true +# comment_width = 100 +# wrap_comments = true diff --git a/Cargo.toml b/Cargo.toml index 5a604c6592..42b60279c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ authors = [ description = "Library to work with Aries protocols & collection of supporting components" license = "Apache-2.0" edition = "2021" +rust-version = "1.79" [profile.release] debug = 0 diff --git a/README.md b/README.md index bf22237b99..cbaa08604d 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,13 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Join the chat at https://chat.hyperledger.org/channel/aries](https://img.shields.io/badge/Chat%20on-Hyperledger%20Chat-blue)](https://chat.hyperledger.org/channel/aries) -The repository contains Rust crates to build +The repository contains Rust crates to build + - [Aries](https://github.com/hyperledger/aries-rfcs/) based applications (mobile, server, anything, ...), - [DIDComm](https://didcomm.org/) related components. ## Aries implementation + - [`aries_vcx`](aries/aries_vcx) - Library implementing DIDComm protocols, with focus on verifiable credential issuance and verification. - [`messages`](aries/messages) - Library for building and parsing Aries (DIDComm v1) messages. - [`aries_vcx_anoncreds`](aries/aries_vcx_anoncreds) - Interfaces for interaction with credentials. @@ -17,28 +19,45 @@ The repository contains Rust crates to build - [`agents`](aries/agents) - Aries agents built on top of `aries_vcx`. ## Did document implementation - - [`did_doc`](did_core/did_doc) - Building and parsing [DID Documents](https://w3c.github.io/did-core/) + +- [`did_doc`](did_core/did_doc) - Building and parsing [DID Documents](https://w3c.github.io/did-core/) ## Did methods implementation - - [`did_parser`](did_core/did_parser_nom) - Building and parsing [DIDs](https://w3c.github.io/did-core/) - - [`did_peer`](did_core/did_methods/did_peer) - https://identity.foundation/peer-did-method-spec/ - - [`did_sov`](did_core/did_methods/did_resolver_sov) - https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html - - [`did_cheqd`](did_core/did_methods/did_cheqd) - https://docs.cheqd.io/product/architecture/adr-list/adr-001-cheqd-did-method - - [`did_web`](did_core/did_methods/did_resolver_web) - https://w3c-ccg.github.io/did-method-web/ - - [`did_key`](did_core/did_methods/did_key) - https://w3c-ccg.github.io/did-method-key/ - - [`did_jwk`](did_core/did_methods/did_jwk) - https://github.com/quartzjer/did-jwk/blob/main/spec.md + +- [`did_parser`](did_core/did_parser_nom) - Building and parsing [DIDs](https://w3c.github.io/did-core/) +- [`did_peer`](did_core/did_methods/did_peer) - https://identity.foundation/peer-did-method-spec/ +- [`did_sov`](did_core/did_methods/did_resolver_sov) - https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html +- [`did_cheqd`](did_core/did_methods/did_cheqd) - https://docs.cheqd.io/product/architecture/adr-list/adr-001-cheqd-did-method +- [`did_web`](did_core/did_methods/did_resolver_web) - https://w3c-ccg.github.io/did-method-web/ +- [`did_key`](did_core/did_methods/did_key) - https://w3c-ccg.github.io/did-method-key/ +- [`did_jwk`](did_core/did_methods/did_jwk) - https://github.com/quartzjer/did-jwk/blob/main/spec.md # Contact + Do you have a question ❓Are you considering using our components? πŸš€ We'll be excited to hear from you. πŸ‘‹ There's 2 best way to reach us: + - Leave us message on `aries-vcx` [discord](https://discord.com/channels/905194001349627914/955480822675308604) channel. - Join our Zoom community calls. Biweekly Tuesdays @ 11:00 pm UTC via Zoom, find more details on [wiki](https://wiki.hyperledger.org/display/ARIES/Community+calls) ## Versioning & releases - - Crates are not yet published on crates.io. You can consume crates as github-type Cargo dependency. - - All releases have currently major version `0` - - We bump minor version on releases containing new features, significant refactors or breaking changes. - - We bump patch version if release only contains fixes or smaller refactoring. - - See [releases](https://github.com/hyperledger/aries-vcx/releases) page. - - Crates are known to be stable with atleast Rust version 1.79 + +- Crates are not yet published on crates.io. You can consume crates as github-type Cargo dependency. +- All releases have currently major version `0` + - We bump minor version on releases containing new features, significant refactors or breaking changes. + - We bump patch version if release only contains fixes or smaller refactoring. +- See [releases](https://github.com/hyperledger/aries-vcx/releases) page. +- Crates are known to be stable with atleast Rust version 1.79 + +# Contributions + +Contributions are very welcome! If you have questions or issues, please let us know on [Discord](https://chat.hyperledger.org/channel/aries) or at our [bi-weekly community call](https://wiki.hyperledger.org/display/ARIES/Community+calls). + +For contributions, please run `clippy` and format prior to creating a PR. This can be done via `just`: + +``` +cargo install just +just clippy +just fmt +``` diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v1/mod.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v1/mod.rs index 95b75f4194..feb1b0df59 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v1/mod.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v1/mod.rs @@ -63,16 +63,15 @@ impl DelayedSerde for CredentialIssuanceV1 { D: Deserializer<'de>, { let (protocol, kind_str) = msg_type; - let kind = match protocol { - CredentialIssuanceKind::V1(CredentialIssuanceTypeV1::V1_0(kind)) => { - kind.kind_from_str(kind_str) - } - CredentialIssuanceKind::V2(_) => { - return Err(D::Error::custom( + let kind = + match protocol { + CredentialIssuanceKind::V1(CredentialIssuanceTypeV1::V1_0(kind)) => { + kind.kind_from_str(kind_str) + } + CredentialIssuanceKind::V2(_) => return Err(D::Error::custom( "Cannot deserialize issue-credential-v2 message type into issue-credential-v1", - )) - } - }; + )), + }; match kind.map_err(D::Error::custom)? { CredentialIssuanceTypeV1_0::OfferCredential => { diff --git a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/mod.rs b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/mod.rs index 200ff03b91..2253562b76 100644 --- a/aries/messages/src/msg_fields/protocols/cred_issuance/v2/mod.rs +++ b/aries/messages/src/msg_fields/protocols/cred_issuance/v2/mod.rs @@ -62,16 +62,15 @@ impl DelayedSerde for CredentialIssuanceV2 { D: Deserializer<'de>, { let (protocol, kind_str) = msg_type; - let kind = match protocol { - CredentialIssuanceKind::V2(CredentialIssuanceTypeV2::V2_0(kind)) => { - kind.kind_from_str(kind_str) - } - CredentialIssuanceKind::V1(_) => { - return Err(D::Error::custom( + let kind = + match protocol { + CredentialIssuanceKind::V2(CredentialIssuanceTypeV2::V2_0(kind)) => { + kind.kind_from_str(kind_str) + } + CredentialIssuanceKind::V1(_) => return Err(D::Error::custom( "Cannot deserialize issue-credential-v1 message type into issue-credential-v2", - )) - } - }; + )), + }; match kind.map_err(D::Error::custom)? { CredentialIssuanceTypeV2_0::OfferCredential => { diff --git a/aries/wrappers/uniffi-aries-vcx/README.md b/aries/wrappers/uniffi-aries-vcx/README.md index 22c06d00bd..d85d469228 100644 --- a/aries/wrappers/uniffi-aries-vcx/README.md +++ b/aries/wrappers/uniffi-aries-vcx/README.md @@ -38,7 +38,7 @@ eg. for Android ARM64 on host linux platform. rustup target add aarch64-linux-android ``` -More documentation can be found [here](https://rust-lang.github.io/rustup/cross-compilation.html). Information on supported platforms can be found [here](https://doc.rust-lang.org/nightly/rustc/platform-support.html). +More documentation can be found [here](https://rust-lang.github.io/rustup/cross-compilation.html). Information on supported platforms can be found [here](https://doc.rust-lang.org/stable/rustc/platform-support.html). 3. `cargo-ndk` requires Android NDK to be set up on the host machine. The recommended way of doing this is using Android Studio as described [here](https://developer.android.com/studio/projects/install-ndk#default-version). diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index f158160d61..0000000000 --- a/codecov.yml +++ /dev/null @@ -1,4 +0,0 @@ -fixes: - - "/home/indy/aries-vcx/::aries-vcx/" -ignore: - - "libvcx" diff --git a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs index 1e19b3b089..b6a47a6eed 100644 --- a/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs +++ b/did_core/did_methods/did_peer/src/peer_did/numalgos/numalgo2/helpers.rs @@ -144,11 +144,10 @@ mod tests { #[test] fn test_process_elements_with_multiple_elements() { - let did: Did = - "did:peer:2.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.\ + let did: Did = "did:peer:2.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.\ SeyJpZCI6IiNzZXJ2aWNlLTAiLCJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCJ9" - .parse() - .unwrap(); + .parse() + .unwrap(); let did_doc = diddoc_from_peerdid2_elements( DidDocument::new(did.clone()), @@ -164,12 +163,11 @@ mod tests { #[test] fn test_process_elements_error_on_invalid_element() { - let did: Did = - "did:peer:2.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.\ + let did: Did = "did:peer:2.Vz6MkqRYqQiSgvZQdnBytw86Qbs2ZWUkGv22od935YF4s8M7V.\ SeyJpZCI6IiNzZXJ2aWNlLTAiLCJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9lbmRwb2ludCJ9.\ Xinvalid" - .parse() - .unwrap(); + .parse() + .unwrap(); match diddoc_from_peerdid2_elements( DidDocument::new(did.clone()), diff --git a/justfile b/justfile index 609f68a7b5..c8894595e3 100644 --- a/justfile +++ b/justfile @@ -2,17 +2,15 @@ default: just --list fmt: - cargo +nightly-2023-05-08 fmt + cargo fmt fmt-check: - cargo +nightly-2023-05-08 fmt --check + cargo fmt --check -clippy-workspace wallet: - cargo clippy --examples --tests --no-default-features -F anoncreds,vdr_proxy_ledger,legacy_proof,{{wallet}} - -clippy-aries-vcx features: - cargo clippy -p aries_vcx --features legacy_proof --features {{features}} --no-default-features +clippy: + cargo clippy --examples --tests --all-features +# The following need review: check-workspace: cargo check --tests --all-features diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000000..c6e4d7d503 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.79" From 78dce279937b960fd08ab24471d0e9f363e65852 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Wed, 11 Dec 2024 07:51:12 -0800 Subject: [PATCH 2/2] Simplify DIDComm unpack(), use `Key` instead of `String` (#1310) * feat: adjusted encryption envelope to use key references instead of base58 strings Signed-off-by: James Ebert * feat: refactor didcomm unpack() to be streamlined and to use keys instead of strings Signed-off-by: James Ebert * chore: adjust iterator Signed-off-by: James Ebert * revert iter() change Signed-off-by: James Ebert * chore: clippy Signed-off-by: James Ebert * chore: improve borrowing Signed-off-by: James Ebert * chore: clippy tests Signed-off-by: James Ebert --------- Signed-off-by: James Ebert --- .../src/controllers/didcomm.rs | 23 +- aries/aries_vcx/src/utils/didcomm_utils.rs | 44 ++-- .../src/utils/encryption_envelope.rs | 245 +++++++++--------- aries/aries_vcx/tests/test_connection.rs | 25 +- aries/aries_vcx/tests/test_did_exchange.rs | 11 +- aries/misc/test_utils/src/devsetup.rs | 2 +- did_core/public_key/src/error.rs | 4 + did_core/public_key/src/key.rs | 18 ++ did_core/public_key/src/key_type.rs | 17 ++ 9 files changed, 212 insertions(+), 177 deletions(-) diff --git a/aries/agents/aath-backchannel/src/controllers/didcomm.rs b/aries/agents/aath-backchannel/src/controllers/didcomm.rs index 6ea4cd1856..5596076678 100644 --- a/aries/agents/aath-backchannel/src/controllers/didcomm.rs +++ b/aries/agents/aath-backchannel/src/controllers/didcomm.rs @@ -215,9 +215,10 @@ impl HarnessAgent { } pub async fn receive_message(&self, payload: Vec) -> HarnessResult { - let (message, sender_vk, recipient_vk) = EncryptionEnvelope::anon_unpack_aries_msg( + let (message, sender_vk, recipient_vk) = EncryptionEnvelope::unpack_aries_msg( self.aries_agent.wallet().as_ref(), - payload.clone(), + &payload, + &None, ) .await?; let sender_vk = sender_vk.ok_or_else(|| { @@ -245,7 +246,10 @@ impl HarnessAgent { } } AriesMessage::TrustPing(TrustPing::Ping(msg)) => { - let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?; + let connection_id = self + .aries_agent + .connections() + .get_by_sender_vk(sender_vk.base58())?; self.aries_agent .connections() .process_trust_ping(msg, &connection_id) @@ -253,14 +257,21 @@ impl HarnessAgent { } AriesMessage::Connection(msg) => self.handle_connection_msg(msg).await?, AriesMessage::CredentialIssuance(msg) => { - let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?; + let connection_id = self + .aries_agent + .connections() + .get_by_sender_vk(sender_vk.base58())?; self.handle_issuance_msg(msg, &connection_id).await? } AriesMessage::DidExchange(msg) => { - self.handle_did_exchange_msg(msg, recipient_vk).await? + self.handle_did_exchange_msg(msg, recipient_vk.base58()) + .await? } AriesMessage::PresentProof(msg) => { - let connection_id = self.aries_agent.connections().get_by_sender_vk(sender_vk)?; + let connection_id = self + .aries_agent + .connections() + .get_by_sender_vk(sender_vk.base58())?; self.handle_presentation_msg(msg, &connection_id).await? } m => { diff --git a/aries/aries_vcx/src/utils/didcomm_utils.rs b/aries/aries_vcx/src/utils/didcomm_utils.rs index 50ce4efc0f..1845613a85 100644 --- a/aries/aries_vcx/src/utils/didcomm_utils.rs +++ b/aries/aries_vcx/src/utils/didcomm_utils.rs @@ -36,7 +36,7 @@ pub(crate) fn resolve_service_key_to_typed_key( /// Resolves the first ed25519 base58 public key (a.k.a. verkey) within the DIDDocuments key /// agreement keys. Useful for resolving keys that can be used for packing DIDCommV1 messages. -pub fn resolve_ed25519_base58_key_agreement(did_document: &DidDocument) -> VcxResult { +pub fn resolve_ed25519_key_agreement(did_document: &DidDocument) -> VcxResult { let vm_types = [ VerificationMethodType::Ed25519VerificationKey2018, VerificationMethodType::Ed25519VerificationKey2020, @@ -50,58 +50,58 @@ pub fn resolve_ed25519_base58_key_agreement(did_document: &DidDocument) -> VcxRe let vm = did_document.get_key_agreement_of_type(&vm_types)?; let key = vm.public_key()?; - match key.key_type() { - KeyType::Ed25519 => {} - _ => { - return Err(AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidVerkey, - format!("Cannot resolve key agreement as an Ed25519 key: {vm:?}"), - )) - } - } - - Ok(vm.public_key()?.base58()) + Ok(key.validate_key_type(KeyType::Ed25519)?.to_owned()) } -pub fn get_ed25519_base58_routing_keys( +pub fn get_ed25519_routing_keys( their_did_doc: &DidDocument, service_id: &Uri, -) -> VcxResult> { +) -> VcxResult> { let service = their_did_doc.get_service_by_id(service_id)?; let Ok(routing_keys) = service.extra_field_routing_keys() else { return Ok(vec![]); }; - let mut naked_routing_keys = Vec::new(); + let mut ed25519_routing_keys = Vec::new(); for key in routing_keys.iter() { let pub_key = resolve_service_key_to_typed_key(key, their_did_doc)?; if pub_key.key_type() == &KeyType::Ed25519 { - naked_routing_keys.push(pub_key.base58()); + ed25519_routing_keys.push(pub_key); + } else { + warn!( + "Unexpected key with type {} in routing keys list", + pub_key.key_type() + ); } } - Ok(naked_routing_keys) + Ok(ed25519_routing_keys) } -pub fn get_ed25519_base58_recipient_keys( +pub fn get_ed25519_recipient_keys( their_did_doc: &DidDocument, service_id: &Uri, -) -> VcxResult> { +) -> VcxResult> { let service = their_did_doc.get_service_by_id(service_id)?; let Ok(recipient_keys) = service.extra_field_recipient_keys() else { return Ok(vec![]); }; - let mut naked_recipient_keys = Vec::new(); + let mut ed25519_recipient_keys = Vec::new(); for key in recipient_keys.iter() { let pub_key = resolve_service_key_to_typed_key(key, their_did_doc)?; if pub_key.key_type() == &KeyType::Ed25519 { - naked_recipient_keys.push(pub_key.base58()); + ed25519_recipient_keys.push(pub_key); + } else { + warn!( + "Unexpected key with type {} in recipient keys list", + pub_key.key_type() + ); } } - Ok(naked_recipient_keys) + Ok(ed25519_recipient_keys) } diff --git a/aries/aries_vcx/src/utils/encryption_envelope.rs b/aries/aries_vcx/src/utils/encryption_envelope.rs index 9a522e2f1e..0fed891fe6 100644 --- a/aries/aries_vcx/src/utils/encryption_envelope.rs +++ b/aries/aries_vcx/src/utils/encryption_envelope.rs @@ -8,10 +8,11 @@ use messages::{ use public_key::{Key, KeyType}; use uuid::Uuid; -use super::didcomm_utils::get_ed25519_base58_recipient_keys; use crate::{ errors::error::prelude::*, - utils::didcomm_utils::{get_ed25519_base58_routing_keys, resolve_ed25519_base58_key_agreement}, + utils::didcomm_utils::{ + get_ed25519_recipient_keys, get_ed25519_routing_keys, resolve_ed25519_key_agreement, + }, }; #[derive(Debug)] @@ -31,7 +32,7 @@ impl EncryptionEnvelope { did_doc ); - let recipient_key = + let recipient_key_base58 = did_doc .recipient_keys()? .first() @@ -40,8 +41,17 @@ impl EncryptionEnvelope { AriesVcxErrorKind::InvalidState, format!("No recipient key found in DIDDoc: {:?}", did_doc), ))?; - let routing_keys = did_doc.routing_keys(); - Self::create_from_keys(wallet, data, sender_vk, recipient_key, routing_keys).await + + let recipient_key = Key::from_base58(&recipient_key_base58, KeyType::Ed25519)?; + let routing_keys = did_doc + .routing_keys() + .iter() + .map(|routing_key| Key::from_base58(routing_key, KeyType::Ed25519)) + .collect::, _>>()?; + let sender_key = sender_vk + .map(|key| Key::from_base58(key, KeyType::Ed25519)) + .transpose()?; + Self::create_from_keys(wallet, data, sender_key, recipient_key, routing_keys).await } /// Create encrypted message based on key agreement keys of our did document, counterparties @@ -63,22 +73,22 @@ impl EncryptionEnvelope { their_did_doc: &DidDocument, their_service_id: &Uri, ) -> VcxResult { - let sender_vk = resolve_ed25519_base58_key_agreement(our_did_doc)?; + let sender_vk = resolve_ed25519_key_agreement(our_did_doc)?; let recipient_key = { - let service_keys = get_ed25519_base58_recipient_keys(their_did_doc, their_service_id)?; + let service_keys = get_ed25519_recipient_keys(their_did_doc, their_service_id)?; match service_keys.into_iter().next() { Some(key) => key, // as a backup, use the first key agreement key, or none - None => resolve_ed25519_base58_key_agreement(their_did_doc)?, + None => resolve_ed25519_key_agreement(their_did_doc)?, } }; - let routing_keys = get_ed25519_base58_routing_keys(their_did_doc, their_service_id)?; + let routing_keys = get_ed25519_routing_keys(their_did_doc, their_service_id)?; EncryptionEnvelope::create_from_keys( wallet, data, - Some(&sender_vk), + Some(sender_vk), recipient_key, routing_keys, ) @@ -88,17 +98,24 @@ impl EncryptionEnvelope { pub async fn create_from_keys( wallet: &impl BaseWallet, data: &[u8], - sender_vk: Option<&str>, - // TODO - why not have encryption envelope take typed [Key]s, and enforce they are - // KeyType::Ed25519 - recipient_key: String, - routing_keys: Vec, + sender_vk: Option, + recipient_key: Key, + routing_keys: Vec, ) -> VcxResult { + // Validate keys are Ed25519 + sender_vk + .as_ref() + .map(|key| key.validate_key_type(KeyType::Ed25519)) + .transpose()?; + for key in routing_keys.iter().as_ref() { + key.validate_key_type(KeyType::Ed25519)?; + } + let message = EncryptionEnvelope::encrypt_for_pairwise( wallet, data, sender_vk, - recipient_key.clone(), + recipient_key.validate_key_type(KeyType::Ed25519)?.clone(), ) .await?; EncryptionEnvelope::wrap_into_forward_messages(wallet, message, recipient_key, routing_keys) @@ -109,24 +126,18 @@ impl EncryptionEnvelope { async fn encrypt_for_pairwise( wallet: &impl BaseWallet, data: &[u8], - sender_vk: Option<&str>, - recipient_key: String, + sender_vk: Option, + recipient_key: Key, ) -> VcxResult> { debug!( "Encrypting for pairwise; sender_vk: {:?}, recipient_key: {}", sender_vk, recipient_key ); - let recipient_keys = vec![Key::from_base58(&recipient_key, KeyType::Ed25519)?]; + let recipient_keys = vec![recipient_key]; wallet - .pack_message( - sender_vk - .map(|key| Key::from_base58(key, KeyType::Ed25519)) - .transpose()?, - recipient_keys, - data, - ) + .pack_message(sender_vk, recipient_keys, data) .await .map_err(|err| err.into()) } @@ -134,20 +145,24 @@ impl EncryptionEnvelope { async fn wrap_into_forward_messages( wallet: &impl BaseWallet, mut data: Vec, - recipient_key: String, - routing_keys: Vec, + recipient_key: Key, + routing_keys: Vec, ) -> VcxResult> { let mut forward_to_key = recipient_key; - for routing_key in routing_keys.iter() { + for routing_key in routing_keys { debug!( "Wrapping message in forward message; forward_to_key: {}, routing_key: {}", forward_to_key, routing_key ); - data = - EncryptionEnvelope::wrap_into_forward(wallet, data, &forward_to_key, routing_key) - .await?; - forward_to_key.clone_from(routing_key); + data = EncryptionEnvelope::wrap_into_forward( + wallet, + data, + &forward_to_key, + routing_key.clone(), + ) + .await?; + forward_to_key.clone_from(&routing_key); } Ok(data) } @@ -155,11 +170,11 @@ impl EncryptionEnvelope { async fn wrap_into_forward( wallet: &impl BaseWallet, data: Vec, - forward_to_key: &str, - routing_key: &str, + forward_to_key: &Key, + routing_key: Key, ) -> VcxResult> { let content = ForwardContent::builder() - .to(forward_to_key.to_string()) + .to(forward_to_key.base58()) .msg(serde_json::from_slice(&data)?) .build(); @@ -170,10 +185,7 @@ impl EncryptionEnvelope { let message = json!(AriesMessage::from(message)).to_string(); - let receiver_keys = vec![routing_key] - .into_iter() - .map(|item| Key::from_base58(item, KeyType::Ed25519)) - .collect::>()?; + let receiver_keys = vec![routing_key]; wallet .pack_message(None, receiver_keys, message.as_bytes()) @@ -181,27 +193,35 @@ impl EncryptionEnvelope { .map_err(|err| err.into()) } - async fn _unpack_a2a_message( + // Will unpack a message as either anoncrypt or authcrypt. + async fn unpack_a2a_message( wallet: &impl BaseWallet, - encrypted_data: Vec, - ) -> VcxResult<(String, Option, String)> { + encrypted_data: &[u8], + ) -> VcxResult<(String, Option, Key)> { trace!( - "EncryptionEnvelope::_unpack_a2a_message >>> processing payload of {} bytes", + "EncryptionEnvelope::unpack_a2a_message >>> processing payload of {} bytes", encrypted_data.len() ); - let unpacked_msg = wallet.unpack_message(&encrypted_data).await?; + let unpacked_msg = wallet.unpack_message(encrypted_data).await?; + let sender_key = unpacked_msg + .sender_verkey + .map(|key| Key::from_base58(&key, KeyType::Ed25519)) + .transpose()?; Ok(( unpacked_msg.message, - unpacked_msg.sender_verkey, - unpacked_msg.recipient_verkey, + sender_key, + Key::from_base58(&unpacked_msg.recipient_verkey, KeyType::Ed25519)?, )) } - pub async fn anon_unpack_aries_msg( + /// Unpacks an authcrypt or anoncrypt message returning the message, which is deserialized into an Aries message, as well as the sender key (if any -- anoncrypt does not return this) and the recipient key. Optionally takes expected_sender_vk, which does a comparison to ensure the sender key is the expected key. + pub async fn unpack_aries_msg( wallet: &impl BaseWallet, - encrypted_data: Vec, - ) -> VcxResult<(AriesMessage, Option, String)> { - let (message, sender_vk, recipient_vk) = Self::anon_unpack(wallet, encrypted_data).await?; + encrypted_data: &[u8], + expected_sender_vk: &Option, + ) -> VcxResult<(AriesMessage, Option, Key)> { + let (message, sender_vk, recipient_vk) = + Self::unpack(wallet, encrypted_data, expected_sender_vk).await?; let a2a_message = serde_json::from_str(&message).map_err(|err| { AriesVcxError::from_msg( AriesVcxErrorKind::InvalidJson, @@ -211,76 +231,48 @@ impl EncryptionEnvelope { Ok((a2a_message, sender_vk, recipient_vk)) } - pub async fn anon_unpack( + /// Unpacks an authcrypt or anoncrypt message returning the message, the sender key (if any -- anoncrypt does not return this), and the recipient key. Optionally takes expected_sender_vk, which does a comparison to ensure the sender key is the expected key. + pub async fn unpack( wallet: &impl BaseWallet, - encrypted_data: Vec, - ) -> VcxResult<(String, Option, String)> { + encrypted_data: &[u8], + expected_sender_vk: &Option, + ) -> VcxResult<(String, Option, Key)> { trace!( "EncryptionEnvelope::anon_unpack >>> processing payload of {} bytes", encrypted_data.len() ); - Self::_unpack_a2a_message(wallet, encrypted_data).await - } - - pub async fn auth_unpack_aries_msg( - wallet: &impl BaseWallet, - encrypted_data: Vec, - expected_vk: &str, - ) -> VcxResult { - let message = Self::auth_unpack(wallet, encrypted_data, expected_vk).await?; - let a2a_message = serde_json::from_str(&message).map_err(|err| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidJson, - format!("Cannot deserialize A2A message: {}", err), - ) - })?; - Ok(a2a_message) - } - - pub async fn auth_unpack( - wallet: &impl BaseWallet, - encrypted_data: Vec, - expected_vk: &str, - ) -> VcxResult { - trace!( - "EncryptionEnvelope::auth_unpack >>> processing payload of {} bytes, expected_vk: {}", - encrypted_data.len(), - expected_vk - ); - - let (a2a_message, sender_vk, _) = Self::_unpack_a2a_message(wallet, encrypted_data).await?; - trace!( - "anon_unpack >> a2a_msg: {:?}, sender_vk: {:?}", - a2a_message, - sender_vk - ); - - match sender_vk { - Some(sender_vk) => { - if sender_vk != expected_vk { - error!( - "auth_unpack sender_vk != expected_vk.... sender_vk: {}, expected_vk: {}", - sender_vk, expected_vk + let (a2a_message, sender_vk, recipient_vk) = + Self::unpack_a2a_message(wallet, encrypted_data).await?; + + // If expected_sender_vk was provided and a sender_verkey exists, verify that they match + if let Some(expected_key) = expected_sender_vk { + match &sender_vk { + Some(sender_vk) => { + if sender_vk != expected_key { + error!( + "auth_unpack sender_vk != expected_sender_vk.... sender_vk: {}, expected_sender_vk: {}", + sender_vk, expected_key ); - return Err(AriesVcxError::from_msg( - AriesVcxErrorKind::AuthenticationError, - format!( + return Err(AriesVcxError::from_msg( + AriesVcxErrorKind::AuthenticationError, + format!( "Message did not pass authentication check. Expected sender verkey \ was {}, but actually was {}", - expected_vk, sender_vk + expected_key, sender_vk ), + )); + } + } + None => { + error!("auth_unpack message was authcrypted"); + return Err(AriesVcxError::from_msg( + AriesVcxErrorKind::AuthenticationError, + "Can't authenticate message because it was anoncrypted.", )); } } - None => { - error!("auth_unpack message was authcrypted"); - return Err(AriesVcxError::from_msg( - AriesVcxErrorKind::AuthenticationError, - "Can't authenticate message because it was anoncrypted.", - )); - } } - Ok(a2a_message) + Ok((a2a_message, sender_vk, recipient_vk)) } } @@ -307,14 +299,14 @@ pub mod unit_tests { &setup.wallet, data_original.as_bytes(), None, - did_data.verkey().base58(), + did_data.verkey().clone(), [].to_vec(), ) .await .unwrap(); let (data_unpacked, sender_verkey, _) = - EncryptionEnvelope::anon_unpack(&setup.wallet, envelope.0) + EncryptionEnvelope::unpack(&setup.wallet, &envelope.0, &None) .await .unwrap(); @@ -336,24 +328,25 @@ pub mod unit_tests { .await .unwrap(); - let sender_vk = sender_data.verkey().base58(); - let recipient_vk = recipient_data.verkey().base58(); + let sender_vk = sender_data.verkey().clone(); + let recipient_vk = recipient_data.verkey(); let data_original = "foobar"; let envelope = EncryptionEnvelope::create_from_keys( &setup.wallet, data_original.as_bytes(), - Some(&sender_vk), + Some(sender_vk.clone()), recipient_vk.clone(), [].to_vec(), ) .await .unwrap(); - let data_unpacked = EncryptionEnvelope::auth_unpack(&setup.wallet, envelope.0, &sender_vk) - .await - .unwrap(); + let (data_unpacked, _sender_vk_unpacked, _recipient_vk_unpacked) = + EncryptionEnvelope::unpack(&setup.wallet, &envelope.0, &Some(sender_vk)) + .await + .unwrap(); assert_eq!(data_original, data_unpacked); } @@ -382,14 +375,14 @@ pub mod unit_tests { let envelope = EncryptionEnvelope::create_from_keys( &setup.wallet, data_original.as_bytes(), - Some(&sender_data.verkey().base58()), - recipient_data.verkey().base58(), - [routing_data.verkey().base58()].to_vec(), + Some(sender_data.verkey().clone()), + recipient_data.verkey().clone(), + [routing_data.verkey().clone()].to_vec(), ) .await .unwrap(); - let (fwd_msg, _, _) = EncryptionEnvelope::anon_unpack(&setup.wallet, envelope.0) + let (fwd_msg, _, _) = EncryptionEnvelope::unpack(&setup.wallet, &envelope.0, &None) .await .unwrap(); let fwd_payload = serde_json::from_str::(&fwd_msg) @@ -398,7 +391,7 @@ pub mod unit_tests { .unwrap() .to_string(); let (core_payload, _, _) = - EncryptionEnvelope::anon_unpack(&setup.wallet, fwd_payload.into()) + EncryptionEnvelope::unpack(&setup.wallet, fwd_payload.as_bytes(), &None) .await .unwrap(); @@ -429,17 +422,17 @@ pub mod unit_tests { let envelope = EncryptionEnvelope::create_from_keys( &setup.wallet, data_original.as_bytes(), - Some(&bob_data.verkey().base58()), // bob trying to impersonate alice - recipient_data.verkey().base58(), + Some(bob_data.verkey().clone()), // bob trying to impersonate alice + recipient_data.verkey().clone(), [].to_vec(), ) .await .unwrap(); - let err = EncryptionEnvelope::auth_unpack( + let err = EncryptionEnvelope::unpack( &setup.wallet, - envelope.0, - &alice_data.verkey().base58(), + &envelope.0, + &Some(alice_data.verkey().clone()), ) .await; assert!(err.is_err()); diff --git a/aries/aries_vcx/tests/test_connection.rs b/aries/aries_vcx/tests/test_connection.rs index 1dae681b36..08ae819940 100644 --- a/aries/aries_vcx/tests/test_connection.rs +++ b/aries/aries_vcx/tests/test_connection.rs @@ -60,15 +60,12 @@ async fn decrypt_message( impl BaseWallet, >, received: Vec, - consumer_to_institution: &GenericConnection, ) -> AriesMessage { - EncryptionEnvelope::auth_unpack_aries_msg( - &consumer.wallet, - received, - &consumer_to_institution.remote_vk().unwrap(), - ) - .await - .unwrap() + let (message, _, _) = + EncryptionEnvelope::unpack_aries_msg(&consumer.wallet, received.as_slice(), &None) + .await + .unwrap(); + message } async fn send_and_receive_message( @@ -85,7 +82,6 @@ async fn send_and_receive_message( impl BaseWallet, >, institution_to_consumer: &GenericConnection, - consumer_to_institution: &GenericConnection, message: &AriesMessage, ) -> AriesMessage { let encrypted_message = institution_to_consumer @@ -93,7 +89,7 @@ async fn send_and_receive_message( .await .unwrap() .0; - decrypt_message(consumer, encrypted_message, consumer_to_institution).await + decrypt_message(consumer, encrypted_message).await } async fn create_service( @@ -126,7 +122,7 @@ async fn test_agency_pool_establish_connection_via_public_invite() -> Result<(), let mut consumer = create_test_agent(setup.genesis_file_path).await; create_service(&institution).await; - let (consumer_to_institution, institution_to_consumer) = + let (_consumer_to_institution, institution_to_consumer) = create_connections_via_public_invite(&mut consumer, &mut institution).await; let basic_message = build_basic_message("Hello TestAgent".to_string()); @@ -134,7 +130,6 @@ async fn test_agency_pool_establish_connection_via_public_invite() -> Result<(), &consumer, &institution, &institution_to_consumer, - &consumer_to_institution, &basic_message.clone().into(), ) .await @@ -153,7 +148,7 @@ async fn test_agency_pool_establish_connection_via_pairwise_invite() -> Result<( let mut institution = create_test_agent(setup.genesis_file_path.clone()).await; let mut consumer = create_test_agent(setup.genesis_file_path).await; - let (consumer_to_institution, institution_to_consumer) = + let (_consumer_to_institution, institution_to_consumer) = create_connections_via_pairwise_invite(&mut consumer, &mut institution).await; let basic_message = build_basic_message("Hello TestAgent".to_string()); @@ -161,7 +156,6 @@ async fn test_agency_pool_establish_connection_via_pairwise_invite() -> Result<( &consumer, &institution, &institution_to_consumer, - &consumer_to_institution, &basic_message.clone().into(), ) .await @@ -190,7 +184,7 @@ async fn test_agency_pool_establish_connection_via_out_of_band() -> Result<(), B let mut consumer = create_test_agent(setup.genesis_file_path).await; create_service(&endorser).await; - let (consumer_to_endorser, endorser_to_consumer) = + let (_consumer_to_endorser, endorser_to_consumer) = create_connections_via_oob_invite(&mut consumer, &mut endorser).await; let basic_message = build_basic_message("Hello TestAgent".to_string()); @@ -198,7 +192,6 @@ async fn test_agency_pool_establish_connection_via_out_of_band() -> Result<(), B &consumer, &endorser, &endorser_to_consumer, - &consumer_to_endorser, &basic_message.clone().into(), ) .await diff --git a/aries/aries_vcx/tests/test_did_exchange.rs b/aries/aries_vcx/tests/test_did_exchange.rs index a7f7f6cf58..8d83da96d0 100644 --- a/aries/aries_vcx/tests/test_did_exchange.rs +++ b/aries/aries_vcx/tests/test_did_exchange.rs @@ -16,8 +16,7 @@ use aries_vcx::{ transition::transition_result::TransitionResult, }, utils::{ - didcomm_utils::resolve_ed25519_base58_key_agreement, - encryption_envelope::EncryptionEnvelope, + didcomm_utils::resolve_ed25519_key_agreement, encryption_envelope::EncryptionEnvelope, }, }; use aries_vcx_anoncreds::anoncreds::base_anoncreds::BaseAnonCreds; @@ -53,8 +52,8 @@ pub mod utils; fn assert_key_agreement(a: DidDocument, b: DidDocument) { log::warn!("comparing did doc a: {}, b: {}", a, b); - let a_key = resolve_ed25519_base58_key_agreement(&a).unwrap(); - let b_key = resolve_ed25519_base58_key_agreement(&b).unwrap(); + let a_key = resolve_ed25519_key_agreement(&a).unwrap(); + let b_key = resolve_ed25519_key_agreement(&b).unwrap(); assert_eq!(a_key, b_key); } @@ -191,9 +190,9 @@ async fn did_exchange_test( info!("Encrypted message: {:?}", m); let requesters_peer_did = requesters_peer_did.resolve_did_doc()?; - let expected_sender_vk = resolve_ed25519_base58_key_agreement(&requesters_peer_did)?; + let expected_sender_vk = resolve_ed25519_key_agreement(&requesters_peer_did)?; let unpacked = - EncryptionEnvelope::auth_unpack(&agent_inviter.wallet, m.0, &expected_sender_vk).await?; + EncryptionEnvelope::unpack(&agent_inviter.wallet, &m.0, &Some(expected_sender_vk)).await?; info!("Unpacked message: {:?}", unpacked); diff --git a/aries/misc/test_utils/src/devsetup.rs b/aries/misc/test_utils/src/devsetup.rs index 770d847f3e..4697bd8fb8 100644 --- a/aries/misc/test_utils/src/devsetup.rs +++ b/aries/misc/test_utils/src/devsetup.rs @@ -196,7 +196,7 @@ pub async fn dev_build_featured_wallet(key_seed: &str) -> (String, impl BaseWall { use crate::{constants::INSTITUTION_DID, mock_wallet::MockWallet}; - return (INSTITUTION_DID.to_owned(), MockWallet); + (INSTITUTION_DID.to_owned(), MockWallet) } } diff --git a/did_core/public_key/src/error.rs b/did_core/public_key/src/error.rs index 13ca4ea541..62d4ce175e 100644 --- a/did_core/public_key/src/error.rs +++ b/did_core/public_key/src/error.rs @@ -2,6 +2,8 @@ use std::error::Error; use thiserror::Error; +use crate::KeyType; + #[derive(Debug, Error)] pub enum PublicKeyError { #[error("Base 64 decoding error")] @@ -18,6 +20,8 @@ pub enum PublicKeyError { UnsupportedMulticodecDescriptor(u64), #[error("Unsupported multicodec descriptor: {0}")] UnsupportedKeyType(String), + #[error("Invalid KeyType {0}, expected KeyType: {1}")] + InvalidKeyType(KeyType, KeyType), } #[derive(Debug, Error)] diff --git a/did_core/public_key/src/key.rs b/did_core/public_key/src/key.rs index 8edd3b74b6..a90f23235e 100644 --- a/did_core/public_key/src/key.rs +++ b/did_core/public_key/src/key.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use serde::{Deserialize, Serialize}; use super::KeyType; @@ -22,6 +24,16 @@ impl Key { &self.key_type } + pub fn validate_key_type(&self, key_type: KeyType) -> Result<&Self, PublicKeyError> { + if self.key_type() != &key_type { + return Err(PublicKeyError::InvalidKeyType( + self.key_type().to_owned(), + key_type, + )); + } + Ok(self) + } + pub fn key(&self) -> &[u8] { self.key.as_ref() } @@ -88,6 +100,12 @@ impl Key { } } +impl Display for Key { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.base58()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/did_core/public_key/src/key_type.rs b/did_core/public_key/src/key_type.rs index 66643b16da..10394c582b 100644 --- a/did_core/public_key/src/key_type.rs +++ b/did_core/public_key/src/key_type.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use serde::{Deserialize, Serialize}; use crate::error::PublicKeyError; @@ -58,3 +60,18 @@ impl TryFrom for KeyType { } } } + +impl Display for KeyType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + KeyType::Bls12381g1 => write!(f, "Bls12381g1"), + KeyType::Bls12381g2 => write!(f, "Bls12381g2"), + KeyType::X25519 => write!(f, "X25519"), + KeyType::Ed25519 => write!(f, "Ed25519"), + KeyType::Bls12381g1g2 => write!(f, "Bls12381g1g2"), + KeyType::P256 => write!(f, "P256"), + KeyType::P384 => write!(f, "P384"), + KeyType::P521 => write!(f, "P521"), + } + } +}