1
$\begingroup$

I want to read the full output hash of SHA-256 as a number. How I can do it? Is it in the range of 0 to 2^256?

$\endgroup$
4
  • 1
    $\begingroup$ This is rather a programming question because the implementation of the hash functions outputs byte array and the famous GMP library has import and export functions. $\endgroup$
    – kelalaka
    Dec 16 '19 at 10:03
  • 1
    $\begingroup$ This question is not egligible for migration to Stack Overflow. As a theoretical question it might be on-topic here given that byte to integer conversion is a standard problem in cryptography. Answers may contain illustrative code, but don't have to of course. $\endgroup$
    – SEJPM
    Dec 16 '19 at 21:23
  • $\begingroup$ As for your practical concerns, neither standard C++ nor standard JS have a concept of integers larger than 64 bit. If you still need the output as an integer, I suggest you pick a big integer library, there should be plenty available. $\endgroup$
    – SEJPM
    Dec 16 '19 at 21:29
  • 1
    $\begingroup$ For C++ you could also look at crypto libraries. They often contain a so called "bignum" implementation, e.g. the well known Crypto++ has this multi-precision Integer constructor $\endgroup$
    – Maarten Bodewes
    Dec 16 '19 at 22:34
1
$\begingroup$

Yes, the output of SHA-256 is well distributed over the entire output of the hash function. That also means that any number generated by unknown input is well distributed, of course.

Which number is represented depends on the number system. If you want to interpret it to be in the range $\big[0, 2^{256}\big)$ then that's certainly possible - and the most likely interpretation by cryptographers (as most cryptographic algorithms use modular operations, and those are most easily defined to use zero- or positive integers).

To use SHA-256 as a positive number you simply interpret it as a statically sized, unsigned number.

Now the fact that it is statically sized doesn't matter much, as any library will likely skip leading zeros. It may however an issue if you want to revert back to bytes.

That leaves the issue of endianness of the number. You can interpret such a value as big endian (network order) number or little endian number. In case of big endian the most significant byte is on the left, while in little endian it is on the right. As the number is well distributed, each interpretation is equally valid - but obviously they will lead to different values with near-certainty for such large values. Generally cryptographers prefer big endian, especially for large number calculations as e.g. in RSA.

One way to do this for C++ is to use a cryptographic library, where such conversions are common. E.g. in Crypto++ there is the Integer constructor with a constructor using the following signature:

Integer::Integer  (   const byte *    encodedInteger,
                        size_t          byteCount,
                        Signedness      sign = UNSIGNED,
                        ByteOrder       order = BIG_ENDIAN_ORDER 
                    )       

Here encodedInteger would be the hash value of 32 bytes, byteCount would then be set to 32 of course. sign already defaults to unsigned as this is about cryptography and byte order has the right default as well. Beware that not every "BigNum" implementation will have such cryptographically sensible defaults - Java's BigInteger for instance does require you to explicitly indicate that the result should be interpreted as unsigned value.

In the RSA standard the operation is known as the Octet String to Integer Primitive (OS2IP). Please do note though that the formula for that method mathematically describes the usual layout of the bytes in memory. There is no need to perform any exponentiation or multiplication to implement such functionality.

$\endgroup$
2
  • $\begingroup$ ... and yes, I did find an implementation in Java that did compute the value of the number using multiplication and exponentiation. Nothing will surprise me anymore in that sense. Although the BigNum implementation called BigDecimal that used base 10 calculations made me more than chuckle. $\endgroup$
    – Maarten Bodewes
    Dec 17 '19 at 13:05
  • $\begingroup$ Oh, yeah, JavaScript seems to have a BigInt in some browsers, although you probably have to use hexadecimals rather than bytes directly. Personally I think that both C++ and JavaScript languages are terrible for starting cryptographers, the chance of shooting yourself in the foot are huge. $\endgroup$
    – Maarten Bodewes
    Dec 17 '19 at 14:08
0
$\begingroup$

Yesish. It would be $ 0 \to (2^{256} -1) $ due to that zero index thing with computers. The distribution of numbers/bytes/bits is fair. You should be able to deduce what you want from Class BigInteger.

$\endgroup$
4
  • $\begingroup$ I want to read by javascript or c++. Can you help me, @Paul Uszak? $\endgroup$ Dec 16 '19 at 6:27
  • $\begingroup$ @CôngNguyễn I'm sorry, I can't as C/C++ isn't my forte. But has kelalaka's comment helped? $\endgroup$
    – Paul Uszak
    Dec 16 '19 at 16:49
  • 1
    $\begingroup$ What kind of weird notation for a range of integers is that? $\endgroup$
    – Maeher
    Dec 16 '19 at 17:35
  • $\begingroup$ For any Java users out there, you'd have to use new BigInteger(1, byte[]) rather than just new BigInteger(byte[]) as there is a 50% chance that you end up with a negative value if you'd use the latter. $\endgroup$
    – Maarten Bodewes
    Dec 18 '19 at 19:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.