-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zeroize: potetial redesign ideas #1046
Comments
The point of As long as |
No, it's not. |
I was talking about the proc-macro, not the trait itself. I guess your original point then was about the trait not the proc-macro? Unfortunately I don't remember the motivation behind the |
Yes. As I wrote in the OP, in RustCrypto we usually do not rely on proc macro and instead manually implement |
I would probably suggest against any breaking changes to Due to the trait-based nature of its API, which is used across crates, it makes breaking changes extremely difficult due to the requirement for coordinated upgrades. I find names like
I think #1045 is fine, but should be done in an additive manner. |
I also think it would be good to be able to silently and transparently promote secret storage for other types to be heap-backed as well when available when the |
For most of the RustCrypto crates upgrade should be quite painless since they do not provide
I do not insist on this exact names, think of them as of placehoders.
But it should not be implemented for types like
Such types can have |
You're completely redesigning the API, so this will be a massive breaking change (and I'm not sure I'm particularly pleased with the new design). Unlike our other trait crates where we generally control all the downstream trait impls, Also if we're thinking about a |
I have updated draft in the OP.
I think you overestimate potential consequences. Downstream crates which derive Users may have issues if they include our type which implement Another potential issue is that users may rely on
I've skimmed the paper and I am not sure it's relevant for deciding how public API of |
There are a lot of uses which aren't custom derive. I suggest looking through this: |
It does not matter whether it's derive or manual implementations. The uses will continue to work until maintainers will decide to migrate to zeroize v2.0. Even if an upstream crate has migrated to v2.0, downstream may delay full migration to v2.0 by simply wrapping upstream types by |
The problem is when you have cross-crate interdependencies, especially when there are multiple different vendors of crates at various levels, e.g.: protocol implementation -> elliptic curve library -> numerical library Breaking changes on trait-based APIs are incredibly intrusive in these sorts of environments. It's why I guess there's the semver trick to work around this, but with this sort of API, I think the amount of downstream churn and toil needs to be carefully weighed against the benefits that breaking changes might bring. |
Yet another approach is to simply make a new library with a different name which provides the same functionality / end goals, which can be vetted independently, and if it seems like a better approach, you can deprecate the old one. This is what I've explored with e.g. |
Note that the proposed re-design does not have
Yes, it's a viable option. The only question is whether the RustCrypto crates should keep |
I think we can make progress there without breaking changes. #1045 is a good start. |
This isn't quite true. Really it comes down to whether a type optionally contains secrets, or always contains secrets. You are adding a boolean flag to your
But what is the utility of Generally how code is structured with |
Yes. I do not plan to implement the redesign in the near future, so the linked PR should be merged regardless of this discussion.
Not quite. The difference is that The biggest concern with
Because code like this will be much more annoying to write and work with: struct AeCipher {
#[cfg(not(feature = "zeroize"))]
cipher: Ctr<Aes128>,
#[cfg(not(feature = "zeroize"))]
hasher: Hmac<Sha256>,
#[cfg(feature = "zeroize")]
cipher: Zod<Ctr<Aes128>>,
#[cfg(feature = "zeroize")]
hasher: Zod<Hmac<Sha256>>,
} But I think in most cases users will not use the optionality. |
No code is written like that today. Those types all take care of zeroizing themselves, and the drop impls are gated on the
|
I thought you asked about the proposed API.
The main point of the proposal is to move from this model and instead make users to explicitly mark zeroized data in their code using |
To do that, add a
And if |
No, in my opinion, you can not. I think it's incorrect to implement
Secrecy is often dependent on how this type is used and this information is available only to downstream users. You can not know it just by type beforehand. For example, the same |
For |
For example, non secret mode can be useful for ephemeral cipher instances stored on stack which get erased by stack bleaching after necessary computations with the cipher are completed. The PRNG example is also applicable (after all, with AES-NI
How? Such impl directly contradicts the trait docs:
|
You explicitly mentioned not wanting to leave |
If you're using stack bleaching, you can just leave the |
Ah, I was confused by the name. I thought the marker trait indicates that
Using stack bleaching in one part of application does not mean I don't have long-lived ciphers which should be zeroized on drop in other part. As I wrote earlier, necessity of zeroization on drop is often dependent on how we use a type. |
Okay fine, it could be written using your
Trying to micro-optimize the cases where sometimes you want to use zeroize using the Perhaps before we go down that road we can explore using |
It could be a little detrimental to make A note about that in the documentation would help, but I think it might be beneficial to gate it behind a feature to prevent downstream users from misusing it on something that already implements But it would be a little more ideal if it were possible to make an |
@nstilt1 it's |
Regarding the usage of zeroize, it may be valuable to borrow theory from the fast key erasure of the CSPRNG in the linux kernel. |
Right now I see the following issues with public API of
zeroize
:Zeroize
can be inefficient since they rely on zeroization of fields one by one or on zeroizingDrop
impls.Zeroize
ad rely on manual implementations.ZeroizeOnDrop
is a somewhat useless trait, I haven't seen it used in practice.Zeroizing
usefulness is limited. It can be used only for "primitive" types (e.g. raw keys), complex types do not implementZeroize
and instead implement zeroizingDrop
.I think most structures should be zeroized using the "flat" zeroization (see #1045) and that it can be useful to have explicit indication in user code of structs being zeroized on drop.
So I would like to suggest roughly this API:
UPD:
FlatPod
andFlatZod
are removed.It can be introduced in a backward-compatible way, but for clarity it's probably worth to release it as v2.0.
Users would write code like this:
While it will be a bit less convinient, I think it's useful to have explicit indication in source code that secret types will be zeroized on drop. We may provide aliases like
type ZodAes128 = Zod<Aes128>
to improve visibility, but I don't think they are worth the trouble and it should be sufficient to simply referenceszeroize
in docs.The text was updated successfully, but these errors were encountered: