diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..dd84ea78 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/build_and_tests.yml b/.github/workflows/build_and_tests.yaml similarity index 95% rename from .github/workflows/build_and_tests.yml rename to .github/workflows/build_and_tests.yaml index 003ebc7d..abc5c553 100644 --- a/.github/workflows/build_and_tests.yml +++ b/.github/workflows/build_and_tests.yaml @@ -15,16 +15,16 @@ env: jobs: version: - uses: radumarias/rencfs/.github/workflows/version_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/version_reusable.yaml@main build_and_test: name: build and test - uses: radumarias/rencfs/.github/workflows/build_and_tests_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/build_and_tests_reusable.yaml@main secrets: inherit package: needs: [version, build_and_test] - uses: radumarias/rencfs/.github/workflows/package_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/package_reusable.yaml@main with: upload_artifacts: false version: ${{ needs.version.outputs.version }} diff --git a/.github/workflows/build_and_tests_reusable.yml b/.github/workflows/build_and_tests_reusable.yaml similarity index 92% rename from .github/workflows/build_and_tests_reusable.yml rename to .github/workflows/build_and_tests_reusable.yaml index 64333778..99b7f227 100644 --- a/.github/workflows/build_and_tests_reusable.yml +++ b/.github/workflows/build_and_tests_reusable.yaml @@ -1,11 +1,11 @@ -name: '_reusable-build-and-tests-reusable' +name: '_build-and-tests' on: workflow_call: env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 # TODO: remove this when we cache the builds - + jobs: tests: name: build and tests @@ -13,13 +13,19 @@ jobs: strategy: matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] - fail-fast: true + fail-fast: true steps: - uses: actions/checkout@v4 + - name: setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: rustfmt, clippy + profile: minimal + - name: setup Rust run: | - rustup update cargo install cargo-aur cargo install cargo-generate-rpm diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yaml similarity index 100% rename from .github/workflows/jekyll-gh-pages.yml rename to .github/workflows/jekyll-gh-pages.yaml diff --git a/.github/workflows/package_reusable.yml b/.github/workflows/package_reusable.yaml similarity index 81% rename from .github/workflows/package_reusable.yml rename to .github/workflows/package_reusable.yaml index 1b46be63..15673cc0 100644 --- a/.github/workflows/package_reusable.yml +++ b/.github/workflows/package_reusable.yaml @@ -1,4 +1,4 @@ -name: '_reusable-package' +name: '_package' on: workflow_call: inputs: @@ -18,15 +18,24 @@ jobs: steps: - uses: actions/checkout@v4 - - name: install latest Rust nightly - run: rustup default nightly && rustup update - - - name: install cargo-aur - run: cargo install cargo-aur + - name: setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: rustfmt, clippy + profile: minimal + + - name: setup Rust + run: | + cargo install cargo-aur + cargo install cargo-generate-rpm + + - name: run cargo aur and generate-rpm + if: matrix.os == 'ubuntu-latest' + run: | + cargo aur + cargo generate-rpm - - name: run cargo aur - run: cargo aur - - name: check for publish run: cargo publish --dry-run --allow-dirty diff --git a/.github/workflows/release.yml b/.github/workflows/release.yaml similarity index 98% rename from .github/workflows/release.yml rename to .github/workflows/release.yaml index a8058b5c..b1718f11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yaml @@ -11,16 +11,16 @@ env: jobs: version: - uses: radumarias/rencfs/.github/workflows/version_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/version_reusable.yaml@main build_and_test: name: build and test - uses: radumarias/rencfs/.github/workflows/build_and_tests_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/build_and_tests_reusable.yaml@main secrets: inherit package: needs: [version, build_and_test] - uses: radumarias/rencfs/.github/workflows/package_reusable.yml@main + uses: radumarias/rencfs/.github/workflows/package_reusable.yaml@main with: upload_artifacts: true version: ${{ needs.version.outputs.version }} diff --git a/.github/workflows/version_reusable.yml b/.github/workflows/version_reusable.yaml similarity index 100% rename from .github/workflows/version_reusable.yml rename to .github/workflows/version_reusable.yaml diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..41719f52 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +radumarias@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a71c179..a6d2773d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,20 +3,22 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions. 1. Join [slack](https://join.slack.com/t/rencfs/shared_invite/zt-2o4l1tdkk-VJeWIbO2p6zgeafDISPHbQ) -2. Become familiar with docs and code by reading the [ramp-up](Ramp-up.md) -3. **Ask the owner of the repository to add your GitHub username to the repository** +2. Become familiar with docs and code by reading the [ramp-up](Ramp-up.md) guide +3. **Ask the owner of the repository to add your GitHub username to the repository** os that you can work on issues and be able to create your own branches and not needing to fork the repo 4. Pick an open issue or a task in the corresponding [project](https://github.com/users/radumarias/projects/1) for the repo that you'll be working on. You can see [good for first issues](https://github.com/radumarias/rencfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) that you can pick from -5. **Assign the issues you are working on to you and move them to the corresponding status column as you are working on them. If the taks is not an issue yet, convert it to issue first** +5. **Assign the issues you are working on to you and move them to the corresponding status column as you are progressing on them. If the taks is not an issue yet, convert it to issue first** 6. Make the changes in your branch 7. Add docs as they apply 8. Add tests, benchmarks and examples for your changes, if applicable -9. `cargo fmt --all` to format the code. You can configure your **IDE** to do this on +9. `cargo fmt --all` to format the code. You can configure your `IDE` to do this on save, [RustRover](https://www.jetbrains.com/help/rust/rustfmt.html) and [VSCode](https://code.visualstudio.com/docs/languages/rust#_formatting) 10. `cargo clippy --all --release` and fix any erorrs 11. **DON'T INCREASE THE VERSION NUMBER IN `Cargo.toml`, WE WILL DO THAN WHEN RELEASING** -12. **MAKE SURE YOU RUN THIS BEFORE PUSHING TO THE REPO `./check-before-push-linux.sh`, `./check-before-push-macos.sh` or `cmd /c check-before-push-windows.bat` and fix any errors** -13. Create a **PR** back to the **parent** repo targeting the `main` branch and request review from owners of the repository -14. Monitor the checks (GitHub actions runs) and fix the code if they are failing -15. Respond to any comments -16. In the end, ideally, it will be merged to `main` +12. Create a `git` `commit hook` file in `.git/hooks/pre-commit` with [this](hooks/linux-macos/pre-commit) content on `Linux` and `MacOS`, or [this](hooks/windows/pre-commit) on `Windows`. Make it executable in Linux and macO with `chmod +x .git/hooks/pre-commit` .This will run when you do `git commit` and will make the commit to be quite slow, but please give it time to complete as this helps to fix any issues locally and not relying just on running `ci` on GitHub when you create the PR +13. Commit your changes and if there are any errors fix them before you push them +14. Push your changes and create a `PR` back to the `parent` repo targeting the `main` branch and request review from owners of the repository +15. Monitor the checks (GitHub actions runs) and fix the code if they are failing +16. Respond to any comments +17. **DON'T MERGE THE PR YOURSELF, LEAVE THAT TO REPOSITORY OWNERS** +18. In the end, ideally, it will be merged to `main` diff --git a/Cargo.lock b/Cargo.lock index 06f892f4..032a4fdd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aes" @@ -57,9 +57,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -72,33 +72,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "argon2" @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -136,9 +136,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-broadcast" @@ -164,13 +164,13 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-lite 2.3.0", "slab", ] @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock 3.4.0", "cfg-if 1.0.0", @@ -219,11 +219,11 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.2", - "rustix 0.38.34", + "polling 3.7.3", + "rustix 0.38.37", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -270,7 +270,7 @@ dependencies = [ "cfg-if 1.0.0", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.34", + "rustix 0.38.37", "windows-sys 0.48.0", ] @@ -282,25 +282,25 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-lock 3.4.0", "atomic-waker", "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.34", + "rustix 0.38.37", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -322,13 +322,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -355,17 +355,17 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -397,9 +397,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake2" @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "bon" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "811d7882589e047896e5974d039dd8823a67973a63d559e6ad1e87ff5c42ed4f" +checksum = "97493a391b4b18ee918675fb8663e53646fd09321c58b46afa04e8ce2499c869" dependencies = [ "bon-macros", "rustversion", @@ -466,15 +466,15 @@ dependencies = [ [[package]] name = "bon-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e745a763e579a5ce70130e66f9dd35abf77cfeb9f418f305aeab8d1ae54c43" +checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" dependencies = [ "darling", "ident_case", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -491,9 +491,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cbc" @@ -506,9 +506,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.99" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -528,6 +531,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cipher" version = "0.4.4" @@ -540,9 +549,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -550,9 +559,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -562,27 +571,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "concurrent-queue" @@ -611,15 +620,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -670,12 +679,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" dependencies = [ - "nix 0.28.0", - "windows-sys 0.52.0", + "nix 0.29.0", + "windows-sys 0.59.0", ] [[package]] @@ -699,7 +708,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -710,7 +719,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -746,9 +755,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enumflags2" @@ -768,7 +777,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -847,9 +856,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "flume" @@ -934,7 +943,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-core", "futures-io", "parking", @@ -949,7 +958,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -1006,9 +1015,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "hashbrown" @@ -1079,9 +1088,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1119,9 +1128,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" @@ -1131,9 +1140,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1154,15 +1163,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linux-keyutils" @@ -1170,7 +1179,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -1198,15 +1207,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown", ] @@ -1246,18 +1255,18 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -1292,13 +1301,25 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if 1.0.0", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", "memoffset 0.9.1", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if 1.0.0", + "cfg_aliases 0.2.1", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1325,9 +1346,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -1354,7 +1375,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "itoa", ] @@ -1400,9 +1421,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -1420,9 +1441,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" [[package]] name = "ordered-stream" @@ -1442,9 +1463,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -1466,7 +1487,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1494,12 +1515,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-io", ] @@ -1521,17 +1542,17 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.34", + "rustix 0.38.37", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1542,9 +1563,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" @@ -1558,18 +1582,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1606,18 +1630,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1686,8 +1710,8 @@ dependencies = [ "retainer", "ring", "rpassword", - "secrecy", "serde", + "shush-rs", "strum", "strum_macros", "subtle", @@ -1758,9 +1782,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -1781,11 +1805,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys 0.4.14", @@ -1804,15 +1828,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "secrecy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" -dependencies = [ - "zeroize", -] - [[package]] name = "secret-service" version = "3.1.0" @@ -1834,11 +1849,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -1847,9 +1862,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -1863,22 +1878,22 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -1889,7 +1904,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -1923,6 +1938,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shush-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de8f82d4a4085f9ea4ab8d493e6e62ab871b2bf446d4d90633b58ca400aedff" +dependencies = [ + "errno", + "libc", + "windows-sys 0.59.0", + "zeroize", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -1990,9 +2023,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" @@ -2004,7 +2037,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2026,9 +2059,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -2037,34 +2070,35 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if 1.0.0", - "fastrand 2.1.0", - "rustix 0.38.34", - "windows-sys 0.52.0", + "fastrand 2.1.1", + "once_cell", + "rustix 0.38.37", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2110,9 +2144,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.2" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -2134,14 +2168,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -2150,9 +2184,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -2196,7 +2230,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2256,7 +2290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2267,7 +2301,7 @@ checksum = "96cbd06a7b648f1603e60d75d9ed295d096b340d30e9f9324f4b512b5d40cd92" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] @@ -2289,9 +2323,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "untrusted" @@ -2313,9 +2347,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "waker-fn" @@ -2331,34 +2365,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if 1.0.0", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2366,32 +2401,32 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "which" -version = "6.0.1" +version = "6.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" dependencies = [ "either", "home", - "rustix 0.38.34", + "rustix 0.38.37", "winsafe", ] @@ -2432,7 +2467,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -2452,18 +2496,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2474,9 +2518,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2486,9 +2530,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2498,15 +2542,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2516,9 +2560,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2528,9 +2572,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2540,9 +2584,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2552,9 +2596,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -2573,12 +2617,12 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2649,22 +2693,23 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.77", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1809e4d5..39c126d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,6 @@ rpassword = "7.3.1" anyhow = "1.0.82" argon2 = "0.5.3" keyring = "2.3.2" -secrecy = "0.8.0" retainer = "0.3.0" num-format = "0.4.4" ring = "0.17.8" @@ -57,6 +56,7 @@ blake3 = "=0.1.3" thread_local = "1.1.8" subtle = "2.6.1" bon = "2.2.0" +shush-rs = "0.1.10" [target.'cfg(target_os = "linux")'.dependencies] fuse3 = { version = "0.7.2", features = ["tokio-runtime", "unprivileged"] } diff --git a/Dockerfile b/Dockerfile index e4d14bd2..7ff82b63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,9 +19,10 @@ RUN . ~/.cargo/env && rustup default nightly && rustup update # rm -Rvf /usr/src/rencfs/src # Build our actual code -COPY Cargo.toml Cargo.lock /usr/src/rencfs/ -COPY src /usr/src/rencfs/src -COPY examples /usr/src/rencfs/examples +#COPY Cargo.toml Cargo.lock /usr/src/rencfs/ +#COPY src /usr/src/rencfs +COPY . /usr/src/rencfs +#COPY examples /usr/src/rencfs/examples RUN . ~/.cargo/env && \ cd /usr/src/rencfs/ && \ cargo build --target x86_64-unknown-linux-musl --release diff --git a/README.md b/README.md index 265ff221..eea35d0d 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ An encrypted file system written in Rust that is mounted with FUSE on Linux. It You can then safely backup the encrypted directory to an untrusted server without worrying about the data being exposed. You can also store it in any cloud storage like Google Drive, Dropbox, etc. and have it synced across multiple devices. -You can use it as CLI or as a library to build your custom FUSE implementation or other apps that works with encrypted data. +You can use it as CLI or as a library to build your custom FUSE implementation or other apps that work with encrypted data. # Motivation -Create a `simple`, `performant`, `modular` and `ergonomic` yet `very secure` `encrypted filesystem` to protect your `privacy` which is also `open souce` and uses `well known audited` crates as `cryptograhic primitives`. +Create a `simple`, `performant`, `modular` and `ergonomic` yet `very secure` `encrypted filesystem` to protect your `privacy` which is also `open souce` and is correctly and safely using `well known audited` crates as `cryptograhic primitives`. # A short story @@ -46,7 +46,7 @@ It was [crate of the week](https://this-week-in-rust.org/blog/2024/08/14/this-we - `Security` using well-known audited `AEAD` cryptography primitives - `Data integrity`, data is written with `WAL` to ensure integrity even on crash or power loss -- Hide all data for enhanced `privacy`, all metadata and content are encrypted +- Hide all data for enhanced `privacy`, all `metadata`, `content`, `file name`, `file size`, `*time` fields, `files count` are encrypted - Safe manage of `credentials` in memory with `mlock(2)`, `mprotect`, `zeroize` and `expiry` - `Performance`, `memory safety` and `optimized` for `concurrency` with Rust - Simplicity @@ -88,9 +88,9 @@ In progress: - [ring](https://crates.io/crates/ring) for encryption and [argon2](https://crates.io/crates/argon2) for key derivation function (generating key from password used to encrypt the master encryption key) - [rand_chacha](https://crates.io/crates/rand_chacha) for random generators -- [secrecy](https://crates.io/crates/secrecy) for keeping pass and encryption keys safe in memory and zeroing them when +- [shush-rs](https://crates.io/crates/shush-rs) for keeping pass and encryption keys safe in memory and zeroing them when not used. It keeps encryption keys in memory only while being used, and when not active it will release and zeroing - them in memory + them in memory. It locks memory page as well, preventing it from being written to swap. - [blake3](https://crates.io/crates/blake3) for hashing - password saved in OS keyring using [keyring](https://crates.io/crates/keyring) - [tracing](https://crates.io/crates/tracing) for logs @@ -99,6 +99,9 @@ In progress: - [Alternatives](https://alternativeto.net/software/encfs/) - [EncFS](https://vgough.github.io/encfs/) and [alternatives](https://alternativeto.net/software/encfs/) +- [CryFS](https://www.cryfs.org/) +- [gocryptfs](https://nuetzlich.net/gocryptfs/) +- [fscrypt](https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html) - [VeraCrypt](https://www.veracrypt.fr/code/VeraCrypt/?h=NewSysEncWizard) - [Cryptomator](https://cryptomator.org/) - [TrueCrypt](https://truecrypt.sourceforge.net/) @@ -112,18 +115,8 @@ In progress: ## What separates us -- Advanced `security` using well-known audited `AEAD` cryptography primitives -- `Data integrity`, data is written with `WAL` to ensure integrity even on crash or power loss -- `Performance`, `memory safety` and `optimized` for `concurrency` with Rust -- Simplicity -- Hide all data for enhanced `privacy`, all metadata and content are encrypted -- Safe manage of `credentials` in memory with `mlock(2)`, `mprotect`, `zeroize` and `expiry` -- `Multi-platform`, on all platforms -- `Fast seek` on both reads and writes -- `Writes in parallel` -- Exposed with `FUSE` -- Fully open source -- Use it as a libraty to build your own apps +[Asked](https://chatgpt.com/share/66e7a5a5-d254-8003-9359-9b1556b75fe9) ChatGPT if there are other solutions out there which offers all the key funcionalities we do, seems there are not :) Seems we are realy building a unique solution. +You can see the [key features](README.md#key-features) that separates us. # Usage @@ -278,6 +271,7 @@ You can see more [here](https://crates.io/crates/rencfs) ## Browser +If you want to give it a quick try and not setup anything locally you can [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/radumarias/rencfs) [![Open Rustlings On Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/?repo=radumarias%2Frencfs&ref=main) @@ -304,7 +298,8 @@ cat test.txt For now the `FUSE` (`fuse3` crate) only works on `Linux`, so to start the project you will need to be on Linux. Instead, you can [Develop inside a Container](#developing-inside-a-container), which will start a local Linux container, the IDE will connect to it, -you can build and start the app in there and also use terminal to test it. +you can build and start the app in there and also use terminal to test it. +On windows you can start it in [WSL](https://harsimranmaan.medium.com/install-and-setup-rust-development-environment-on-wsl2-dccb4bf63700). ### Getting the sources @@ -334,6 +329,12 @@ In that case please add it to the `PATH` manually. Project is setup to use `nightly` toolchain in `rust-toolchain.toml`, on first build you will see it fetch the nightly. +Make sure to add this you your `$PATH` too + +```bash +export PATH="$PATH::$HOME/.cargo/bin" +``` + ```bash cargo install cargo-aur cargo install cargo-generate-rpm @@ -346,19 +347,19 @@ Also, these deps are required (or based on your distribution): #### Arch ```bash -sudo pacman -Syu && sudo pacman -S fuse3 base-devel +sudo pacman -Syu && sudo pacman -S fuse3 base-devel act ``` #### Ubuntu ```bash -sudo apt-get update && sudo apt-get install fuse3 build-essential +sudo apt-get update && sudo apt-get install fuse3 build-essential act ``` #### Fedora ```bash -sudo dnf update && sudo dnf install fuse3 && dnf install @development-tools +sudo dnf update && sudo dnf install fuse3 && dnf install @development-tools act ``` ### Build for debug diff --git a/Ramp-up.md b/Ramp-up.md index 66738dd3..58cde4dd 100644 --- a/Ramp-up.md +++ b/Ramp-up.md @@ -1,11 +1,11 @@ -# Ramp up +# Ramp up guide -1. Read an [article](https://medium.com/system-weakness/hitchhikers-guide-to-building-a-distributed-filesystem-in-rust-the-very-beginning-2c02eb7313e7) and [one pager](The_Hitchhiker_s_Guide_to_Building_an_Encrypted_Filesystem_in_Rust-1.pdf) more about the project +1. Read an [article](https://medium.com/system-weakness/hitchhikers-guide-to-building-a-distributed-filesystem-in-rust-the-very-beginning-2c02eb7313e7) and [one pager](The_Hitchhiker_s_Guide_to_Building_an_Encrypted_Filesystem_in_Rust-1.pdf) to get more details about the project 2. Become familiar with the [concepts and features](https://github.com/radumarias/rencfs) and [lib docs](https://docs.rs/rencfs/latest/rencfs) 3. Understand the [layers](https://github.com/radumarias/rencfs/blob/main/website/resources/layers.png) -4. Give it a [quick try] with Docker](https://github.com/radumarias/rencfs#give-it-a-quick-try-with-docker), this is optional +4. Give it a [quick try](https://github.com/radumarias/rencfs#give-it-a-quick-try-with-docker) with Docker, this is optional 5. Or run it as [CLI](https://github.com/radumarias/rencfs?tab=readme-ov-file#command-line-tool) app 6. Clone or fork the repo. After you're added to the repo you can work in your branches in there, no need to fork it if you don't want to -7. Build from [source](https://github.com/radumarias/rencfs?tab=readme-ov-file#locally) and start it. In case you don't have Linux you can [develop inside a container](https://github.com/radumarias/rencfs?tab=readme-ov-file#developing-inside-a-container). This will start a new Linux container and remotely connect the local IDE to the container, you can also connect with IDE's terminal to it and run the code. On Windows you can use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) +7. [Build](https://github.com/radumarias/rencfs?tab=readme-ov-file#build-from-source) from source and start it. In case you don't have Linux you can [develop inside a container](https://github.com/radumarias/rencfs?tab=readme-ov-file#developing-inside-a-container). This will start a new Linux container and remotely connecting the local IDE to the container, you can also connect with IDE's terminal to it and run the code. On Windows you can use [WSL](https://harsimranmaan.medium.com/install-and-setup-rust-development-environment-on-wsl2-dccb4bf63700). As a last resort you can [develop in browser](https://github.com/radumarias/rencfs/blob/main/README.md#browser). 8. Run and understand the [examples](examples). You can write some new ones to better understand the flow and code, if you do, please create a `PR` back to the parent repo targeting the `main` branch to include those for others too 9. Become familiar with some [tests](https://github.com/radumarias/rencfs/blob/main/src/encryptedfs/test.rs) and benchmarks. You can write some new ones to better understand the flow and code, if you do, please create a `PR` back to the parent repo targeting the `main` branch to include those for others too diff --git a/check-before-push.bat b/check-before-push.bat new file mode 100755 index 00000000..45496568 --- /dev/null +++ b/check-before-push.bat @@ -0,0 +1,13 @@ +@echo off +set CARGO_TERM_COLOR=always +set RUSTFLAGS=-Dwarnings +set RUSTDOCFLAGS=-Dwarnings + +cargo fmt --all +if %errorlevel% neq 0 exit /b %errorlevel% + +cargo clippy --release --all-targets --fix --allow-dirty +if %errorlevel% neq 0 exit /b %errorlevel% + +act --action-offline-mode -W .github/workflows/build_and_tests_reusable.yaml +if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/check-before-push.sh b/check-before-push.sh new file mode 100755 index 00000000..d0981970 --- /dev/null +++ b/check-before-push.sh @@ -0,0 +1,11 @@ +#!/bin/zsh + +set -e + +export CARGO_TERM_COLOR=always +export RUSTFLAGS="-Dwarnings" +export RUSTDOCFLAGS="-Dwarnings" + +cargo fmt --all +cargo clippy --release --all-targets --fix --allow-dirty +act --action-offline-mode -W .github/workflows/build_and_tests_reusable.yaml diff --git a/examples/change_password.rs b/examples/change_password.rs index d4838cb3..fc01bd87 100644 --- a/examples/change_password.rs +++ b/examples/change_password.rs @@ -2,7 +2,7 @@ use core::str::FromStr; use rencfs::crypto::Cipher; use rencfs::encryptedfs::EncryptedFilesystem; use rencfs::encryptedfs::{EncryptedFs, FsError}; -use secrecy::SecretString; +use shush_rs::SecretString; use std::env::args; use std::path::Path; diff --git a/examples/change_password_cli.rs b/examples/change_password_cli.rs index 4ba7f98a..7c006b08 100644 --- a/examples/change_password_cli.rs +++ b/examples/change_password_cli.rs @@ -1,9 +1,9 @@ -use std::env::args; use std::io; use std::io::Write; +use std::{env::args, str::FromStr}; use rpassword::read_password; -use secrecy::{ExposeSecret, SecretString}; +use shush_rs::{ExposeSecret, SecretString}; use tracing::{error, info}; use rencfs::encryptedfs::EncryptedFilesystem; @@ -22,13 +22,13 @@ async fn main() { use rencfs::crypto::Cipher; print!("Enter old password: "); io::stdout().flush().unwrap(); - let old_password = SecretString::new(read_password().unwrap()); + let old_password = SecretString::from_str(&read_password().unwrap()).unwrap(); print!("Enter new password: "); io::stdout().flush().unwrap(); - let new_password = SecretString::new(read_password().unwrap()); + let new_password = SecretString::from_str(&read_password().unwrap()).unwrap(); print!("Confirm new password: "); io::stdout().flush().unwrap(); - let new_password2 = SecretString::new(read_password().unwrap()); + let new_password2 = SecretString::from_str(&read_password().unwrap()).unwrap(); if new_password.expose_secret() != new_password2.expose_secret() { error!("Passwords do not match"); return; diff --git a/examples/crypto_speed.rs b/examples/crypto_speed.rs index e99f6cfc..f9e8cfb4 100644 --- a/examples/crypto_speed.rs +++ b/examples/crypto_speed.rs @@ -8,7 +8,7 @@ use std::{fs, io}; use anyhow::Result; use rand_core::RngCore; -use secrecy::SecretVec; +use shush_rs::SecretVec; use rencfs::crypto; use rencfs::crypto::write::{CryptoInnerWriter, CryptoWrite}; @@ -156,5 +156,5 @@ where fn get_key(cipher: Cipher) -> io::Result> { let mut key = vec![0; cipher.key_len()]; crypto::create_rng().fill_bytes(key.as_mut_slice()); - Ok(SecretVec::new(key)) + Ok(SecretVec::from(key)) } diff --git a/examples/crypto_write_read.rs b/examples/crypto_write_read.rs index 6471f654..32181f8a 100644 --- a/examples/crypto_write_read.rs +++ b/examples/crypto_write_read.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io; use std::path::Path; -use secrecy::SecretVec; +use shush_rs::SecretVec; use tracing::info; use rencfs::crypto; @@ -18,7 +18,7 @@ fn main() -> Result<()> { let cipher = Cipher::ChaCha20Poly1305; let mut key = vec![0; cipher.key_len()]; crypto::create_rng().fill_bytes(key.as_mut_slice()); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let mut args = args(); // skip the program name diff --git a/examples/encryptedfs.rs b/examples/encryptedfs.rs index 05eb0d3a..d38236db 100644 --- a/examples/encryptedfs.rs +++ b/examples/encryptedfs.rs @@ -3,7 +3,7 @@ use std::fs; use std::path::Path; use anyhow::Result; -use secrecy::SecretString; +use shush_rs::SecretString; use rencfs::crypto::Cipher; use rencfs::encryptedfs::write_all_string_to_fs; diff --git a/examples/mount.rs b/examples/mount.rs index 30954f50..c93d2b16 100644 --- a/examples/mount.rs +++ b/examples/mount.rs @@ -4,7 +4,7 @@ use std::io; use std::path::Path; use anyhow::Result; -use secrecy::SecretString; +use shush_rs::SecretString; use tracing::info; use rencfs::crypto::Cipher; diff --git a/hooks/linux-macos/pre-commit b/hooks/linux-macos/pre-commit new file mode 100644 index 00000000..a135916c --- /dev/null +++ b/hooks/linux-macos/pre-commit @@ -0,0 +1,51 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +#else +# # If there are whitespace errors, print the offending file names and fail. +# exec git diff-index --check --cached $against -- +fi + +./check-before-push.sh diff --git a/hooks/windows/pre-commit b/hooks/windows/pre-commit new file mode 100644 index 00000000..15aa4632 --- /dev/null +++ b/hooks/windows/pre-commit @@ -0,0 +1,45 @@ +#!/usr/bin/env pwsh +# Pre-commit hook script for Git on Windows (PowerShell) +# Save this file as .git/hooks/pre-commit.ps1 + +# Check if we are committing to an existing branch or the initial commit +$against = "" +try { + git rev-parse --verify HEAD > $null 2>&1 + $against = "HEAD" +} catch { + # Initial commit: diff against an empty tree object + $against = git hash-object -t tree /dev/null +} + +# Get the allownonascii configuration value +$allownonascii = git config --type=bool hooks.allownonascii + +# Redirect output to stderr +$ErrorActionPreference = "Stop" + +# Cross-platform projects tend to avoid non-ASCII filenames; prevent them from being added to the repository +if ($allownonascii -ne $true) { + # Ensure there are no non-ASCII file names being added + $diff = git diff-index --cached --name-only --diff-filter=A -z $against | + ForEach-Object { $_.Trim([char]0) } + + foreach ($file in $diff) { + if ($file -cmatch '[^ -~]') { + Write-Host "Error: Attempt to add a non-ASCII file name." -ForegroundColor Red + Write-Host "This can cause problems if you want to work with people on other platforms." + Write-Host "To be portable it is advisable to rename the file." + Write-Host "If you know what you are doing, you can disable this check using:" + Write-Host " git config hooks.allownonascii true" -ForegroundColor Yellow + exit 1 + } + } +} + +# Call an additional script for checks before pushing (if applicable) +# Ensure that `check-before-push.ps1` exists in the repo +if (Test-Path "./check-before-push.ps1") { + & "./check-before-push.ps1" +} + +exit 0 diff --git a/java-bridge/Cargo.lock b/java-bridge/Cargo.lock index e9390d83..6c6227dd 100644 --- a/java-bridge/Cargo.lock +++ b/java-bridge/Cargo.lock @@ -1152,7 +1152,7 @@ dependencies = [ "ctrlc", "jni", "rencfs", - "secrecy", + "shush-rs", "tokio", "tracing", "tracing-appender", @@ -1212,9 +1212,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linux-keyutils" @@ -1741,8 +1741,8 @@ dependencies = [ "retainer", "ring", "rpassword", - "secrecy", "serde", + "shush-rs", "strum", "strum_macros", "subtle", @@ -1868,15 +1868,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "secrecy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" -dependencies = [ - "zeroize", -] - [[package]] name = "secret-service" version = "3.1.0" @@ -1987,6 +1978,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shush-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de8f82d4a4085f9ea4ab8d493e6e62ab871b2bf446d4d90633b58ca400aedff" +dependencies = [ + "errno", + "libc", + "windows-sys 0.59.0", + "zeroize", +] + [[package]] name = "signal-hook-registry" version = "1.4.2" diff --git a/java-bridge/Cargo.toml b/java-bridge/Cargo.toml index e83a45f3..ffca5756 100644 --- a/java-bridge/Cargo.toml +++ b/java-bridge/Cargo.toml @@ -24,5 +24,5 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" tracing-appender = "0.2.3" tokio = { version = "1.39.2", features = ["full"] } -secrecy = "0.8.0" +shush-rs = "0.1.10" ctrlc = { version = "3.1.9", features = ["termination"] } diff --git a/java-bridge/src/lib.rs b/java-bridge/src/lib.rs index 15d603f5..69d2799c 100644 --- a/java-bridge/src/lib.rs +++ b/java-bridge/src/lib.rs @@ -1,6 +1,6 @@ extern crate jni; extern crate rencfs; -extern crate secrecy; +extern crate shush_rs; extern crate tokio; extern crate tracing; @@ -13,7 +13,7 @@ use rencfs::crypto::Cipher; use rencfs::encryptedfs::PasswordProvider; use rencfs::log::log_init; use rencfs::mount::{create_mount_point, umount, MountHandle}; -use secrecy::SecretString; +use shush_rs::SecretString; use std::collections::BTreeMap; use std::ops::Add; use std::path::Path; diff --git a/src/crypto.rs b/src/crypto.rs index 516f68aa..a1e8f8f4 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -15,8 +15,8 @@ use num_format::{Locale, ToFormattedString}; use rand_chacha::rand_core::{CryptoRng, RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; use ring::aead::{AES_256_GCM, CHACHA20_POLY1305}; -use secrecy::{ExposeSecret, SecretString, SecretVec}; use serde::{Deserialize, Serialize}; +use shush_rs::{ExposeSecret, SecretString, SecretVec}; use strum_macros::{Display, EnumIter, EnumString}; use thiserror::Error; use tracing::{debug, error, instrument}; @@ -212,7 +212,7 @@ pub fn decrypt(s: &str, cipher: Cipher, key: &SecretVec) -> Result Resul Argon2::default() .hash_password_into(password.expose_secret().as_bytes(), salt, &mut dk) .map_err(|err| Error::GenericString(err.to_string()))?; - Ok(SecretVec::new(dk)) + Ok(SecretVec::new(Box::new(dk))) } #[allow(clippy::missing_errors_doc)] @@ -245,7 +245,7 @@ pub fn encrypt_file_name( "$." | "$.." => Ok(secret_string.clone()), "." | ".." => Ok(format!("${secret_string}")), _ => { - let secret = SecretString::from_str(secret_string) + let secret = SecretString::from_str(&secret_string) .map_err(|err| Error::GenericString(err.to_string()))?; let mut encrypted = encrypt(&secret, cipher, key)?; encrypted = encrypted.replace('/', "|"); @@ -258,9 +258,9 @@ pub fn encrypt_file_name( #[allow(clippy::missing_errors_doc)] #[must_use] pub fn hash_file_name(name: &SecretString) -> String { - if name.expose_secret() == "$." || name.expose_secret() == "$.." { + if *name.expose_secret() == "$." || *name.expose_secret() == "$.." { name.expose_secret().clone() - } else if name.expose_secret() == "." || name.expose_secret() == ".." { + } else if *name.expose_secret() == "." || *name.expose_secret() == ".." { format!("${}", name.expose_secret()) } else { hex::encode(hash_secret_string(name)) @@ -289,7 +289,7 @@ pub fn hash_secret_string(data: &SecretString) -> [u8; 32] { #[must_use] pub fn hash_secret_vec(data: &SecretVec) -> [u8; 32] { - hash(data.expose_secret()) + hash(&data.expose_secret()) } /// Copy from `pos` position in file `len` bytes @@ -386,7 +386,7 @@ mod tests { use super::*; use rand_core::RngCore; - use secrecy::{ExposeSecret, Secret, SecretString, SecretVec}; + use shush_rs::{ExposeSecret, SecretString, SecretVec}; use std::{ fs::File, io::{self, Write}, @@ -397,7 +397,7 @@ mod tests { fn create_encrypted_file( content: &str, cipher: Cipher, - key: &Secret>, + key: &SecretVec, ) -> (TempDir, PathBuf) { let temp_dir = tempdir().unwrap(); let file_path = temp_dir.path().join("test_file.txt"); @@ -423,15 +423,15 @@ mod tests { (temp_dir, encrypted_file_path) } - fn secret_key(cipher: Cipher) -> Secret> { + fn secret_key(cipher: Cipher) -> SecretVec { let mut key = vec![0; cipher.key_len()]; create_rng().fill_bytes(&mut key); - SecretVec::new(key) + SecretVec::new(Box::new(key)) } #[test] fn test_simple_encrypt_and_decrypt() { - let secret = SecretString::new("Test secret".to_string()); + let secret = SecretString::from_str("Test secret").unwrap(); for &cipher in &[Cipher::ChaCha20Poly1305, Cipher::Aes256Gcm] { let key = secret_key(cipher); @@ -444,7 +444,7 @@ mod tests { #[test] fn test_encrypt_and_decrypt_file_name() { - let secret_name = SecretString::new("testfile.txt".to_string()); + let secret_name = SecretString::from_str("testfile.txt").unwrap(); for &cipher in &[Cipher::ChaCha20Poly1305, Cipher::Aes256Gcm] { let key = secret_key(cipher); @@ -453,7 +453,7 @@ mod tests { assert_eq!(decrypted.expose_secret(), secret_name.expose_secret()); } - let secret_name = SecretString::new("testfile\\With/slash.txt".to_string()); + let secret_name = SecretString::from_str("testfile\\With/slash.txt").unwrap(); for &cipher in &[Cipher::ChaCha20Poly1305, Cipher::Aes256Gcm] { let key = secret_key(cipher); @@ -466,7 +466,7 @@ mod tests { #[test] fn test_encrypt_and_decrypt_file_name_invalid_cipher() { let key = secret_key(Cipher::ChaCha20Poly1305); - let secret_name = SecretString::new("testfile.txt".to_string()); + let secret_name = SecretString::from_str("testfile.txt").unwrap(); let encrypted = encrypt_file_name(&secret_name, Cipher::ChaCha20Poly1305, &key).unwrap(); let result = decrypt_file_name(&encrypted, Cipher::Aes256Gcm, &key); @@ -475,7 +475,7 @@ mod tests { #[test] fn test_derive_key() { - let password = SecretString::new("password".to_string()); + let password = SecretString::from_str("password").unwrap(); let salt = b"salt_of_pass"; for &cipher in &[Cipher::ChaCha20Poly1305, Cipher::Aes256Gcm] { @@ -486,7 +486,7 @@ mod tests { #[test] fn test_derive_key_consistency() { - let password = SecretString::new("password".to_string()); + let password = SecretString::from_str("password").unwrap(); let salt = b"random_salt"; let derived_key_1 = derive_key(&password, Cipher::ChaCha20Poly1305, salt).unwrap(); @@ -497,7 +497,7 @@ mod tests { #[test] fn test_derive_key_empty_salt() { - let empty_password = SecretString::new("password".to_string()); + let empty_password = SecretString::from_str("password").unwrap(); let empty_salt = b""; let result = derive_key(&empty_password, Cipher::ChaCha20Poly1305, empty_salt); @@ -508,7 +508,7 @@ mod tests { #[test] fn test_derive_key_uniqueness() { - let password = SecretString::new("password".to_string()); + let password = SecretString::from_str("password").unwrap(); let salts = vec![b"random_salt1", b"random_salt2", b"random_salt3"]; let mut derived_keys = std::collections::HashSet::new(); @@ -525,12 +525,12 @@ mod tests { for &cipher in &[Cipher::ChaCha20Poly1305, Cipher::Aes256Gcm] { let key = secret_key(cipher); - let data = SecretString::new("A".to_string()); + let data = SecretString::from_str("A").unwrap(); let encrypted = encrypt(&data, cipher, &key).unwrap(); let decrypted = decrypt(&encrypted, cipher, &key).unwrap(); assert_eq!(decrypted.expose_secret(), data.expose_secret()); - let large_data = SecretString::new("A".repeat(1024 * 1024)); // 1 MB + let large_data = SecretString::from_str("A".repeat(1024 * 1024).as_str()).unwrap(); // 1 MB let encrypted = encrypt(&large_data, cipher, &key).unwrap(); let decrypted = decrypt(&encrypted, cipher, &key).unwrap(); assert_eq!(decrypted.expose_secret(), large_data.expose_secret()); @@ -539,43 +539,43 @@ mod tests { #[test] fn test_encrypt_decrypt_empty_string() { - let key = SecretVec::new(vec![0; 32]); - let secret = SecretString::new("".to_string()); + let key = SecretVec::from(vec![0; 32]); + let secret = SecretString::new(Box::new("".to_string())); let encrypted = encrypt(&secret, Cipher::ChaCha20Poly1305, &key).unwrap(); let decrypted = decrypt(&encrypted, Cipher::ChaCha20Poly1305, &key).unwrap(); - assert_eq!(decrypted.expose_secret(), ""); + assert_eq!(*decrypted.expose_secret(), ""); } #[test] fn test_hash_file_name_special_cases() { let expected = "$.".to_string(); - let name = SecretString::new(expected.clone()); + let name = SecretString::new(Box::new(expected.clone())); let result = hash_file_name(&name); assert_eq!(result, expected); let expected = "$..".to_string(); - let name = SecretString::new(expected.clone()); + let name = SecretString::new(Box::new(expected.clone())); let result = hash_file_name(&name); assert_eq!(result, expected); let input = ".".to_string(); let expected = "$.".to_string(); - let name = SecretString::new(input); + let name = SecretString::new(Box::new(input)); let result = hash_file_name(&name); assert_eq!(result, expected); let input = "..".to_string(); let expected = "$..".to_string(); - let name = SecretString::new(input); + let name = SecretString::new(Box::new(input)); let result = hash_file_name(&name); assert_eq!(result, expected); } #[test] fn test_hash_file_name_regular_case() { - let name = SecretString::new("filename.txt".to_string()); + let name = SecretString::new(Box::new("filename.txt".to_string())); let result = hash_file_name(&name); let expected_hash = hex::encode(hash_secret_string(&name)); assert_eq!(result, expected_hash); @@ -583,7 +583,7 @@ mod tests { #[test] fn test_hash_secret_string() { - let secret = SecretString::new("hash this secret".to_string()); + let secret = SecretString::new(Box::new("hash this secret".to_string())); let expected_hash_hex = "d820cbf278fc742d8ec30e43947674689cd06d5aa9b71a2f9afe162a4ce408dc"; let hash_hex = hex::encode(hash_secret_string(&secret)); @@ -613,7 +613,7 @@ mod tests { #[test] fn test_copy_from_file_exact_zero_length() { - let key = SecretVec::new(vec![0; 32]); + let key = SecretVec::from(vec![0; 32]); let (_temp_dir, file_path) = create_encrypted_file("Hello, world!", Cipher::ChaCha20Poly1305, &key); diff --git a/src/crypto/buf_mut.rs b/src/crypto/buf_mut.rs index 1b662a3e..cb4963c7 100644 --- a/src/crypto/buf_mut.rs +++ b/src/crypto/buf_mut.rs @@ -2,7 +2,7 @@ use std::cmp::min; use std::io; use std::io::{Read, SeekFrom, Write}; -use secrecy::Zeroize; +use shush_rs::Zeroize; pub struct BufMut { // TODO: use secrets to benefit of mlock() diff --git a/src/crypto/read.rs b/src/crypto/read.rs index 387a6043..91ad1e35 100644 --- a/src/crypto/read.rs +++ b/src/crypto/read.rs @@ -6,7 +6,7 @@ use ring::aead::{ Aad, Algorithm, BoundKey, Nonce, NonceSequence, OpeningKey, UnboundKey, NONCE_LEN, }; use ring::error; -use secrecy::{ExposeSecret, SecretVec}; +use shush_rs::{ExposeSecret, SecretVec}; use tracing::{error, instrument, warn}; use crate::crypto::buf_mut::BufMut; @@ -91,7 +91,7 @@ impl RingCryptoRead { let ciphertext_block_size = NONCE_LEN + BLOCK_SIZE + algorithm.tag_len(); let buf = BufMut::new(vec![0; ciphertext_block_size]); let last_nonce = Arc::new(Mutex::new(None)); - let unbound_key = UnboundKey::new(algorithm, key.expose_secret()).unwrap(); + let unbound_key = UnboundKey::new(algorithm, &key.expose_secret()).unwrap(); let nonce_sequence = ExistingNonceSequence::new(last_nonce.clone()); let opening_key = OpeningKey::new(unbound_key, nonce_sequence); Self { diff --git a/src/crypto/read/bench.rs b/src/crypto/read/bench.rs index c27abb43..91b46a30 100644 --- a/src/crypto/read/bench.rs +++ b/src/crypto/read/bench.rs @@ -7,7 +7,7 @@ fn bench_read_1mb_chacha_file(b: &mut Bencher) { use crate::crypto::write::CryptoWrite; use crate::crypto::Cipher; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use std::io; use std::io::Seek; use test::black_box; @@ -17,7 +17,7 @@ fn bench_read_1mb_chacha_file(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let file = tempfile::tempfile().unwrap(); let mut writer = crypto::create_write(file, cipher, &key); @@ -43,7 +43,7 @@ fn bench_read_1mb_aes_file(b: &mut Bencher) { use crate::crypto::write::CryptoWrite; use crate::crypto::Cipher; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use std::io; use std::io::Seek; use test::black_box; @@ -53,7 +53,7 @@ fn bench_read_1mb_aes_file(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let file = tempfile::tempfile().unwrap(); let mut writer = crypto::create_write(file, cipher, &key); @@ -79,7 +79,7 @@ fn bench_read_1mb_chacha_ram(b: &mut Bencher) { use crate::crypto::write::CryptoWrite; use crate::crypto::Cipher; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use std::io; use std::io::Seek; use test::black_box; @@ -89,7 +89,7 @@ fn bench_read_1mb_chacha_ram(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let cursor_write = io::Cursor::new(vec![]); let mut writer = crypto::create_write(cursor_write, cipher, &key); @@ -115,7 +115,7 @@ fn bench_read_1mb_aes_ram(b: &mut Bencher) { use crate::crypto::write::CryptoWrite; use crate::crypto::Cipher; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use std::io; use std::io::Seek; use test::black_box; @@ -125,7 +125,7 @@ fn bench_read_1mb_aes_ram(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let cursor_write = io::Cursor::new(vec![]); let mut writer = crypto::create_write(cursor_write, cipher, &key); diff --git a/src/crypto/read/test.rs b/src/crypto/read/test.rs index ff256c65..1c6ba587 100644 --- a/src/crypto/read/test.rs +++ b/src/crypto/read/test.rs @@ -3,7 +3,7 @@ use super::CryptoRead; #[allow(unused_imports)] use ring::aead::AES_256_GCM; #[allow(unused_imports)] -use secrecy::SecretVec; +use shush_rs::SecretVec; #[allow(unused_imports)] use std::io::{self, Seek}; #[allow(unused_imports)] @@ -11,10 +11,10 @@ use tracing_test::traced_test; #[allow(dead_code)] fn create_secret_key(key_len: usize) -> SecretVec { use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; let mut key = vec![0; key_len]; rand::thread_rng().fill_bytes(&mut key); - SecretVec::new(key) + SecretVec::new(Box::new(key)) } #[allow(dead_code)] fn create_encrypted_data(data: &[u8], key: &SecretVec) -> Vec { @@ -169,7 +169,7 @@ fn test_ring_crypto_read_seek_chacha() { use std::io::{Cursor, Read, Seek, SeekFrom, Write}; use ring::aead::CHACHA20_POLY1305; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto::read::RingCryptoRead; use crate::crypto::write::{CryptoWrite, RingCryptoWrite}; @@ -180,7 +180,7 @@ fn test_ring_crypto_read_seek_chacha() { let algorithm = &CHACHA20_POLY1305; // Create a key for encryption - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -228,7 +228,7 @@ fn test_ring_crypto_read_seek_aes() { let algorithm = &AES_256_GCM; // Create a key for encryption - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, true, algorithm, &key); @@ -279,7 +279,7 @@ fn test_ring_crypto_read_seek_blocks_chacha() { // Create a key for encryption let algorithm = &CHACHA20_POLY1305; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -330,7 +330,7 @@ fn test_ring_crypto_read_seek_blocks_aes() { // Create a key for encryption let algorithm = &AES_256_GCM; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, true, algorithm, &key); @@ -381,7 +381,7 @@ fn test_ring_crypto_read_seek_blocks_boundary_chacha() { // Create a key for encryption let algorithm = &CHACHA20_POLY1305; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -429,7 +429,7 @@ fn test_ring_crypto_read_seek_blocks_boundary_aes() { // Create a key for encryption let algorithm = &AES_256_GCM; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, true, algorithm, &key); @@ -477,7 +477,7 @@ fn test_ring_crypto_read_seek_skip_blocks_chacha() { // Create a key for encryption let algorithm = &CHACHA20_POLY1305; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -513,7 +513,7 @@ fn test_ring_crypto_read_seek_skip_blocks_aes() { // Create a key for encryption let algorithm = &AES_256_GCM; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -549,7 +549,7 @@ fn test_ring_crypto_read_seek_in_second_block() { // Create a key for encryption let algorithm = &AES_256_GCM; - let key = SecretVec::new(vec![0; algorithm.key_len()]); + let key = SecretVec::new(Box::new(vec![0; algorithm.key_len()])); // write the data let mut writer = RingCryptoWrite::new(cursor, false, algorithm, &key); @@ -571,7 +571,8 @@ fn test_ring_crypto_read_seek_in_second_block() { fn finish_seek() { use super::RingCryptoRead; let reader = io::Cursor::new(vec![0; 10]); - let mut reader = RingCryptoRead::new_seek(reader, &AES_256_GCM, &SecretVec::new(vec![0; 32])); + let mut reader = + RingCryptoRead::new_seek(reader, &AES_256_GCM, &SecretVec::new(Box::new(vec![0; 32]))); let mut reader = reader.into_inner(); let _ = reader.seek(io::SeekFrom::Start(0)); } @@ -582,7 +583,7 @@ fn reader_only_read() { use std::io::Read; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::Cipher; @@ -597,7 +598,7 @@ fn reader_only_read() { let cipher = Cipher::Aes256Gcm; let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let reader = ReadOnly {}; let _reader = crypto::create_read(reader, cipher, &key); @@ -611,7 +612,7 @@ fn reader_with_seeks() { use std::io::{self, Seek, SeekFrom}; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::read::BLOCK_SIZE; @@ -621,7 +622,7 @@ fn reader_with_seeks() { let cipher = Cipher::Aes256Gcm; let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::new(Box::new(key)); let len = BLOCK_SIZE * 3 + 42; diff --git a/src/crypto/write.rs b/src/crypto/write.rs index 1283ec9b..9de2785d 100644 --- a/src/crypto/write.rs +++ b/src/crypto/write.rs @@ -9,7 +9,7 @@ use ring::aead::{ Aad, Algorithm, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, UnboundKey, NONCE_LEN, }; use ring::error::Unspecified; -use secrecy::{ExposeSecret, SecretVec}; +use shush_rs::{ExposeSecret, SecretVec}; use tracing::error; use crate::crypto::buf_mut::BufMut; @@ -89,7 +89,7 @@ impl RingCryptoWrite { algorithm: &'static Algorithm, key: &SecretVec, ) -> Self { - let unbound_key = UnboundKey::new(algorithm, key.expose_secret()).expect("unbound key"); + let unbound_key = UnboundKey::new(algorithm, &key.expose_secret()).expect("unbound key"); let nonce_sequence = Arc::new(Mutex::new(RandomNonceSequence::default())); let wrapping_nonce_sequence = RandomNonceSequenceWrapper::new(nonce_sequence.clone()); let sealing_key = SealingKey::new(unbound_key, wrapping_nonce_sequence); @@ -97,7 +97,7 @@ impl RingCryptoWrite { let (last_nonce, opening_key, decrypt_buf) = if writer.as_write_seek_read().is_some() { let last_nonce = Arc::new(Mutex::new(None)); - let unbound_key = UnboundKey::new(algorithm, key.expose_secret()).unwrap(); + let unbound_key = UnboundKey::new(algorithm, &key.expose_secret()).unwrap(); let nonce_sequence2 = ExistingNonceSequence::new(last_nonce.clone()); let opening_key = OpeningKey::new(unbound_key, nonce_sequence2); let ciphertext_block_size = NONCE_LEN + BLOCK_SIZE + algorithm.tag_len(); diff --git a/src/crypto/write/bench.rs b/src/crypto/write/bench.rs index cf06bad1..7e17b5a5 100644 --- a/src/crypto/write/bench.rs +++ b/src/crypto/write/bench.rs @@ -7,7 +7,7 @@ fn bench_writer_1mb_cha_cha20poly1305_file(b: &mut Bencher) { use std::io; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::CryptoWrite; @@ -19,7 +19,7 @@ fn bench_writer_1mb_cha_cha20poly1305_file(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let rnd_reader = RandomReader::new(len); b.iter(|| { @@ -38,7 +38,7 @@ fn bench_writer_1mb_aes256gcm_file(b: &mut Bencher) { use std::io; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::CryptoWrite; @@ -50,7 +50,7 @@ fn bench_writer_1mb_aes256gcm_file(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let rnd_reader = RandomReader::new(len); b.iter(|| { @@ -69,7 +69,7 @@ fn bench_writer_1mb_cha_cha20poly1305_mem(b: &mut Bencher) { use std::io; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::CryptoWrite; @@ -81,7 +81,7 @@ fn bench_writer_1mb_cha_cha20poly1305_mem(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let rnd_reader = RandomReader::new(len); b.iter(|| { @@ -101,7 +101,7 @@ fn bench_writer_1mb_aes256gcm_mem(b: &mut Bencher) { use std::io; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::CryptoWrite; @@ -113,7 +113,7 @@ fn bench_writer_1mb_aes256gcm_mem(b: &mut Bencher) { let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let rnd_reader = RandomReader::new(len); b.iter(|| { diff --git a/src/crypto/write/test.rs b/src/crypto/write/test.rs index d3daa624..3a5bcb9d 100644 --- a/src/crypto/write/test.rs +++ b/src/crypto/write/test.rs @@ -1,7 +1,7 @@ use std::io::{self, Seek, SeekFrom}; use ring::aead::{Aad, Algorithm, BoundKey, OpeningKey, UnboundKey, NONCE_LEN}; -use secrecy::{ExposeSecret, SecretVec}; +use shush_rs::{ExposeSecret, SecretVec}; use std::sync::{Arc, Mutex}; #[allow(unused_imports)] use tracing_test::traced_test; @@ -13,10 +13,10 @@ use crate::crypto::Cipher; #[allow(dead_code)] fn create_secret_key(key_len: usize) -> SecretVec { use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; let mut key = vec![0; key_len]; rand::thread_rng().fill_bytes(&mut key); - SecretVec::new(key) + SecretVec::from(key) } #[allow(dead_code)] @@ -1315,7 +1315,7 @@ fn writer_only_write() { use std::io::{self, Write}; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::{CryptoInnerWriter, WriteSeekRead}; @@ -1345,7 +1345,7 @@ fn writer_only_write() { let cipher = Cipher::Aes256Gcm; let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let writer = WriteOnly {}; let _writer = crypto::create_write(writer, cipher, &key); @@ -1359,7 +1359,7 @@ fn writer_with_seeks() { use std::io::{self, Cursor, Seek, SeekFrom}; use rand::RngCore; - use secrecy::SecretVec; + use shush_rs::SecretVec; use crate::crypto; use crate::crypto::write::BLOCK_SIZE; @@ -1368,7 +1368,7 @@ fn writer_with_seeks() { let cipher = Cipher::Aes256Gcm; let mut key: Vec = vec![0; cipher.key_len()]; rand::thread_rng().fill_bytes(&mut key); - let key = SecretVec::new(key); + let key = SecretVec::from(key); let len = BLOCK_SIZE * 3 + 42; diff --git a/src/encryptedfs.rs b/src/encryptedfs.rs index 70afaded..102393c9 100644 --- a/src/encryptedfs.rs +++ b/src/encryptedfs.rs @@ -3,8 +3,8 @@ use async_trait::async_trait; use futures_util::TryStreamExt; use lru::LruCache; use num_format::{Locale, ToFormattedString}; -use secrecy::{ExposeSecret, SecretString, SecretVec}; use serde::{Deserialize, Serialize}; +use shush_rs::{ExposeSecret, SecretBox, SecretString, SecretVec}; use std::backtrace::Backtrace; use std::collections::{HashMap, HashSet, VecDeque}; use std::fmt::Debug; @@ -407,7 +407,7 @@ impl From for SetFileAttr { #[derive(Debug, Clone)] pub struct DirectoryEntry { pub ino: u64, - pub name: SecretString, + pub name: SecretBox, pub kind: FileType, } @@ -423,7 +423,7 @@ impl PartialEq for DirectoryEntry { #[derive(Debug)] pub struct DirectoryEntryPlus { pub ino: u64, - pub name: SecretString, + pub name: SecretBox, pub kind: FileType, pub attr: FileAttr, } @@ -567,7 +567,7 @@ pub struct EncryptedFs { self_weak: std::sync::Mutex>>, attr_cache: ExpireValue>, FsError, AttrCacheProvider>, dir_entries_name_cache: - ExpireValue>, FsError, DirEntryNameCacheProvider>, + ExpireValue>>, FsError, DirEntryNameCacheProvider>, dir_entries_meta_cache: ExpireValue, FsError, DirEntryMetaCacheProvider>, sizes_write: Mutex>, @@ -737,7 +737,7 @@ impl EncryptedFilesystem for EncryptedFs { read: bool, write: bool, ) -> FsResult<(u64, FileAttr)> { - if name.expose_secret() == "." || name.expose_secret() == ".." { + if *name.expose_secret() == "." || *name.expose_secret() == ".." { return Err(FsError::InvalidInput("name cannot be '.' or '..'")); } if !self.exists(parent) { @@ -811,7 +811,7 @@ impl EncryptedFilesystem for EncryptedFs { attr_clone.ino, &DirectoryEntry { ino: attr_clone.ino, - name: SecretString::from_str("$.").expect("cannot parse"), + name: SecretString::new(Box::new("$.".into())), kind: FileType::Directory, }, ) @@ -821,7 +821,7 @@ impl EncryptedFilesystem for EncryptedFs { attr_clone.ino, &DirectoryEntry { ino: parent, - name: SecretString::from_str("$..").expect("cannot parse"), + name: SecretString::new(Box::new("$..".into())), kind: FileType::Directory, }, ) @@ -1750,9 +1750,9 @@ impl EncryptedFilesystem for EncryptedFs { async fn rename( &self, parent: u64, - name: &SecretString, + name: &SecretBox, new_parent: u64, - new_name: &SecretString, + new_name: &SecretBox, ) -> FsResult<()> { if self.read_only { return Err(FsError::ReadOnly); @@ -1812,7 +1812,7 @@ impl EncryptedFilesystem for EncryptedFs { attr.ino, &DirectoryEntry { ino: new_parent, - name: SecretString::from_str("$..").expect("cannot parse"), + name: SecretBox::new(Box::new("$..".to_string())), kind: FileType::Directory, }, ) @@ -1889,8 +1889,8 @@ impl EncryptedFilesystem for EncryptedFs { /// Change the password of the filesystem used to access the encryption key. async fn passwd( data_dir: &Path, - old_password: SecretString, - new_password: SecretString, + old_password: SecretBox, + new_password: SecretBox, cipher: Cipher, ) -> FsResult<()> { check_structure(data_dir, false).await?; @@ -1903,12 +1903,12 @@ impl EncryptedFilesystem for EncryptedFs { let reader = crypto::create_read(File::open(enc_file)?, cipher, &initial_key); let key: Vec = bincode::deserialize_from(reader).map_err(|_| FsError::InvalidPassword)?; - let key = SecretVec::new(key); + let key = SecretBox::new(Box::new(key)); // encrypt it with a new key derived from new password let new_key = crypto::derive_key(&new_password, cipher, &salt)?; crypto::atomic_serialize_encrypt_into( &data_dir.join(SECURITY_DIR).join(KEY_ENC_FILENAME), - &key.expose_secret(), + &*key.expose_secret(), cipher, &new_key, )?; @@ -2576,7 +2576,7 @@ fn read_or_create_key( let reader = crypto::create_read(File::open(key_path)?, cipher, &derived_key); let key: Vec = bincode::deserialize_from(reader).map_err(|_| FsError::InvalidPassword)?; - Ok(SecretVec::new(key)) + Ok(SecretBox::new(Box::new(key))) } else { // first time, create a random key and encrypt it with the derived key from password let mut key: Vec = vec![]; @@ -2597,7 +2597,7 @@ fn read_or_create_key( let file = writer.finish()?; file.sync_all()?; File::open(key_path.parent().unwrap())?.sync_all()?; - Ok(SecretVec::new(key)) + Ok(SecretBox::new(Box::new(key))) } } diff --git a/src/encryptedfs/bench.rs b/src/encryptedfs/bench.rs index 1d6d7516..98819566 100644 --- a/src/encryptedfs/bench.rs +++ b/src/encryptedfs/bench.rs @@ -6,7 +6,7 @@ use test::{black_box, Bencher}; #[allow(unused_imports)] use rand::Rng; #[allow(unused_imports)] -use secrecy::SecretString; +use shush_rs::SecretString; #[allow(unused_imports)] use crate::encryptedfs::EncryptedFilesystem; diff --git a/src/encryptedfs/test.rs b/src/encryptedfs/test.rs index 2fa2e3ee..7c9d000a 100644 --- a/src/encryptedfs/test.rs +++ b/src/encryptedfs/test.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use std::string::ToString; use std::time::SystemTime; -use secrecy::{ExposeSecret, SecretString}; +use shush_rs::{ExposeSecret, SecretString}; use tracing_test::traced_test; use crate::crypto::Cipher; @@ -574,7 +574,7 @@ async fn test_read_dir() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); assert_eq!(entries.len(), 2); @@ -601,7 +601,7 @@ async fn test_read_dir() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); let mut sample = vec![ @@ -621,7 +621,7 @@ async fn test_read_dir() { kind: FileType::Directory, }, ]; - sample.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(entries.len(), 3); assert_eq!(sample, entries); @@ -669,7 +669,7 @@ async fn test_read_dir() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); assert_eq!(entries.len(), 2); @@ -691,7 +691,7 @@ async fn test_read_dir() { let iter = fs.read_dir(parent).await.unwrap(); let mut entries: Vec = iter.map(Result::unwrap).collect(); - entries.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); let mut sample = vec![ DirectoryEntry { ino: parent, @@ -719,7 +719,7 @@ async fn test_read_dir() { kind: FileType::Directory, }, ]; - sample.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(entries.len(), 5); assert_eq!(sample, entries); }, @@ -770,7 +770,7 @@ async fn test_read_dir_plus() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); @@ -803,7 +803,7 @@ async fn test_read_dir_plus() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); @@ -829,7 +829,7 @@ async fn test_read_dir_plus() { attr: dir_attr, }, ]; - sample.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(entries.len(), 3); assert_eq!(sample, entries); @@ -867,7 +867,7 @@ async fn test_read_dir_plus() { .unwrap() .name .expose_secret() - .cmp(b.as_ref().unwrap().name.expose_secret()) + .cmp(&*b.as_ref().unwrap().name.expose_secret()) }); let entries: Vec = entries.into_iter().map(Result::unwrap).collect(); @@ -894,7 +894,7 @@ async fn test_read_dir_plus() { let iter = fs.read_dir_plus(parent).await.unwrap(); let mut entries: Vec = iter.map(Result::unwrap).collect(); - entries.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); // reload it as atime is changed on read_dir*() let attr_parent = fs.get_attr(attr_parent.ino).await.unwrap(); let mut sample = vec![ @@ -923,7 +923,7 @@ async fn test_read_dir_plus() { attr: dir_attr, }, ]; - sample.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + sample.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(entries.len(), 4); assert_eq!(sample, entries); }, @@ -1240,7 +1240,7 @@ async fn test_create() { .unwrap() .map(Result::unwrap) .collect(); - entries.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(attr, entries[1].attr); assert!(fs.exists_by_name(ROOT_INODE, &test_file).unwrap()); assert_eq!( @@ -1290,7 +1290,7 @@ async fn test_create() { .unwrap() .map(Result::unwrap) .collect(); - entries.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(ROOT_INODE, entries[0].attr.ino); assert_eq!(attr, entries[1].attr); assert!(fs.exists_by_name(ROOT_INODE, &test_dir).unwrap()); @@ -1341,7 +1341,7 @@ async fn test_create() { .unwrap() .map(Result::unwrap) .collect(); - entries.sort_by(|a, b| a.name.expose_secret().cmp(b.name.expose_secret())); + entries.sort_by(|a, b| a.name.expose_secret().cmp(&*b.name.expose_secret())); assert_eq!(attr, entries[2].attr); assert_eq!(parent, entries[0].attr.ino); assert!(fs.exists_by_name(parent, &test_dir_2).unwrap()); @@ -1503,7 +1503,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -1511,7 +1511,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -1565,7 +1565,7 @@ async fn test_rename() { .unwrap() .filter(|entry| { let file_new = "file-new"; - entry.as_ref().unwrap().name.expose_secret() == file_new + *entry.as_ref().unwrap().name.expose_secret() == file_new }) .count(), 0 @@ -1649,7 +1649,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -1657,7 +1657,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -1783,7 +1783,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -1791,7 +1791,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -1915,7 +1915,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -1923,7 +1923,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -2048,7 +2048,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -2056,7 +2056,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -2129,7 +2129,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -2137,7 +2137,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); @@ -2223,7 +2223,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == "..") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == "..") .count(), 1 ); @@ -2231,7 +2231,7 @@ async fn test_rename() { fs.read_dir(new_attr.ino) .await .unwrap() - .filter(|entry| entry.as_ref().unwrap().name.expose_secret() == ".") + .filter(|entry| *entry.as_ref().unwrap().name.expose_secret() == ".") .count(), 1 ); diff --git a/src/expire_value.rs b/src/expire_value.rs index f094c011..197c4ab8 100644 --- a/src/expire_value.rs +++ b/src/expire_value.rs @@ -16,6 +16,10 @@ pub trait ValueProvider: Send + Sync + 'sta async fn provide(&self) -> Result; } +/// It keeps the value in memory while it's being used and while there are strong references to it. +/// +/// After the specified `duration` it will remove it from internal cache and just keep it while there are strong references to it, after which it will be zeroized and dropped from memory. +// Helps mitigate against [Cold boot attack](https://en.wikipedia.org/wiki/Cold_boot_attack) by expiring values from memory. pub struct ExpireValue< T: Send + Sync + 'static, E: Error + Send + Sync + 'static, diff --git a/src/keyring.rs b/src/keyring.rs index 08b3baee..b2fb96e2 100644 --- a/src/keyring.rs +++ b/src/keyring.rs @@ -1,5 +1,7 @@ +use std::str::FromStr; + use keyring::Entry; -use secrecy::{ExposeSecret, SecretString}; +use shush_rs::{ExposeSecret, SecretString}; #[allow(dead_code)] const KEYRING_SERVICE: &str = "rencfs"; @@ -9,7 +11,7 @@ const KEYRING_USER: &str = "encrypted_fs"; #[allow(dead_code)] pub(crate) fn save(password: &SecretString, suffix: &str) -> Result<(), keyring::Error> { let entry = Entry::new(KEYRING_SERVICE, &format!("{KEYRING_USER}.{suffix}"))?; - entry.set_password(password.expose_secret()) + entry.set_password(&password.expose_secret()) } #[allow(dead_code)] @@ -21,5 +23,5 @@ pub(crate) fn remove(suffix: &str) -> Result<(), keyring::Error> { #[allow(dead_code)] pub(crate) fn get(suffix: &str) -> Result { let entry = Entry::new(KEYRING_SERVICE, &format!("{KEYRING_USER}.{suffix}"))?; - Ok(SecretString::new(entry.get_password()?)) + Ok(SecretString::from_str(&entry.get_password()?).unwrap()) } diff --git a/src/lib.rs b/src/lib.rs index 14a123d6..d957eb22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #![feature(test)] #![feature(error_generic_member_access)] #![feature(seek_stream_len)] -#![feature(const_refs_to_cell)] #![feature(box_into_inner)] //! # Encrypted File System //! @@ -28,7 +27,7 @@ //! use tracing::info; //! //! use anyhow::Result; -//! use secrecy::SecretString; +//! use shush_rs::SecretString; //! //! use rencfs::crypto::Cipher; //! use rencfs::encryptedfs::PasswordProvider; @@ -86,7 +85,7 @@ //! ``` //! use std::fs; //! use std::str::FromStr; -//! use secrecy::SecretString; +//! use shush_rs::SecretString; //! use rencfs::encryptedfs::{EncryptedFs, FileType, PasswordProvider, CreateFileAttr}; //! use rencfs::crypto::Cipher; //! use anyhow::Result; @@ -145,7 +144,7 @@ //! ```no_run //! use rencfs::crypto::Cipher; //! use rencfs::encryptedfs::{EncryptedFs, FsError}; -//! use secrecy::SecretString; +//! use shush_rs::SecretString; //! use std::env::args; //! use std::path::Path; //! use std::str::FromStr; @@ -184,7 +183,7 @@ //! use std::str::FromStr; //! //! use rpassword::read_password; -//! use secrecy::{ExposeSecret, SecretString}; +//! use shush_rs::{ExposeSecret, SecretString}; //! use tracing::{error, info}; //! //! use rencfs::encryptedfs::{EncryptedFs, FsError}; @@ -201,13 +200,13 @@ //! use rencfs::crypto::Cipher; //! print!("Enter old password: "); //! io::stdout().flush().unwrap(); -//! let old_password = SecretString::new(read_password().unwrap()); +//! let old_password = SecretString::from_str(&read_password().unwrap()).unwrap(); //! print!("Enter new password: "); //! io::stdout().flush().unwrap(); -//! let new_password = SecretString::new(read_password().unwrap()); +//! let new_password = SecretString::from_str(&read_password().unwrap()).unwrap(); //! print!("Confirm new password: "); //! io::stdout().flush().unwrap(); -//! let new_password2 = SecretString::new(read_password().unwrap()); +//! let new_password2 = SecretString::from_str(&read_password().unwrap()).unwrap(); //! if new_password.expose_secret() != new_password2.expose_secret() { //! error!("Passwords do not match"); //! return; @@ -246,7 +245,7 @@ //! use std::path::Path; //! use std::sync::Arc; //! -//! use secrecy::SecretVec; +//! use shush_rs::SecretVec; //! use tracing::info; //! //! use rencfs::crypto; @@ -259,7 +258,7 @@ //! let cipher = Cipher::ChaCha20Poly1305; //! let mut key = vec![0; cipher.key_len()]; //! crypto::create_rng().fill_bytes(key.as_mut_slice()); -//! let key = SecretVec::new(key); +//! let key = SecretVec::from(key); //! //! let mut args = args(); //! // skip the program name diff --git a/src/mount/linux.rs b/src/mount/linux.rs index 7f1d8e1d..81e01ce4 100644 --- a/src/mount/linux.rs +++ b/src/mount/linux.rs @@ -25,7 +25,7 @@ use fuse3::{Errno, Inode, MountOptions, Result, SetAttr, Timestamp}; use futures_util::stream::Iter; use futures_util::{stream, FutureExt}; use libc::{EACCES, EEXIST, EFBIG, EIO, EISDIR, ENAMETOOLONG, ENOENT, ENOTDIR, ENOTEMPTY, EPERM}; -use secrecy::{ExposeSecret, SecretString}; +use shush_rs::{ExposeSecret, SecretString}; use tracing::{debug, error, instrument, trace, warn}; use tracing::{info, Level}; @@ -72,7 +72,7 @@ impl Iterator for DirectoryEntryIterator { Some(Ok(DirectoryEntry { inode: entry.ino, kind, - name: OsString::from(entry.name.expose_secret()), + name: OsString::from(&*entry.name.expose_secret()), #[allow(clippy::cast_possible_wrap)] offset: self.1 as i64, })) @@ -108,7 +108,7 @@ impl Iterator for DirectoryEntryPlusIterator { inode: entry.ino, generation: 0, kind, - name: OsString::from(entry.name.expose_secret()), + name: OsString::from(&*entry.name.expose_secret()), #[allow(clippy::cast_possible_wrap)] offset: self.1 as i64, attr: entry.attr.into(), diff --git a/src/run.rs b/src/run.rs index 7b39b48d..a21c9f6a 100644 --- a/src/run.rs +++ b/src/run.rs @@ -8,7 +8,7 @@ use anyhow::Result; use clap::{crate_authors, crate_name, crate_version, Arg, ArgAction, ArgMatches, Command}; use ctrlc::set_handler; use rpassword::read_password; -use secrecy::{ExposeSecret, SecretString}; +use shush_rs::{ExposeSecret, SecretString}; use strum::IntoEnumIterator; use thiserror::Error; use tokio::sync::Mutex; @@ -228,13 +228,13 @@ async fn run_change_password(cipher: Cipher, matches: &ArgMatches) -> Result<()> // read password from stdin print!("Enter old password: "); io::stdout().flush().unwrap(); - let password = SecretString::new(read_password().unwrap()); + let password = SecretString::from_str(&read_password().unwrap()).unwrap(); print!("Enter new password: "); io::stdout().flush().unwrap(); - let new_password = SecretString::new(read_password().unwrap()); + let new_password = SecretString::from_str(&read_password().unwrap()).unwrap(); print!("Confirm new password: "); io::stdout().flush().unwrap(); - let new_password2 = SecretString::new(read_password().unwrap()); + let new_password2 = SecretString::from_str(&read_password().unwrap()).unwrap(); if new_password.expose_secret() != new_password2.expose_secret() { println!("Passwords do not match"); return Err(ExitStatusError::Failure(1).into()); @@ -270,13 +270,17 @@ async fn run_mount(cipher: Cipher, matches: &ArgMatches) -> Result<()> { let data_dir: String = matches.get_one::("data-dir").unwrap().to_string(); // when running from IDE we can't read from stdin with rpassword, get it from env var - let mut password = - SecretString::new(env::var("RENCFS_PASSWORD").unwrap_or_else(|_| String::new())); + let mut password = SecretString::from_str( + env::var("RENCFS_PASSWORD") + .unwrap_or_else(|_| String::new()) + .as_str(), + ) + .unwrap(); if password.expose_secret().is_empty() { // read password from stdin print!("Enter password: "); io::stdout().flush().unwrap(); - password = SecretString::new(read_password().unwrap()); + password = SecretString::from_str(read_password().unwrap().as_str()).unwrap(); if !PathBuf::new().join(data_dir.clone()).is_dir() || fs::read_dir(&data_dir) @@ -290,7 +294,8 @@ async fn run_mount(cipher: Cipher, matches: &ArgMatches) -> Result<()> { // first run, ask to confirm password print!("Confirm password: "); io::stdout().flush().unwrap(); - let confirm_password = SecretString::new(read_password().unwrap()); + let confirm_password = + SecretString::from_str(read_password().unwrap().as_str()).unwrap(); if password.expose_secret() != confirm_password.expose_secret() { error!("Passwords do not match"); return Err(ExitStatusError::Failure(1).into()); diff --git a/src/test_common.rs b/src/test_common.rs index 52f3f107..7e5a25a5 100644 --- a/src/test_common.rs +++ b/src/test_common.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use std::sync::{Arc, LazyLock}; use std::{env, fs, io}; -use secrecy::SecretString; +use shush_rs::SecretString; use tempfile::NamedTempFile; use thread_local::ThreadLocal; use tokio::sync::Mutex;