fix(primitives): gate PrivateKey raw access and zeroize via derive#2994
Open
chefsale wants to merge 2 commits into
Open
fix(primitives): gate PrivateKey raw access and zeroize via derive#2994chefsale wants to merge 2 commits into
chefsale wants to merge 2 commits into
Conversation
Two security issues in `PrivateKey` (crates/primitives/src/identity.rs):
1. Raw bytes were exposed via `Deref<Target=[u8;32]>`, `AsRef<[u8;32]>`
and a derived `BorshSerialize`/`BorshDeserialize`. Any of these made it
trivial to copy or serialize the secret into a buffer that is never
zeroized, silently defeating the zeroize-on-drop guarantee.
- Drop the blanket `Deref` and `AsRef` impls and the Borsh derives.
- Gate raw access behind a single audited `as_bytes(&self) -> &[u8; 32]`
accessor, documented as the one reviewed entry point to the secret.
- Update all call sites: in-place crypto uses (`SigningKey::from_bytes`,
`SharedKey`) and the storage layers that persist an explicit `[u8; 32]`
copy now go through `as_bytes()`.
2. The `Drop` impl zeroized via an `unsafe` cast of `*mut Hash` to `*mut u8`
over `size_of::<Hash>()`, which would silently miss key material if `Hash`
ever gained padding or fields.
- Change the inner type to a plain `[u8; 32]` and `#[derive(ZeroizeOnDrop)]`,
removing the hand-rolled `unsafe` Drop and tracking field layout
automatically. Enables zeroize's `derive` feature on calimero-primitives.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gfW6RgRfT6z5VDPg4dXQW
Contributor
There was a problem hiding this comment.
🤖 MeroReviewer
Reviewed by 1 agents | Quality score: 28% | Review time: 65.5s
💡 1 suggestions. See inline comments.
🤖 Generated by MeroReviewer | Review ID: review-2dd88236
Contributor
Documentation ReviewThe following documentation may need updates based on the changes in this PR:
|
Contributor
There was a problem hiding this comment.
🤖 AI Code Reviewer
Reviewed by 2 agents | Quality score: 54% | Review time: 1244.3s
🟡 1 warnings. See inline comments.
🤖 Generated by AI Code Reviewer | Review ID: review-dea067e6
- create_context: pass `&identity_secret` directly to `sign_apply_and_publish` instead of `PrivateKey::from(*..as_bytes())`, which created an extra live, separately-dropped copy of the secret. - identity: document that `Clone`/`Copy` are deliberately not derived on `PrivateKey`, since either would hand out an untracked copy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014gfW6RgRfT6z5VDPg4dXQW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two security issues in
PrivateKey(crates/primitives/src/identity.rs):Raw bytes were exposed via
Deref<Target=[u8;32]>,AsRef<[u8;32]>and a derived
BorshSerialize/BorshDeserialize. Any of these made ittrivial to copy or serialize the secret into a buffer that is never
zeroized, silently defeating the zeroize-on-drop guarantee.
DerefandAsRefimpls and the Borsh derives.as_bytes(&self) -> &[u8; 32]accessor, documented as the one reviewed entry point to the secret.
SigningKey::from_bytes,SharedKey) and the storage layers that persist an explicit[u8; 32]copy now go through
as_bytes().The
Dropimpl zeroized via anunsafecast of*mut Hashto*mut u8over
size_of::<Hash>(), which would silently miss key material ifHashever gained padding or fields.
[u8; 32]and#[derive(ZeroizeOnDrop)],removing the hand-rolled
unsafeDrop and tracking field layoutautomatically. Enables zeroize's
derivefeature on calimero-primitives.Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_014gfW6RgRfT6z5VDPg4dXQW