Skip to content
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

Compile-time output length #4065

Open
Chaosvex opened this issue May 20, 2024 · 3 comments
Open

Compile-time output length #4065

Chaosvex opened this issue May 20, 2024 · 3 comments
Labels
enhancement Enhancement or new feature

Comments

@Chaosvex
Copy link

Chaosvex commented May 20, 2024

Just wanted to open a discussion about HashFunction's output_length().

One feature that would be nice to have would be to a way to get the output length at compile-time rather than relying on runtime asserts. In cases where you don't want to Botan allocating a vector for the result, it's cumbersome and error-prone (been there, done that) to have to do something like:

std::array<std::uint8_t, 20> result;
...
assert(result.size() == hasher->output_length();
hasher->update(...);
hasher->final(result.data());

It'd be nice to be able to just write something akin to:

std::array<std::uint8_t, Botan::SHA_160::output_length()> result;
static_assert(Botan::SHA_160::output_length() == result.size()); // *or* this
...
hasher->update(...);
hasher->final(result.data());

This would have been trivial to add under the original v1 design but the newer string-based interface rules it out. I saw that there's an open discussion on providing a better interface but that has a much wider scope and as such, it seems unlikely to go anywhere.

I do have some thoughts on possible solutions but the changes required would feel a little disjointed, but at least the scope would be narrow and wouldn't introduce any breaking changes. However, if a new interface was likely to be on the horizon, it'd be better to hold off.

Thanks!

@randombit
Copy link
Owner

I can absolutely understand why you'd want this. But it may not be really possible for us to provide it. Really we couldn't provide it even in the old interface with a named-class-per-algorithm; it works in your example but not for SHA-3, BLAKE, SHAKE, etc since there there is a variable output length which is parameterized at runtime.

The best approach I can see that might get you some of the way to what you're looking for would be a hypothetical API that I just made up.

enum class HashFunctionParams {
  SHA_1,
  SHA_256,
  SHA_3(size_t), // in my imagination C++ also has sum types; we could fake this in various ways
  ...
};

constexpr size_t HashFunctionParams::output_length() {
   switch(*this) {
     case HashFunctionParams::SHA_1: return 20;
     case HashFunctionParams::SHA_256: return 32;
     //...
    }
}

constexpr auto hash_id = HashFunctionParams::SHA_1;
auto hash = HashFunction::create_from_params(hash_id);
hash->update(whatever);
std::array<uint8_t, hash_id.output_length()> digest;
hash->final(digest.data());

This would actually be pretty nice and avoid a lot of string handling that we're otherwise stuck with during algorithm creation.

But, this isn't something that's likely to happen very soon.

@randombit randombit added the enhancement Enhancement or new feature label May 21, 2024
@Chaosvex
Copy link
Author

Chaosvex commented May 21, 2024

Thanks for the input. I hadn't considered the case of the variable output length functions (I haven't used those).

@reneme
Copy link
Collaborator

reneme commented May 22, 2024

Such a thing would also be useful for some internal use cases. We did have some discussion about something similar in the context of asynchronous algorithms. And there's a ticket tracking this todo (for the record): #3706.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement or new feature
Projects
None yet
Development

No branches or pull requests

3 participants