Skip to content

chore(rust): upgrade ed25519-dalek 2.x -> 3.x and rand 0.8 -> 0.10 (fixes #3355) - #3420

Open
AlgoVoi (Christopher Hopley) (chopmob-cloud) wants to merge 10 commits into
microsoft:mainfrom
chopmob-cloud:chore/rust-ed25519-dalek-3-rand-0.10
Open

chore(rust): upgrade ed25519-dalek 2.x -> 3.x and rand 0.8 -> 0.10 (fixes #3355)#3420
AlgoVoi (Christopher Hopley) (chopmob-cloud) wants to merge 10 commits into
microsoft:mainfrom
chopmob-cloud:chore/rust-ed25519-dalek-3-rand-0.10

Conversation

@chopmob-cloud

@chopmob-cloud AlgoVoi (Christopher Hopley) (chopmob-cloud) commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrades ed25519-dalek 2.2.0 -> 3.0.0 and rand 0.8.6 -> 0.10.2 across the agent-governance-rust workspace, as requested in #3355.

Dependabot #3269 (dalek 3) and #3271 (rand 0.10) each failed build-rust because they bump one crate at a time. The two must move together: ed25519-dalek 3 rides rand_core 0.9, which rand 0.10 provides, so bumping either alone leaves a rand_core version mismatch. This is a single coordinated PR.

What actually changed

Bumping both together showed that the ed25519-dalek 2 -> 3 signing/verifying surface used in this crate is source-compatible (SigningKey::generate, Signature::from_bytes, VerifyingKey::from_bytes, Signer/Verifier). All the real edits are the rand 0.9/0.10 trait and module reshuffle:

  • rand::distributions -> rand::distr (clock.rs)
  • rand::thread_rng() -> rand::rng() in non-key-material paths (clock.rs, the AES-GCM nonce in credential_vault.rs)
  • the old Rng extension trait (providing sample_iter) is now RngExt (clock.rs)
  • the old RngCore core trait (providing fill_bytes) is now named Rng (credential_vault.rs)
  • rand::rngs::OsRng was removed; key generation now uses UnwrapErr(SysRng) (identity.rs, identity_support.rs, credential_vault.rs), see below

Note on key-generation RNG

SigningKey::generate in ed25519-dalek 3 requires an infallible CryptoRng (pub fn generate<R: CryptoRng + ?Sized>(csprng: &mut R)). The documented pattern in the ed25519-dalek 3.0.0 SigningKey::generate docs is OS entropy through the UnwrapErr adapter: let mut csprng = UnwrapErr(SysRng); SigningKey::generate(&mut csprng). SysRng (the getrandom 0.4 system source re-exported by rand 0.10 as rand::rngs::SysRng) implements the fallible TryCryptoRng, and rand_core's UnwrapErr wrapper turns it into an infallible CryptoRng via the blanket impl, satisfying the bound directly from OS entropy with no new dependency and no lockfile change.

Every key-material path draws from UnwrapErr(SysRng): AgentIdentity::generate/delegate, Credential::issue, KeyRotationManager::rotate, and the vault's AES-256-GCM CredentialVault::generate_key. Thread RNG (rand::rng()) remains only where key material is not involved (the AES-GCM nonce, generated identifiers, the attestation challenge nonce, and the MCP clock nonce). This draws long-lived key material straight from the OS CSPRNG and removes the thread-local reseed and fork-safety caveats from the keygen path. The dependency-audit doc records the split.

Validation

agent-governance-rust, from a green baseline:

baseline (2.2.0 / 0.8.6) this PR (3.0.0 / 0.10.2)
cargo build --workspace clean clean, no new warnings
cargo test --workspace --locked 514 pass, 0 fail 518 pass, 0 fail (Linux)
cargo clippy --workspace --all-targets 9 warnings 9 warnings (0 new)

The PR adds two keygen tests (distinct usable keys with cross-verification rejection; distinct non-zero vault keys), which is the +4 delta over the 514 baseline together with the branch's earlier additions. The suite still includes the signature-rejection tests (trust::test_verify_peer_rejects_mismatched_claimed_peer, trust::test_verify_peer_rejects_signature_not_created_by_peer, mcp::signing::tests::rejects_replayed_messages), so verification still refuses forged and replayed signatures, not merely accepts valid ones.

Fixes #3355.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 AI Agent: code-reviewer — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

TL;DR: 0 blockers, 0 warnings. Safe and clean upgrade.

# Sev Issue Where

No issues found. Clean change.

@github-actions github-actions Bot added the size/L Large PR (< 500 lines) label Jul 22, 2026
@github-actions

Copy link
Copy Markdown
🤖 AI Agent: contributor-guide — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

Welcome, and thank you for your contribution! Great job coordinating the ed25519-dalek and rand upgrades to resolve dependency conflicts effectively.

Before we can merge, please address the following:

  1. Ensure that all removed dependencies in Cargo.lock are no longer required by any part of the project.
  2. Verify that the changes to rand usage (e.g., rand::rng() and RngExt) are consistent across all affected files.

For more details, refer to our CONTRIBUTING.md. Let us know if you need any help!

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 AI Agent: docs-sync-checker — Docs Sync

AI-generated review output. Treat it as untrusted analysis and verify before acting.

Docs Sync

  • README.md -- no updates found for the changes in the pull request.
  • CHANGELOG.md -- missing entry for the upgrade of ed25519-dalek and rand versions, as well as the associated behavioral changes (e.g., OsRng to rand::rng() for key generation).

Please ensure the CHANGELOG.md reflects these updates.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 AI Agent: security-scanner — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

No security issues found.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 AI Agent: test-generator — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

Test coverage looks good. No gaps identified.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 AI Agent: breaking-change-detector — API Compatibility

AI-generated review output. Treat it as untrusted analysis and verify before acting.

API Compatibility

Severity Change Impact
High Upgrade ed25519-dalek from 2.x to 3.x Potential breaking change due to major version bump. While the PR notes that the signing/verifying surface is source-compatible, downstream consumers relying on internal or undocumented behavior may face issues.
High Upgrade rand from 0.8 to 0.10 Potential breaking change due to major version bump. Changes in trait and module structure (e.g., rand::distributionsrand::distr, OsRng replaced with ThreadRng) may impact consumers relying on the previous API.
Medium Replacement of rand::rngs::OsRng with rand::rng() May affect users who explicitly depend on OsRng for cryptographic random number generation.

@github-actions

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ⚠️ Missing No current-run comment
🛡️ Security Scan ⚠️ Missing No current-run comment
🔄 Breaking Changes ⚠️ Missing No current-run comment
📝 Docs Sync ⚠️ Missing No current-run comment
🧪 Test Coverage ⚠️ Missing No current-run comment

Verdict: ⚠️ AI review incomplete; ready for human review

AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims.

@github-actions

Copy link
Copy Markdown

🔴 Contributor Check: HIGH

Check Result
Profile HIGH
Credential LOW
Overall HIGH

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:HIGH Contributor reputation check flagged HIGH risk label Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

TL;DR: 0 blockers, 0 warnings. No issues found. Clean change.

Changes:

  • Upgrade ed25519-dalek from 2.2.0 to 3.0.0 and rand from 0.8.6 to 0.10.2 across the agent-governance-rust workspace.
  • Update call sites for rand 0.10 API moves/renames (e.g., distributionsdistr, thread_rng()rng(), RngRngExt, RngCoreRng).

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
agent-governance-rust/Cargo.toml Pins ed25519-dalek to =3.0.0 and rand to =0.10.2 at the workspace level.
agent-governance-rust/Cargo.lock Updates the resolved dependency graph for the coordinated ed25519-dalek/rand upgrade.
agent-governance-rust/agentmesh/src/identity.rs Switches key generation RNG call from OsRng to rand::rng() for SigningKey::generate.
agent-governance-rust/agentmesh/src/identity_support.rs Updates SigningKey::generate RNG call sites to rand::rng() for credential/key rotation paths.
agent-governance-rust/agentmesh/src/credential_vault.rs Adapts RNG trait usage (RngCoreRng) and updates thread_rng()rng() for byte filling.
agent-governance-rust/agentmesh-mcp/src/mcp/clock.rs Updates rand imports (distr, RngExt) and RNG creation (rng()) for nonce generation.

@imran-siddique

Copy link
Copy Markdown
Collaborator

MohammadHaroonAbuomar this is the closest Rust PR to merge: mergeable, CI clean, resolves #3355, and the duplicate #3418 is now closed. Could you give it a code-owner review when you have a moment? Thanks.

Copilot AI review requested due to automatic review settings July 27, 2026 22:21
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

@MohammadHaroonAbuomar MohammadHaroonAbuomar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  • Process: real CI has never run on this head (all green checks are pull_request_target bot jobs; build-rust/CodeQL/SBOM stuck action_required) and the PR is CONFLICTING on the exact Cargo.toml/lock block being upgraded. Rebase onto main, get workflow runs approved, require genuinely green CI. (Local compensating run at head: cargo test 514/514 pass; code content verified sound incl. dalek3 signing determinism and no seeded-RNG leaks.)

Minor:

  • audit doc omission: OsRng->ThreadRng is not strictly equivalent (thread-local ChaCha12, reseeds per 64KiB, not fork-safe; no fork usage in workspace today). Add a line.

@MohammadHaroonAbuomar MohammadHaroonAbuomar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  • Process: real CI has never run on this head (all green checks are pull_request_target bot jobs; build-rust/CodeQL/SBOM stuck action_required) and the PR is CONFLICTING on the exact Cargo.toml/lock block being upgraded. Rebase onto main, get workflow runs approved, require genuinely green CI. (Local compensating run at head: cargo test 514/514 pass; code content verified sound incl. dalek3 signing determinism and no seeded-RNG leaks.)

Minor:

  • audit doc omission: OsRng->ThreadRng is not strictly equivalent (thread-local ChaCha12, reseeds per 64KiB, not fork-safe; no fork usage in workspace today). Add a line.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Rebased onto the current upstream/main (8f7a4c9, 15 commits ahead of the previous base). The rebase applied cleanly with zero conflicts: none of the new main commits touch agent-governance-rust, and GitHub now reports the PR mergeable, so the earlier Cargo.toml/Cargo.lock conflict is resolved.

Local validation on the rebased head: cargo test --workspace --locked passes with 0 failures on both a Linux gnu toolchain (516 passed) and a Windows gnu toolchain (515 passed; the one-test delta is a target-gated case, not a failure). This includes the forgery and replay rejection tests (trust::test_verify_peer_rejects_mismatched_claimed_peer, trust::test_verify_peer_rejects_signature_not_created_by_peer, mcp::signing::tests::rejects_replayed_messages), which I re-ran by name to confirm they execute rather than filter out. The --locked flag confirms the lockfile is fully consistent (ed25519-dalek 3.0.0, rand 0.10.2, single rand_core 0.10.1, no git dependencies).

Both minor items from your review are in the audit doc: the OsRng to ThreadRng non-equivalence note (thread-local ChaCha12, per-64KiB reseed, not fork-safe, with the caveat that nothing in the workspace forks today) and the corrected getrandom table (0.2.17 + 0.3.4 + 0.4.3 after, matching the lockfile).

The remaining gate is on the maintainer side: build-rust, CodeQL, and SBOM sit at action_required until a maintainer approves workflow runs for this fork head. Once approved, real CI will run against the rebased head.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

One further hardening since the last update: key generation no longer uses rand's thread RNG. All five key-material call sites (the four Ed25519 SigningKey::generate sites and the vault's AES-256-GCM generate_key) now draw OS entropy via UnwrapErr(SysRng), which is the pattern the ed25519-dalek 3.0.0 SigningKey::generate documentation shows. This removes the thread-local ChaCha12 state, the per-64 KiB reseed window, and the fork-safety caveat from the keygen path, with no new dependency and no lockfile change. Thread rng survives only in non-key-material spots (nonces and generated ids), and the audit doc now lists them explicitly. Two tests were added: distinct usable keys with cross-verification rejection, and distinct non-zero vault keys. Full workspace suite is 518 pass, 0 fail on Linux, including the forgery and replay rejection tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (1)

docs/dependency-audits/2026-07-27-ed25519-dalek-3-rand-0.10.md:110

  • The verification paragraph claims "514 tests passing" and "identical to the pre-upgrade baseline", but this PR adds new keygen tests (and the PR description reports a higher test count). To avoid leaving an incorrect audit record, update this section to avoid hard-coded counts (or update them to the actual current totals).
Verification: `cargo build`, `cargo test` and `cargo clippy` are green, with
514 tests passing, identical to the pre-upgrade baseline, with no tests
skipped or removed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Coordinated bump (fixes microsoft#3355). ed25519-dalek 3 rides rand_core 0.9 which
rand 0.10 provides, so the two must move together; dependabot's one-at-a-time
bumps (microsoft#3269, microsoft#3271) cannot align them. The dalek 2->3 signing/verifying
surface used here is source-compatible; the edits are the rand 0.9/0.10
reshuffle: distributions->distr, thread_rng->rng, the Rng extension trait
->RngExt, the RngCore core trait ->Rng, and OsRng (removed) -> rand::rng()
(ThreadRng, an infallible CryptoRng, which SigningKey::generate requires and
rand 0.10's SysRng -- only TryCryptoRng -- is not).

cargo build/test/clippy green: 514 tests pass, unchanged from baseline,
including the signature-reject tests (verification still refuses forged and
replayed signatures).

Signed-off-by: chopmob-cloud <250041792+chopmob-cloud@users.noreply.github.com>
Signed-off-by: AlgoVoi <chopmob@gmail.com>
The vendored-patch-audit gate requires a dated audit doc whenever a
lockfile changes, and this PR changes agent-governance-rust/Cargo.lock.

Records why ed25519-dalek and rand must move together, the full
transitive delta, the rand_core/getrandom duplicate collapse, the new
digest/sha2 major duplication, and the OsRng -> rand::rng() migration
that keeps an infallible CryptoRng for key generation. No CVE is being
remediated; this is a compatibility-driven upgrade.

Signed-off-by: chopmob-cloud <250041792+chopmob-cloud@users.noreply.github.com>
Signed-off-by: AlgoVoi <chopmob@gmail.com>
Signed-off-by: AlgoVoi <chopmob@gmail.com>
Signed-off-by: AlgoVoi <chopmob@gmail.com>
…ence

ThreadRng is a thread-local ChaCha12 CSPRNG that reseeds from the OS per
64 KiB of output. Unlike OsRng it is not fork-safe: a child that forks
without exec inherits the parent's RNG state. No code in this workspace
calls fork directly and neither Tokio nor the test harness uses a forking
model, so this is not a current risk. Documenting it so the constraint is
visible if a forking process model is introduced later.

Signed-off-by: AlgoVoi <chopmob@gmail.com>
Copilot reviewer noted the audit table listed getrandom After as 0.4.2 but
the actual lockfile has 0.4.3. On inspection the Before column also omitted
the 0.3.4 version that was already present on main before this PR.

Corrected changes:
- Before: 0.2.17 + 0.3.4 + 0.4.2 (0.3.4 was already present on main)
- After:  0.2.17 + 0.3.4 + 0.4.3 (minor patch bump driven by the rand 0.10 upgrade)

Prose corrections:
- Only rand_core collapses (2->1 version); getrandom stays at 3 versions.
- Security bullet updated to match.

Signed-off-by: AlgoVoi <chopmob@gmail.com>
…ed pattern

Key generation previously used rand's thread RNG (ThreadRng: thread-local
ChaCha12, reseeded from the OS per 64 KiB, not fork-safe). ed25519-dalek
3.0.0's SigningKey::generate documentation uses OS entropy directly via
the UnwrapErr adapter: UnwrapErr(SysRng). This change adopts that pattern
for every key-material path:

- AgentIdentity::generate and AgentIdentity::delegate (identity.rs)
- Credential::issue and KeyRotationManager::rotate (identity_support.rs)
- CredentialVault::generate_key, the AES-256-GCM key (credential_vault.rs)

rand::rngs::SysRng (re-export of getrandom 0.4 SysRng, TryCryptoRng with
Error = Infallible under UnwrapErr) satisfies the infallible CryptoRng
bound of SigningKey::generate via the rand_core blanket impl, so no new
dependency is needed and Cargo.lock is unchanged.

Thread rng remains only in non-key-material paths: the AES-GCM nonce,
generated identifiers (credential, link, chain, incident, violation,
report, grant, challenge, sandbox execution ids), the attestation
challenge nonce, and the MCP clock nonce.

The dependency-audit doc drops the ThreadRng-vs-OsRng caveat and now
records the OS-entropy keygen pattern and the surviving thread-rng uses.
Adds two tests: distinct usable Ed25519 keys with cross-verification
rejection, and distinct non-zero vault keys.

Validation: cargo test --workspace --locked green with the GNU host
toolchain (378 lib + 101 integration + 36 mcp + 2 doc tests), clippy
clean of new warnings.

Signed-off-by: AlgoVoi <chopmob@gmail.com>
…cation note

Signed-off-by: AlgoVoi <chopmob@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (4)

agent-governance-rust/agentmesh/src/identity.rs:83

  • Same issue as above: SigningKey::generate(&mut UnwrapErr(SysRng)) borrows a temporary UnwrapErr(SysRng) as &mut, which is not allowed in this call form. Use a local mut binding for the RNG adapter.
        let signing_key = SigningKey::generate(&mut UnwrapErr(SysRng));
        let public_key = signing_key.verifying_key();

agent-governance-rust/agentmesh/src/identity_support.rs:1058

  • SigningKey::generate(&mut UnwrapErr(SysRng)) borrows a temporary RNG adapter as &mut and is likely to fail to compile. Introduce a local mut csprng binding and pass &mut csprng.
            });
        let signing_key = SigningKey::generate(&mut UnwrapErr(SysRng));
        let public_key = signing_key.verifying_key();

agent-governance-rust/agentmesh/src/identity.rs:34

  • SigningKey::generate(&mut UnwrapErr(SysRng)) takes a mutable reference to a temporary UnwrapErr(SysRng) value; Rust does not allow borrowing a temporary as &mut in a function call, so this is likely to fail to compile. Bind the RNG adapter to a local mut variable first, then pass &mut to that.

This issue also appears on line 82 of the same file.

        // OS entropy per the ed25519-dalek 3 documented pattern for key generation.
        let signing_key = SigningKey::generate(&mut UnwrapErr(SysRng));
        let public_key = signing_key.verifying_key();

agent-governance-rust/agentmesh/src/identity_support.rs:175

  • SigningKey::generate(&mut UnwrapErr(SysRng)) attempts to take &mut to a temporary UnwrapErr(SysRng) value; this pattern is likely to fail to compile. Bind UnwrapErr(SysRng) to a local mut variable first.

This issue also appears on line 1056 of the same file.

        let expires_at_secs = issued_at_secs.saturating_add(ttl_seconds.max(1));
        // OS entropy per the ed25519-dalek 3 documented pattern for key generation.
        let signing_key = SigningKey::generate(&mut UnwrapErr(SysRng));
        let token = URL_SAFE_NO_PAD.encode(signing_key.to_bytes());

These rand-crate identifiers appear in the dalek-3/rand-0.10 dependency
audit docs and were missed in the initial spell commit (017d3c2).

Signed-off-by: AlgoVoi <chopmob@gmail.com>

@prayagupa Prayag (prayagupa) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correct ed25519-dalek 2→3 / rand 0.8→0.10 migration — OsRngUnwrapErr(SysRng), thread_rng()rng(), distributionsdistr/RngExt — with added tests asserting distinct, verifiable OS-entropy keys. Test Coverage, Security Scan, and Breaking Changes are all green. LGTM.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@MohammadHaroonAbuomar following up on imran-siddique's ping from a couple of weeks ago. The PR is rebased onto current main (as of 2026-08-04), all CI checks are green, and GitHub reports it mergeable. Happy to address any questions if something is holding up the review.

Copilot AI review requested due to automatic review settings August 6, 2026 18:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

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

Labels

documentation Improvements or additions to documentation needs-review:HIGH Contributor reputation check flagged HIGH risk size/XL Extra large PR (500+ lines) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(rust): upgrade ed25519-dalek 2.x -> 3.x and rand 0.8 -> 0.10

5 participants