-
Notifications
You must be signed in to change notification settings - Fork 211
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
aead: add AeadCore::TAG_POSITION
and move AeadInPlace
methods to AeadInOut
#1798
base: master
Are you sure you want to change the base?
Conversation
Aead
traitAead
trait
This PR would be easier to review if it did only what the title suggests, combining all of the traits into a single trait. However it also adds a bunch of additional methods, which can be done separately, potentially to the I don't like this approach because it limits the flexibility of the While there's something to be said for "one trait to worry about", this PR replaces the "which trait do I use?" problem with "which method do I use?". And I don't think you'll achieve any greater flexibility without multiple traits anyway. If you do try to add other traits (to support heap-allocated use, and/or async use), they can't build off I think you could probably get most of the same benefits by combining just the |
Made an attempt at porting the consumers over in RustCrypto/AEADs#674. I'm not sure how to deal with the SIVs crates as they do not really have a tag serialization? |
@baloo |
Ok, I removed the helper methods for now.
Could you provide concrete examples of such wrapping? I think we should prioritize pure Rust software implementations foremost. Compatibility with other use cases such as hardware-based accelerators on embedded devices or external IO-based tokens could be a nice bonus, but we should carefully consider concrete examples without hypotheticals. As I mentioned in the OP, such use cases may be better covered by a separate higher-level I also think that it should be possible to emulate (albeit somewhat inefficiently) the detached
I disagree. I think the suggested approach clearly follows the idiomatic handling of "extension" methods commonly used in Rust. We have "fundamental" low-level detached methods and associated constants which represent "simple and straightforward mappings of the underlying cryptographic functions". On top of them we build convenient extension methods with an ability to overwrite blanket implementations if it's necessary for some reason. For example, compare it against the Now, there is an alternative approach of "extension traits" (e.g.
It's very close to what I propose. The main difference is that I think that instead of the current If you really don't like the suggested names, instead of I did not include this new trait as part of this PR because I assume you would like to see it added in a separate PR.
From my teaching experience, one of the common stumbling blocks for students is understanding hierarchy of blanket trait impls (and it sometimes applies even to mildly experienced Rust programmers). It's very easy to look at crate docs, see that a type implements trait I understand that I may not be the best person to argue this point considering the APIs in our other crates, but I try to be conscious about it. |
That means if you want to wrap anything which implements an AEAD with heap allocations, you lose type safety around the nonce size. Forcing the It's also a departure from the design of crates like
I think there's been a lot of headway on that, some of which we aren't leveraging but probably should, namely rustdoc also enumerates the blanket impls for a given type which makes them much more discoverable. |
And I don't think that we should have it in a
How it's different from the
I had in mind potential migration to the As for
I don't think it helps that much. The merged trait would also work much better with hypothetical inherent trait implementations (which I really hope we will get one day). |
They could still do that if you impl'd those same methods on
Which is a lot less suboptimal than simply being able to return the
No, that's not what I was talking about. I was talking about how https://docs.rs/digest/latest/digest/trait.Digest.html#impl-Digest-for-D Are you going to similarly get rid of the I think before we try refactoring I can take a look at that soon. |
I would love to do that and long time ago I used roughly this approach. But we have 3 different algorithm classes: fixed output, extendable output, and variable output. And we also have Hash/MAC, customizable/non-customizable, and resetable/non-resetable distinctions on top of that. We could introduce several different traits ( In the If you have a concrete proposal for
If user already has
This looks orthogonal to me. I have some ideas which I plan to prototype on top of this refactor, which would look like additional provided methods on the merged
You haven't addressed my point about |
No, I gave the example of anything which implements an AEAD with heap allocations, i.e. anything where the AEAD implementation owns the return buffer and not the user. For example, that's what the Your solution for these is to introduce a
That's nice if a This PR is a one-sized-fits-some solution, which IMO is a regression from the current state of the crate with dubious benefits. The existing implementation is more flexible, you can still add a
Those methods are going to work on differently structured messages, and you're going to mix them in with the rest of the Perhaps this is the main place we disagree: I want methods organized and grouped by related functionality, and you seem to think it is easier and less confusing for users for them to all be placed into a single trait. IMO having lots of methods on a single trait makes it much harder for users to answer the "what method do I use?" question. |
Heh, this is an amusingly bad example. After digging a bit deeper, you can see that the underlying library uses... buffer-to-buffer APIs! (I am not sure whether the library allows for
Show me a concrete example of an implementation which implements the current
Do you think the same about the Putting the methods into different traits tied with blanket impls not only makes discovery a bit harder (it's objectively easier to read and search docs for one trait, than for several), but also would prevent us from overwriting default impls (assuming we do not have specialization), which may be useful for optimization purposes. |
It didn't used to. This used to be all there was: Yes newer versions added the buffer-to-buffer APIs.
|
Please, look under the hood... By clicking "source" in the linked page you can see this: ffi::crypto_secretbox_xsalsa20poly1305(dst, src, len, n, k) Which is again a buffer-to-buffer API. I understand why the wrapper authors rely on allocations here, but it's simply not relevant for us.
These traits are either about conversions ( What you argue is for 70+ methods from the
|
I'm talking about the public API. That's how it was implemented even if there were buffer-to-buffer ops available internally which were eventually exposed. Anyway, that was just an example from the Rust ecosystem I could think of offhand.
Or how about methods for operating on nonce-prefixed AEAD messages, which you just want to lump into the
No, that's not what I'm arguing, I was pointing out how |
Those public APIs were developed without relying on
All AEADs can implement nonce-prefixed serialization of ciphertexts based on the detached methods, similarly to how all
You wrote:
By this logic My point is that there should be a tangible reason for a trait split. It can be either that we define an extension trait in a separate crate ( |
I'm talking about an extension trait that works for all AEADs. Using an extension trait makes it clear which methods operate on nonce-prefixed AEAD messages as opposed to unprefixed messages. I think solving that is a higher priority over what is effectively a bikeshedding debate about the API where either option has tradeoffs, and those requirements should also inform the design. Also, personally I don't think these "analogies" with |
No, you absolutely did not do that. The linked The same principle more or less applies to the wider ecosystem as well, the mentioned above
So let's move forward with this PR and start working on those higher priority tasks. If in future you will show me a compelling reason why the split matters (e.g. during development of the nonce including methods), I will revert it myself in no time. |
I'd rather move forward with the higher priority work first, then see what it looks like when you try to shoehorn everything into the |
Sigh..... Ok, I will return the |
Aead
traitAeadCore::TAG_POSITION
and move AeadInPlace
methods to Aead
AeadCore::TAG_POSITION
and move AeadInPlace
methods to Aead
AeadCore::TAG_POSITION
and move AeadInPlace
methods to AeadInOut
@@ -155,6 +160,94 @@ pub trait AeadCore { | |||
} | |||
} | |||
|
|||
/// In-place AEAD trait which handles the authentication tag as a return value/separate parameter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inout
operations aren't necessarily in place. This probably needs an all-new description.
Closes #1776