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

Finalising a sha256 has into an [u8; 32] #572

Closed
WhyNotHugo opened this issue Mar 13, 2024 · 9 comments
Closed

Finalising a sha256 has into an [u8; 32] #572

WhyNotHugo opened this issue Mar 13, 2024 · 9 comments

Comments

@WhyNotHugo
Copy link

WhyNotHugo commented Mar 13, 2024

I'm trying to generate the sha256 for some data into a [u8; 32]. I currently have some code that hashes my data into a string (e.g.: a hex representation of the hash):

pub(crate) fn hash(raw_data: impl AsRef<str>) -> String {
    let mut hasher = Sha256::new();

    // ...
    hasher.update(some_data);
    hasher.update(some_data);
    // ...

    format!("{:X}", hasher.finalize())
}

I'd like for this to return a [u8;8] instead, but I'm having a really hard time understanding what's going on beneath so many layers of abstractions. Sha256::new() returns a CoreWrapper<CtVariableCoreWrapper<Sha256VarCore, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>, OidSha256>>. It's not very clear to me what CoreWrapper<CtVariableCoreWrapper<Sha256VarCore, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>, OidSha256>> is or or how I'm supposed to reason about it beyond the basic examples in the README. The documentation for CoreWrapper points to block_buffer::BlockBuffer, but that seems to be something used when implementing a hash function, not when using one.

CoreWrapper<CtVariableCoreWrapper<Sha256VarCore, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>, OidSha256>> implements Digest, which has a finalize_into method, but that expects an un-exported type as input, so it doesn't seem to be what I'm looking for.

Is there any way to write the digest directly into a [u8;32]?

@newpavlov
Copy link
Member

newpavlov commented Mar 13, 2024

finalize for SHA-256 returns GenericArray<u8; U32> (you can not click on type in the digest docs because of a certain rustdoc bug) which effectively is [u8; 32]. It implements Into<[u8; 32]> trait, so you can write let hash: [u8; 32] = hasher.finalize().into();. Now, if you want to return only 8 bytes, you have to decide which bytes to take and which to discard. GenericArray supports all the usual slice operations, so it should be easy to do.

@tarcieri
Copy link
Member

@WhyNotHugo regarding the diagnostics, here's a tracking issue for that: RustCrypto/traits#1069

@WhyNotHugo WhyNotHugo changed the title Finalising a sha256 has into an [u8; 8] Finalising a sha256 has into an [u8; 32] Mar 13, 2024
@WhyNotHugo
Copy link
Author

Er, sorry, I meant [u8;32], my bad.

@WhyNotHugo
Copy link
Author

let hash: [u8; 32] = hasher.finalize().into(); would generate a GenericArray<u8; U32> and then convert that into an array. Is there some way to get the hash directly without the intermediate type?

@tarcieri
Copy link
Member

You should be able to do something like:

let mut buf = [0u8; 32];
digest.finalize_into(buf.as_ref());

(it might require .as_ref().into())

However note that there's no cost to the "intermediate type" and these two are really equivalent.

@WhyNotHugo
Copy link
Author

Thanks, let hash: [u8; 32] = hasher.finalize().into(); works fine.

I prefer to avoid adding generic-array as a direct dependency and using GenericArray directly since I don't want internal implementation details of sha2 leaking into my own codebase.

@WhyNotHugo
Copy link
Author

However note that there's no cost to the "intermediate type" and these two are really equivalent.

This is a good-to-know. Do you think it's worth including the example above in the README or in the docs?

@newpavlov
Copy link
Member

We are in the process of migrating to hybrid-array, which will make extraction of array easier, so it's probably not worth to write new GenericArray-centric docs now.

@WhyNotHugo
Copy link
Author

Nice, happy to see that there is also a path to move onto const-generic, that will definitely make things simpler on the API side :)

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

No branches or pull requests

3 participants