The code below

if(str1 == "abc") {}

can be converted to

if(hash(str1) == 0x8732e) {} // assume hash("abc") == 0x8732e

to obfuscate the code.

But they are not equivalent when hash collision occurs; e.g., str1 = "xyz"'s hash value is the same as "abc".

That is true theoretically. But is it an issue in real-life when the method above is used to obfuscate code? Is it a well accepted obfuscation method?

  • 5
    You're saying "code" and "obfuscate code" but what you've provided is a method of obfuscating the value of a string -- and a somewhat poor one at that, as now the test is vulnerable to the collisions you mention. What are you really trying to accomplish? – alzee Aug 5 '16 at 15:32
  • You can significantly reduce collisions by storing length of string with hash. Getting collision for two strings of same length is very unlikely. – Aria Aug 5 '16 at 18:51
  • 2
    @Aria: Whether that's true or not depends on the hash function, but let's assume for now that it's true. The problem is, that dramatically narrows the search space for a brute-force attack on the hash. Unless your string is long enough that there are more collisions in strings of length 1 - (N-1) than there are in strings of length exactly N, you've made the attacker's job easier if you tell them the length. Depending on how predictable the string is (i.e. if you're picking from an already-narrowed range of options) revealing the length may dramatically speed the search – CBHacking Aug 5 '16 at 18:57
  • 1
    Also posted on Crypto.SE. Please do not post the same question on multiple sites. Each community should have an honest shot at answering without anybody's time being wasted. – D.W. Aug 8 '16 at 16:32
  • If this is for some sort of license key check, then be aware that someone who reverse engineered this code will simply patch the code to if (true) or something similar. – Lie Ryan Feb 21 '19 at 9:28

The example hash digest you gave is wayyyyyyy too short (20 bits, or about a million possibilities), so you'd get collisions far too often and, worse, anybody who decompiled your program could trivially produce the correct strings (or, at least, strings that are acceptable due to hash collisions) just by brute-forcing the likely input space.

"That's a silly objection. It's just an example..." you might say, but it really isn't. I've found, and exploited, this exact type of weakness before. For example, there was a mobile app that used a 32-bit hash function on user inputs to try and hide what inputs would produce what outputs. It took under an hour to write, and run, a program that brute-forced the search space and found inputs that mapped to every hash digest the app was looking for.

In essence, this is much like trying to store passwords securely. There are definitely differences - passwords are rarely very long, while hardcoded strings in a program can be, and if you're performing the string equality test frequently then you can't afford for it to be as slow as a good password verify function would be - but a lot of the same parallels hold. Use a strong hash function, not just resilient to collisions and reversal but also ideally one that isn't so fast its possible to brute-force the whole search space. For short strings, use a salt so that people can't just look up the value in a rainbow table.

Now, as for actual obfuscation: this technique is one (of a great many) that obfuscation can use. It's usually not very effective, especially when implemented weakly (see my second paragraph), and has enough performance impact that it isn't usually used except selectively in places where the slowdown isn't a big deal. Obfuscation in general is a non-solution; at best it slows down reverse engineering enough that by the time the RE is complete the codebase is old enough nobody cares, without causing undue performance or program logic bugs in the meantime. In practice, though, it's usually not that good.

| improve this answer | |

It's not useful

That doesn't really do a good job at obfuscating. If you check against specific strings, those strings probably will occur in the RAM at some point (even during normal usage). An attacker can simply hash the strings they find in the RAM of your program, find a collision, and replace the corresponding parts of the code with the string they found.

It's stupid

Furthermore, pretty much every reason to obfuscate code is stupid – but that's besides to point.

Don't do it

What you should see is that there is a risk of failure. Namely when a hash collision occurs. Because of the way hash functions are designed, for probabilistic calculations we can assume the output of the hash function to be random for every input we haven't tried yet.

If there are several hash values the hash of a varying string are compared to, you can calculate the rate of failure for that comparison using the approximative formula of the birthday paradox ](http://quicklatex.com/cache3/45/ql_670d776bee64464b0374f373c73fa445_l3.png) where [![]1
(source: quicklatex.com) is the size of the codomain of the hash function and
(source: quicklatex.com) is the number of different values the varying string will take.

Once you got that probability for every string comparison in your program, multiply them and call the number you get
(source: quicklatex.com) . The probability that the program will fail is ](http://quicklatex.com/cache3/f1/ql_68b660535c454533f648fe00f7bbccf1_l3.png). If the program will be executed [![]4
(source: quicklatex.com) times that way, the probability that it will fail is http://quicklatex.com/cache3/98/ql_9d24cd1aa3adc352b991541de5630a98_l3.png.

If you value the small amount of obfuscation more than you fear the consequences of your program failing with the probability of http://quicklatex.com/cache3/98/ql_9d24cd1aa3adc352b991541de5630a98_l3.png, do it. Otherwise don't.

| improve this answer | |
  • some of the equation images return "404 not found".. – Amro May 20 '17 at 9:36
  • Yeah, @UTF-8 if you're around, please repair the post. My bot usually makes good edits but failed rather miserably here. – Glorfindel Feb 21 '19 at 9:37

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.