-
Notifications
You must be signed in to change notification settings - Fork 193
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: rework traits #1713
base: master
Are you sure you want to change the base?
aead: rework traits #1713
Conversation
90dfc76
to
6b74373
Compare
FWIW I have an incomplete local branch trying to do similar things (mostly implementing the ideas I talked about in #1672) |
@tarcieri |
@newpavlov as I said in #1672, I am a user of those APIs and know of other embedded users of those APIs. The "small amount of glue code" involves length calculations on slices which those APIs abstract away for users of e.g. I also don't think we should capriciously remove features and break downstream users' code. Features should only be removed if they're a misfeature or they don't have any users, neither of which is the case here. And I especially don't think we should be comingling the removal of major user-facing features in large PRs which are making a large number of unrelated changes such as this one. |
I pushed this up here: #1714 |
/// `Aead*` traits. | ||
pub trait AeadCore { | ||
/// Authenticated Encryption with Associated Data (AEAD) algorithm trait. | ||
pub trait Aead { | ||
/// The length of a nonce. | ||
type NonceSize: ArraySize; |
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.
Maybe we should use IvSizeUser
here instead (after renaming it to NonceSizeUser
)? We will get the RNG methods and Nonce
alias "for free". It also would work a bit nicer with the stream traits.
99ed733
to
0a483d1
Compare
/// Constant which defines whether AEAD specification appends or prepends tags. | ||
/// | ||
/// It influences the behavior of the [`Aead::encrypt_to_vec`], [`Aead::decrypt_to_vec`], | ||
/// [`Aead::encrypt_to_buffer`], and [`Aead::decrypt_to_buffer`] methods. | ||
/// | ||
/// If the specification does not explicitly specify tag kind, we default to postfix tags. | ||
const IS_POSTFIX: bool = true; |
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.
I definitely prefer the approach in #1714 of using a marker trait for postfix-tagged AEADs and using that to gate a blanket impl, especially since we can't provide a good efficient implementation of prefix-tagged AEADs.
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.
A separate marker trait would result in a more complex API surface and artificial (in my opinion) restriction on using the postfix methods. Right now we have everything in one trait with easy-to-read docs.
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.
This PR adds hundreds of lines of code and dozens of new methods without adding any real new functionality, other than inout
integration which should only take a few dozen lines of code.
Compared to #1714, the API surface is vastly more complex.
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.
Most of the added methods (to be precise, 8 of them) are inplace
and to_buf
helper methods.
few dozen lines of code
Can you show these "few dozen lines"? Because unless you want to remove the helper methods, I don't see how exactly you plan to do this.
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.
When I have time I'll push up what I have in mind, possibly this weekend or maybe earlier.
As a general statement, this PR contains a lot of breaking and a lot of irrelevant, unrelated changes, especially with its stated goal of addressing #1672. I would generally prefer to see smaller, more focused PRs that try to solve one-problem-at-a-time, and avoid making unnecessary breaking changes. |
Please consider it a ground up redesign of the crate. I was not happy with the existing API for quite some time and it's a good opportunity to work on it. If we are to exclude the |
Should we add something for automatically prepending/appending nonces to ciphertexts? |
I don't think "ground up redesigns" make sense at this point in the project: the I don't think that's the case here and I think the proposed new API is very much a regression. The current design is based on being simple to understand and use. The You have combined these into a "god object" trait with dozens of methods. In doing so you removed the blanket impls that allow the previous traits to abstractly build on one another and replaced them with copy-and-paste code. The crate was previously |
I think a higher-level API that wraps up calling |
No, it will not break user's code without manually updating dependencies. Changes required in user code will be quite small, far smaller than some of API changes in our other popular crates. Arguably, migration to We are still far from 1.0 release and I don't think it's a right time to go full ossification route.
There was nothing "fundamentally" wrong with The question is whether the new API is better long-term or not. I believe the answer is yes, it has one clear AEAD trait instead of splitting functionality into several different traits. It's more consistent with the You call the new One potential split which could be beneficial is between a "core" trait ( We can have a "minimal" number of methods by removing most helper methods, but I doubt users will thank us for that.
All methods in the PR are intended for potential use by users. The trait just has a trifecta of I guess we could remove the
As mentioned in the TODO comment it's a temporary change until the required methods will be added to the |
It's less consistent with the And I think there are problematic aspects to the |
It's a bit off-topic, but that exact trouble are you talking about? We discussed a potential bridge between tweakable and non-tweakable traits. You argued that my bridge proposals are overengineered and I mostly agree. I don't see where the design of |
If you have separate traits for standard block ciphers versus tweakable block ciphers, under the current design you would also have to duplicate all of the methods for using backends as well, which didn't exist in previous versions of the trait: |
It still does not mean that migration will not be annoying. Users still have to manually fix compilation errors and to read the docs. Same for changes in this PR. I agree that documenting migration process for these changes could be helpful.
I wrote a bit about it in an update to my previous comment, but I don't see what can be done differently here. Tweakable and non-tweakable ciphers simply have a different number of arguments. Unless we want to pile even more complexity with generics (e.g. by considering non-tweakable ciphers as tweakable with zero sized tweak), I don't see a good way towards potential unification. |
The current design of the This PR is re-litigating literally everything in the current design 5 years later, in absence of that previous discussion. There was no planning or discussion, or even a prose description of what's wrong with the current design and what the goals of a rewrite are. So far you haven't even identified those things except to say you were "not happy with the existing API". What was wrong? Why does it warrant a ground up rewrite? What is being done differently here to address those issues? I think if you took a step back and tried to actually plan things out by writing down goals, you would discover many of the changes you want don't require a ground-up rewrite but can be done incrementally, which would make them much easier to understand than a single PR that changes everything, especially for anyone reviewing the source history. Perhaps in the process you could avoid capricious breaking changes which don't add new functionality or other improvements but merely generate churn for users of the library. |
As I've written above, I do not consider the ossification arguments to be valid. We are right in the middle of a major breaking release cycle, so it's a good time to reconsider the existing APIs without being tied to backward compatibility. Therefore, I believe the APIs should be evaluated on their own merits, regardless of how long they have existed. 5 years ago we did not have the I have mostly left the Let's review the new methods step-by-step to find where exactly our disagreements start (let's consider only their essence, we can bikeshed the names and traits in which they should be defined separately):
I also have some ideas for an |
It's not an "ossification argument", it's asking you to justify why your changes are an improvement over the old code. If breaking changes aren't actually improvements, if they're just moving things around, if they're not better but just different, then it would be better to leave things as they are, because otherwise you're just making chores for everyone and wasting their time without actually improving the library.
It feels as though your first major contribution to the library is to steamroll over everything, changing literally every method name.
These all seem like things that can be addressed in self-contained PRs, rather than having to rewrite everything at once.
Our disagreements start with how to proceed with these changes. There's an inherent lack of focus in trying to change literally everything at once. I don't think we can drill down on that list productively in this issue. It's too much going on at once. I think it would be better to make separate issues/PRs to discuss each of those changes. You haven't even enumerated everything yet. Just as one example, you've removed the Documentation, or lack thereof, is one of the biggest complaints about this project. I really, really hope this PR doesn't turn into a huge documentation regression. |
You haven't addressed what exactly you consider "moving around" and what not. I've compiled the list specifically for that purpose. The main change in this PR is an
I do not care about methods names, only about their functionality. I will gladly use any naming scheme you want as long as you take a proper look at the PR without being so dismissive just because I apparently "steamroll" over your previous work.
The changes in this PR are connected to each other. The
I have started from the most important part. We can list and discuss the remaining items after we come to some kind of consensus about desired method signatures. Discussing docs, splitting methods into different traits, allowing or disallowing the postfix methods for SIV-like algorithms, etc., comes after that.
Sorry, but are you serious?! I've moved the docs to README, which is included as the crate-level docs. The change has IMPROVED visibility of the nonce docs. I even provided an explicit reference in the |
This PR introduced the unified
Aead
trait which replaces the oldAead*
traits. It addsinout
support and helper methods for buffer-to-buffer encryption and decryption. The trait also provides a set of methods for postfix encryption/decryption.Tag position in ciphertext is defined by the
IS_POSTFIX
associated constant used by theen/decrypt_to_vec
anden/decrypt_to_buffer
methods.The
Buffer
trait is tweaked slightly in accordance to operations which are used in theAead
trait methods.Closes #1672