1
$\begingroup$

Let's suppose we are hashing a string input from the user via keyboard. A string can be interpreted in many different text encodings (ANSI, UTF-8, UTF-16 and many others). Based on what encoding is used, the underlying binary data and therefore the hashes can be completely different, even though it seems like the same text was entered and the same algorithm was used.

However, I noticed that no matter how many hashing tools I try, hashes are always the same. Hashing apple with SHA-256 gives the same output everywhere.

Is there a consensus on what text encoding to use when hashing a string input? If there is, how wide-spread this consensus is? And what is the rationale behind the choice?

$\endgroup$
  • $\begingroup$ Are you asking if there is a consensus as to what binary representation apple has in a given encoding like UTF-8, or are you asking if there is a consensus as to the specific encoding to use? $\endgroup$ – forest Jul 21 '18 at 6:35
  • 1
    $\begingroup$ @forest I'm asking the latter (consensus about what encoding to use). I know that each string's binary representation is defined by the standards of a specific encoding. $\endgroup$ – Sutarbi Dudek Jul 21 '18 at 13:59
  • $\begingroup$ Somewhat relevant (especially the password profile?): RFC 8265. $\endgroup$ – SEJPM Jul 24 '18 at 11:41
5
$\begingroup$

Hashing is done on binary, not text strings. It is the job of the character encoding to say what binary representation a string will have. After you represent the text using a particular encoding, then you can hash it. The hash process itself does not care at all about encoding, only binary.

There is no consensus as to what the binary representation a given string will be in every circumstance (i.e. how apple will look in binary), but there is a consensus as to what the hash itself uses as input, which is binary. Most strings use the same encoding (ASCII, UTF-8, etc), and since an encoding is needed to convert a string into a binary representation, the most common encodings will be used when hashing said string. This is not universal, of course. If you enter a string on a Japanese system into a hash function, you may get a different result due to it using Shift JIS or UTF-16, for example. Simply put, there is a consensus in what text encoding to use when encoding text, but it does not specify how that string will be used (e.g. passed to a hash).

Note also that many different text encoding formats are redundant for many characters. ASCII characters are represented as the same string of bits when they are encoded instead as UTF-8. The biggest difference is that UTF-8 is capable of encoding characters that ASCII cannot. Because virtually everyone is using either ASCII or UTF-8, the string apple will be the same in all of them.

$\endgroup$
  • $\begingroup$ Comments are not for extended discussion; this conversation has been moved to chat. $\endgroup$ – e-sushi Jul 21 '18 at 7:00
2
$\begingroup$

The consensus is: a hash generally expects binary bits as input (practically, most implementations therefore handle it using binary bytes, aka 8-bit unsigned chars in the range 0x00-0xFF) and it will generally output binary bits (which most implementations output as a series of binary bytes, aka 8-bit unsigned chars) as well.

Now, since a hash generally does not handle any text encoding, this means you’ll practically have to convert things like UTF-16 (which is a multi-byte representation) and UTF-8 (which also partly contains multi-byte chars) to “raw binary bytes” accordingly so that you can feed the binary representation to the hashing function. Not doing this can and will result in glitches in your implementation, as one can frequently find in online tools which try to offer – for example – Javascript SHA-256 and alike hashing, but fail to produce the correct hash values due to wrong or missing conversion of the text encoding. You have to feed your hash a series of binary bits. Practically, the majority of implementations handles those input and output bits using 8-bit binary bytes (aka 8-bit unsigned chars, aka UINT8) as that’s what most modern-day devices work with natively/internally.

Same goes for the output. Any hex representation of a hash is the result of the hash output being converted from an set of bits (mostly implemented as an output of 8-bit unsigned chars) to their equivalent hex representation.


As for the programming part of your question: Hashes do not care what you hash... at all. How you process data before or after hashing is a purely programming-related question and out of the scope of this site.

As for text encoding to choose — that's entirely up to you and strictly depends on your individual scenario. From a programmatic point of view, I would point at UTF8, but one might equally argue that UTF-16 is the way to go, as it offers enhanced support for (eg) Asian languages. Also, it's what languages like Javascript and Java use internally. In the end, it depends on your project and how you want to handle your data... but that decision is — as I noted — not a cryptographically one.


TL;DR: Formally, almost all cryptographic hashes work on one or more binary bits. This is why hash functions like MD5, SHA-1, the SHA-2 family, and SHA-3 all take binary input, work binary internally, and produce a binary output. How you handle your (text) data before or after hashing it is up to you and your programming goals or the individual standards you follow (web standards mostly point to UTF-8 for example), but how you handle your strings in your program is not unrelated to cryptography.

$\endgroup$
  • $\begingroup$ Comments are not for extended discussion; this conversation has been moved to chat. $\endgroup$ – e-sushi Jul 21 '18 at 6:58
1
$\begingroup$

No, there is no consensus. It would be counterproductive anyways - hash algorithms like SHA* are supposed to work for any binary data, period.

If apple gives always the same, you didn't use different text encodings like UTF16, as simple as that.
With the countless more or less bad websites that offer you to hash something, there is no possibility to select any encoding for the text or to submit raw binary data, and most of them will use ASCII/ISO88591/UTF8 (apple is the same in all of them). Use something that actually hashes raw data, not some hobby website.

$\endgroup$
  • $\begingroup$ Why do you think it would be counterproductive? Arriving at the same hashes on different platforms and applications is in fact useful. I'm actually glad hey all gave the same hash, I'm just trying to figure out which encoding that is and why. So do you think it's UTF-8 or some subset of it? $\endgroup$ – Sutarbi Dudek Jul 21 '18 at 0:02
  • 2
    $\begingroup$ Because a) For a cryptographic hash like SHA*, "correcting" the input for the user (converting to encoding Y) is a nasty security problem. b) Specifying some text encoding as part of the hash makes it unsuitable for all non-texts (and no, it's not as easy as saying "if text then encoding", eg. because there many cases where it is not very clear what is to be considered as text). c) Unicode is hella complicated, just most people don't implement it correctly because they don't know it. I want my 100% correct hash without a 100MB software. (Yes I'm serious.) $\endgroup$ – deviantfan Jul 21 '18 at 0:39
  • 1
    $\begingroup$ And, btw. ISO88591 is not a subset of UTF8. $\endgroup$ – deviantfan Jul 21 '18 at 0:40

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.