Skip to content

Conversation

dani-garcia
Copy link
Member

@dani-garcia dani-garcia commented Mar 11, 2025

🎟️ Tracking

📔 Objective

Created bindings in C# for the OPAQUE-KE rust crate.

This PR is entirely new additions, so it might be easier to review from a local clone. The added things are:

  • .github/workflows:
    • Added a new workflow to cross compile the rust module for all supported platforms
    • Updated pack-and-release.yml to obtain the cross compiled libraries
    • Updated prerelease.yml to use the pack-and-release.yml from the branch instead of main, can be reverted before merging
    • Updated start-release.yml to add another option to the selection in workflow_dispatch
  • .vscode/settings.json: Added reference to the rust project so rust analyzer works
  • bitwarden-dotnet.sln: Added reference to the new C# project
  • extensions/Bitwarden.Opaque/
    • rust: The rust project, which compiles to a library with a C API
      • src/opaque: Contains safe wrapper code around the opaque-ke crate. This crate uses a lot of type generics in it's API, which makes it fairly hard to wrap efficiently in FFI. In this case we're using a custom OpaqueImpl trait to implement a sort of dynamic dispatch system on top of the opaque-ke crate, and using a macro to implement it. I the future this might be moved to the bitwarden_crypto crate, and removed from here instead.
      • src/ffi: Contains unsafe C FFI code, using the previous mentioned wrapper. Most of the unsafety is hidden behind custom Buffer and Response types, which are C-like structs passed through FFI.
    • src: The C# project, which links against the Rust C API and offers a safe more idiomatic C# API
      • BitwardenLibrary.cs: This is an internal module with the interface for the C API. It also contains the FFIHandler class, which contains utilities for safely converting the requests and responses back and forth, and freeing the memory as needed.
      • Bitwarden[Client/Server].cs: This is the actual public API of the OPAQUE API, mostly just wrapping the C API in ExecuteFFIFunction, and storing the results in aptly named structs. Note that we also provide a Client implementation even though we don't make use of it, because it simplifies the testing considerably.
    • tests: A small test project to ensure the bindings work correctly
    • perf: A small benchmark to measure the performance of the implementation, run it with dotnet run --project extensions/Bitwarden.Opaque/perf/Bitwarden.Opaque.Benchmarks.csproj -c Release -p:BuildOpaqueLib=true

How to make a new release

  • Bump the VersionPrefix and the PreReleaseVersionIteration in Bitwarden.Opaque.csproj as needed.
  • Run the Start release workflow from your branch, select Bitwarden.Opaque
  • This will create a branch with the name release/Bitwaden.Opaque/x.y, it may open a version bump PR, you can merge it or ignore it
  • If we want a prerelease:

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@dani-garcia dani-garcia changed the title Create initial Rust<->OPAQUE bindings Create initial Rust<->C# OPAQUE bindings Mar 11, 2025

This comment was marked as resolved.

This comment was marked as resolved.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some future plans to move this module to the bitwarden-crypto crate, which would considerably simplify the rust code for this crate. For now it lives here, though

Copy link

@dani-garcia dani-garcia marked this pull request as ready for review March 24, 2025 17:20
@dani-garcia dani-garcia requested review from a team as code owners March 24, 2025 17:20
@dani-garcia dani-garcia requested a review from justindbaur March 24, 2025 17:20
@dani-garcia dani-garcia changed the title [PM-18991] Create initial Rust<->C# OPAQUE bindings [PM-18991] Create Rust<->C# OPAQUE bindings Mar 24, 2025
@trmartin4 trmartin4 removed the request for review from justindbaur September 5, 2025 23:18
@trmartin4 trmartin4 marked this pull request as draft September 5, 2025 23:18
@trmartin4
Copy link
Member

@dani-garcia I converted this to Draft since we will likely need to revisit this when we introduce OPAQUE. I'm cleaning up old PRs that have Justin assigned. Let me know if you disagree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants