128-bit values on 64-bit architecture in C

1.3k Views Asked by At

I am implementing SHA-512 on 64-bit Linux in C. SHA-512 accepts 128 bits as the length of data to be hashed. Currently I am taking two 64-bit long ints to comprise the 128-bit value but I am puttingg zeros intentionally to the first 64 bits and the length is stored in the remaining lower 64 bits. Why am I doing this?

Well I think on 64-bit architectures, I probably won't ever get a value more than 264 or can I? Is this the right way to implement SHA-512 on 64-bit architecture or is there any way to cater 128-bit values on 64-bit architectures that I don't know? The point to note is that I am implementing SHA-512 according to FIPS 180-3.

Any help would highly appreciated.

2

There are 2 best solutions below

0
On BEST ANSWER

I hope that by "64 bit long ints", you really mean unsigned long ints... Seriously, don't do your own SHA-512 implementation until you fully understand how bigint arithmetic is done using smaller integers.

If you want to implement something conforming, then use the full 128 bit. If you use one single function call to hash the complete block, you will hardly need the full 128 bit, 64 will be ok. But to be conforming, you should allow to hash a complete block in packets. Thus you have 3 functions like these:

Init - Initializes the internal state for the next hashing.

Add - Adds a block of data to the current hashing, with internal buffering of incomplete blocks and internal count of the 128 bit size. It takes a block of memory, so a clean C-style interface would use size_t for the number of bytes. However, a 64 bit unsigned integer is good enough for the intended purpose and simplifies the counting.

Finish - Does the padding, completes the hashing and returns the final hash value.

Obviously, this approach needs an additional externally visible struct to hold the current state.

0
On

128-bits integers in GCC

As an extension the integer scalar type __int128 is supported for targets having an integer mode wide enough to hold 128-bit. Simply write __int128 for a signed 128-bit integer, or unsigned __int128 for an unsigned 128-bit integer. There is no support in GCC to express an integer constant of type __int128 for targets having long long integer with less then 128 bit width.