Sometimes, it is useful to hide a string from a binary (executable) file. For example, it makes sense to hide encryption keys from binaries.
When I say “hide”, I mean making strings harder to find in the compiled binary.
For example, this code:
const char* encryptionKey = "My strong encryption key";
// Using the key
after compilation produces an executable file with the following in its data section:
4D 79 20 73 74 72 6F 6E-67 20 65 6E 63 72 79 70 |My strong encryp|
74 69 6F 6E 20 6B 65 79 |tion key |
You can see that our secret string can be easily found and/or modified.
I could hide the string…
char encryptionKey[30];
int n = 0;
encryptionKey[n++] = 'M';
encryptionKey[n++] = 'y';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 's';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'g';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'c';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'y';
encryptionKey[n++] = 'p';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'i';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'k';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'y';
…but it's not a nice method. Any better ideas?
PS: I know that merely hiding secrets doesn't work against a determined attacker, but it's much better than nothing…
Also, I know about assymetric encryption, but it's not acceptable in this case. I am refactoring an existing appication which uses Blowfish encryption and passes encrypted data to the server (the server decrypts the data with the same key).
I can't change the encryption algorithm because I need to provide backward compatibility. I can't even change the encryption key.
I wonder if after first obscuring it like others have mentioned, you could embed your string in an assembly block to try and make it look like instructions. You could then have an "if 0" or "goto just_past_string_assembly" to jump over the "code" which is really hiding your string. This would probably require a bit more work to retrieve the string in code (a one-time coding cost), but it might prove to be a bit more obscure.
This is as secure as leaving your bike unlocked in Amsterdam, the Netherlands near Central Station. (Blink, and it's gone!)
If you're trying to add security to your application then you're doomed to fail from the start since any protection scheme will fail. All you can do is make it more complex for a hacker to find the information he needs. Still, a few tricks:
*) Make sure the string is stored as UTF-16 in your binary.
*) Add numbers and special characters to the string.
*) Use an array of 32-bits integers instead of a string! Convert each to a string and concatenate them all.
*) Use a GUID, store it as binary and convert it to a string to use.
And if you really need some pre-defined text, encrypt it and store the encrypted value in your binary. Decrypt it in runtime where the key to decrypt is one of the options I've mentioned before.
Do realize that hackers will tend to crack your application in other ways than this. Even an expert at cryptography will not be able to keep something safe. In general, the only thing that protects you is the profit a hacker can gain from hacking your code, compared to the cost of hacking it. (These costs would often be just a lot of time, but if it takes a week to hack your application and just 2 days to hack something else, something else is more likely to be attacked.)
Reply to comment: UTF-16 would be two bytes per character, thus harder to recognize for users who look at a dump of the binary, simply because there's an additional byte between every letter. You can still see the words, though. UTF-32 would even be better because it adds more space between letters. Then again, you could also compress the text a bit by changing to an 6-bit-per-character scheme. Every 4 characters would then compact to three numbers. But this would restrict you to 2x26 letters, 10 digits and perhaps the space and dot to get at 64 characters.
The use of a GUID is practical if you store the GUID in it's binary format, not it's textual format. A GUID is 16 bytes long and can be randomly generated. Thus it's difficult to guess the GUID that's used as password. But if you still need to send plain text over, a GUID could be converted to a string representation to be something like "3F2504E0-4F89-11D3-9A0C-0305E82C3301". (Or Base64-encoded as "7QDBkvCA1+B9K/U0vrQx1A==".) But users won't see any plain text in the code, just some apparently random data. Not all bytes in a GUID are random, though. There's a version number hidden in GUIDs. Using a GUID isn't the best option for cryptographic purposes, though. It's either calculated based on your MAC address or by a pseudo-random number, making it reasonable predictable. Still, it's easy to create and easy to store, convert and use. Creating something longer doesn't add more value since a hacker would just try to find other tricks to crack the security. It's just a question about how willing they are to invest more time into analyzing the binaries.
In general, the most important thing that keeps your applications safe is the number of people who are interested in it. If no one cares about your application then no one will bother to hack it either. When you're the top product with 500 million users, then your application is cracked within an hour.
If you store the encryption key in reverse ("yek noitpyrcne gnorts yM") and then reverse it in your code (String.Reverse), this would prevent a simple search through the binary for the text of your encryption key.
To reiterate the point made by every other poster here, however, this will accomplish virtually nothing for you in terms of security.
It's a client-server application! Don't store it in the client itself, that's the place where hackers will obviously look. Instead, add (for your new client only) an extra server function (over HTTPS) to retrieve this password. Thus this password should never hit the client disk.
As a bonus, it becomes a lot easier to fix the server later. Just send a different, per-client time-limited password every time. Don't forget to allow for longer passwords in your new client.
As noted in the comment to pavium's answer, you have two choices:
Unfortunately, if you must resort to embedding both the key and the algorithm within the code, neither is truly secret, so you're left with the (far weaker) alternative of security through obscurity. In other words, as you mentioned, you need a clever way to hide either or both of them inside your executable.
Here are some options, though you need to remember that none of these is truly secure according to any cryptographic best practices, and each has its drawbacks:
printf()
statement, which tends to have numbers, letters, and punctuation.int
,char
, etc.), take a byte from somewhere within each variable after it's initialized (to a non-zero value, of course) and before it changes.Please let us know how you solve the problem!
Edit: You commented that you're refactoring existing code, so I'll assume you can't necessarily choose the key yourself. In that case, follow a 2-step process: Use one of the above methods to encrypt the key itself, then use that key to decrypt the users' data.
I'm sorry for long answer.
Your answers are absolutely correct, but the question was how to hide string and do it nicely.
I did it in such way:
HideString.h:
Most tricky line in HideString.h is:
Lets me explane the line. For code:
generate sequence: generate:and finally,
generate:data for "My strong encryption key" looks like:
Thank you very much for your answers!