Obfuscating encryption password in source code and difficulty of hacking - c#

I am developing mobile game based on C# language. The game's save file will be encrypted by simple password that is stored in the source code. If player were to easily see and edit this file the game would be too easy.
The game itself is not online so if he managed to hack it, it will not bother or create unfairness to other people, so I didn't bother about security that much and I choose to store the password in the code directly to reduce my hassle also.
However I guess with some decompiler someone can directly see the password being declared? I want to ask about some simple way to make password-in-the-source harder to hack. For example, currently I read the password from public static readonly variable. I wonder which one of these adds difficulty to the hacker, or not at all?
Change to private static readonly variable.
Change to private variable of the class. (I am guessing the heap where static variable is stored is easier to hack?)
Change to local variable of save file reading method.
Split the string to several parts and place it in different source files. At the point that code reads save file, it reassemble all the pieces by concatenating them all sequentially.
I create a long seemingly random string that looks like a password, but actually I will pick only some characters from it to construct the true password.
There are 2 passwords. The first one is being encrypted using another password as an encryption key. Decrypt the password to get the true password. Both password will be stored directly in the source code.
I guess I have to know how C# decompiler works, but I have no idea about it. If you have better idea that is not so hard to implement, feel free to add.

Related

Question about encrypting and authenticating instruction file in a .net desktop application

I want to do the below. What is the best way to achieve this?
I have a desktop app in C# which will be installed on multiple client machines.
The application is capable of doing an operation X but it needs some auxillary info which it can read from a file. This auxiliary info essentially provides some specifics that identify that machine where the operation should be run and what operation to run etc.
I will work with the client to get some of this auxilary info about his machine (say hostname/ip address etc) which I want to put in this file along with other info and generate it on my machine and share it with him/her to provide it to my software. I want to encrypt this data so that the structure of the data is not obvious to somebody who opens it. (I will get some of the machine identification info from the client, either via phone or email).
I want to somehow encrypt and secure this file such that only I can generate the file but any of my installations can read it. But since the contained info is specific to a machine it will be executed only on one machine (other machines will read but reject it since the given hostname/ip etc won't match that machine)
How do I do this? I want to make sure the below:
Only I can generate this file.
I need to somehow authenticate that this is generated only by me and not by somebody else.
But my software on client machines should be able to decrypt this.
I don't want to take a password from the customer etc. all the decryption logic should be in the installed software itself. I want to code it in.
When I researched this online, many talk about public and private cryptography but there they talk about encrypting with the public key and decrypting with the private key. But I don't think this will work since decryption is being done by my software at the client machine and so I shouldn't put the private key in my code. Because, from what I read, private key can generate public key so somebody could potentially generate that instruction file if I do this.
What is the best way to do this? Can I encrypt with private key and decrypt with public key? Is it ok if somebody gets hold of my public key (say they disassemble the C# code)? Any other good ways to encrypt and authenticate such that I hold the private data with me but code only harmless public keys/data in the application?
TIA.
Who are you trying to protect this from?
You are giving the end user your application binary. Assume they can decompile it and work out how it works. Or step through your code in a debugger, with access to the contents of every variable. Assume that an attacker can learn everything they need to know about how it works.
At best I would recommend creating a hash of the machine details and a salt value. Then create a signature of that hash.
Keep the salt and the public key of the signature as a constant in the application binary. Maybe XOR values together so an attacker has to think a little about how it works.
But anything more is pointless. Any attacker with more skills will just patch your program to delete the test entirely. So I wouldn't bother building anything too complicated.
Giving someone a program, and preventing them from using it, is like trying to make water not wet.
You have two questions
How do you encrypt the information, and
How can your client make sure the information came from you.
Those are orthogonal
I'll address the second on first - it's easier.
First, hash the file, and add the hash to the payload. Then generate a public/private key pair, then encrypt some known (but non-trivial) information with the private key and add that to the payload. You can distribute the public key with your app. If your app hashes the file and the hashes match and it can decrypt the known information and make sense of it, then it came from you and no one has changed it.
This is known as a digital signature. If you look up a digital signature provider and follow the docs, it should just work.
The encryption problem is more of an issue. There's pretty much no way to do what you want. If your app can decrypt the information using information you distribute with the application, then a determined bad guy can extract that key material and decrypt it.
However, you can use the RSA key container on the client to do the encryption when you install the app. The process is similar to using encrypted sections in a web.config file. Since you won't be following the encrypted config section cookbook the process is complicated.
I've done this before, but it was several jobs ago, so I don't have anything I can show you.
But, it will be encrypted so that it can be read only where it was encrypted. No two installations will recognize each others files.
That said...
Encryption seems like a heavy hammer to prevent your customers from being able to guess "the structure of the data [so that it] is not obvious to somebody who opens it"
Unless you have something worth protecting, you can probably get away with obfuscating the data. For example, you could have the data as JSON, but then use GetBytes on a Utf8Encoding to get a byte[] and convert that to a hex string. A determined hacker could decompile you code, figure out what you've done and reverse it, but that doesn't seem like a threat you really need to worry about.

C# Decrypted Values and Public Class Properties...What is the risk?

(If this is a duplicate post, please point me to the original or tell me what to search for. I could not find anything. Thank you!)
So, I have an encrypted value saved in a database row. I want to retrieve the column values for the database row and store them in a class instance. Is it safe to create a public property on the class for the DECRYPTED value?
public class *DataRow*
{
public string *DataElement* { get; set; }
public string *Value_Decrypted* { get; set; }
}
Can an external process somehow access the public property? Do I need to use SecureString (or something else) to protect against memory hacks? Does .NET's DataProtection help with any of this?
Is there a practical guide/walkthrough somewhere for how to handle this (hopefully without too much coding overhead)?
These feel like pretty basic questions (ashamed), and I have heard talk about these concerns, but in my searching I could not find anything. Wasn't sure what to search for (other than what's in the Title of this post).
As always, any direction will be greatly appreciated.
Thank you!
EDIT:
Thank you everyone for the responses. Password was a BAD example--I understand it is ill advised and usually unnecessary to decrypt a password. I guess my question is more general, relative to how to handle data that does need to be decrypted. I have updated my example to reference an encrypted/decrypted value instead of a password.
I am writing a generic monitor program and need to save access values, paths and commands in a database. I feel it's best to encrypt these values in an effort to minimize exposure of our infrastructure, etc.
The consensus seems to be that saving the decrypted value in any form, property or otherwise, is a bad idea.
I am now thinking that I will store only the encrypted value and then decrypt it, using a SecureString, every time I need it.
Thank you all again!!
Usually password decryption is not necessary. If you let users pick their own passwords it is even unethical.
Having said that:
You should use a one way encryption. Otherwise a SecureString. Consider all public and private members unsafe in this context.
For the one way encryption,some basics: Encrypt password. Store it in database. If you want to check the password, encrypt the inputted data and check if it matches the encrypted value in the database. The encryption is usually seeded with a random salt value.
Check this link for encryption with salt:
https://stackoverflow.com/a/2138588/2416958
The best practice is that you use a One Way encyption method to scramble the password. This prevents the original data from being exposed to any third party and can be only verified by the owner of the password.
No matter what modifier you use for your password filed (private, protected), that value can still be stolen.
Just like Stefan says, it's never a good idea to decrypt the password and store the decrypted version anywhere for any period of time. It's unsafe and at times unethical. You shouldn't even be able to decrypt your users' passwords. Once the user keys in their password, that should be the last time said password is seen in it's decrypted form.
You don't want the encrypted password to be sent back from the server across the network either as an attacker may find a pattern and find out your encryption method which is again not desirable. That's why whenever a user tries to log in, you get their attempt and encrypt it internally and check it against the encrypted version.
Public/Private access modifiers to class's fields were never intended for security purposes. They are there for encapsulation and data hiding for design purposes(as an example a private field can always be accessed through reflection).

Going back from signed hash with RSA SignHash

I'm extremely n00b at this. I'm not even sure if what I'm asking is correct.
I've been asked to decrypt some package, but I found that the package is not being encrypted, instead the package (byte []) has a .zip inside protected with a password.
So now I have to retrieve that password. I tracked it in the code and came to this:
lSupraHeader = lCryptoTransformRSA.SignHash(lSupraHeader, CryptoConfig.MapNameToOID("SHA512"));
lSupraHeader is a Byte [] that contains (between other things) the password. If I get the string from lSupraHeader I can read the password, the problem is that after that "SignHash" I can't get it any more, well, I don't know how to do it.
That code was made a while ago, and change it is not an option for me.
Is there a way to retrieve that password from there? Is is correct what I'm asking whit what I provided or do I need something else?
Is there a way to retrieve that password from there?
No. Once data has been hashed, it cannot be unhashed.
SHA is also known as a "one-way hashing algorithm". It is designed so that any amount of data can be put into it, and a finite amount of data comes out. Such things are useful to check to see if two pieces of data are equal, although this method also has flaws (for which there are various workarounds).
Encryption, on the other hand, takes in data, uses a key, and spits out a bunch of random data roughly equal in size to the original data. Using the same key, the random data can then be unencrypted, or decrypted, to yield the original data.
Having said that:
I tracked it in the code and came to this:
How did you find that out? It would appear that you have access to source code and a debugger. If this is true, then see if you can find an "immediate window" in your debugger. You may be able to set a breakpoint, execute Console.WriteLine(whatever), and manually retrieve the password that way. Doing this would leave the original code untouched.

How can I change file permissions so only a certain program can access it?

I am using C# to make a program which requires a password, and those passwords would be saved in a file. The problem is, I want the program to have access to the file, but not the user. How exactly can I do that? (With GUI, DOS or C#)
Hmmm.. the bottom-line answer here is that there is no way that you can prevent a determined and skilled user from accessing the data - the only thing you can do is make it difficult for him/her.
Here are some possible strategies you might consider for this: Each of these methods requires a different level of skill for the user to obtain the data. The first is almost certainly the hardest to crack.
Encrypt the file - use the .NET ProtectedData class
As in dasblinkenlight's answer, create the file under a different user account
Use Protected Storage
The main problem with this approach is that the password file is stored locally. No matter where you put it, if the legitimate program can read it, any user running with the same permissions can get it too. All you can do is to try to hide it, but that will only give you security though obscurity.
For normal desktop applications that store credentials locally, you should use a hash function on the password given, store that hash, and when authenticating users again, hash their input and compare hashes instead. Never encrypt user passwords, never store passwords as plain text.
In case some "curious" users peek at that file, all they have would be a hash that they have to crack to make any value of it. A determined user will always be able to do that, given enough time, but normally most people are scared at it.
You can create a crypto algorithm so other programs can't open it.

Beginner Encryption, "Master Password" Question

I'm writing a program that, using Rijndael, will encrypt and decrypt files/folders using a user chosen password. Currently, when the user wants to encrypt something, they have to enter a password, that password is used to encrypt and when the user is ready to, decrypt the file/folder.
However, I would like to have a "master password" that will allow the user to only enter the password once in a "preferences" portion of the program, and then the program will automatically use that password for all encryption/decryption. This way they don't have to put in a password every time they want to encrypt/decrypt.
Now, since programs like this are prone to many different kinds of attacks, how do I safely store the user's "master password" so someone couldn't get a hold of it? Storing it in the program in plain text is obviously not a good idea, so I could encrypt/decrypt the password with another password, chosen by me, and stored in the program.
However, again, if someone gets access to the password chosen by me to encrypt/decrypt the master password, then they could decrypt the master password and again, that wouldn't be good.
SO! How do programs safely do this?
Currently I'm saving the "master password" by encrypting it using my own, chosen password, and storing it in a User-scoped setting. If you think this isn't a good idea, please tell me why and what would you change about the process I currently have implemented?
Thank you!
Review this:
http://www.redkestrel.co.uk/Articles/StoringSecrets.html
It's a great article on your options.
That said, I think your use case is already pretty well natively covered by windows itself through EFS....
http://technet.microsoft.com/en-us/library/cc700811.aspx
Just wanted to add one thing:
It is fundamentally impossible to protect a "secret" from those who have physical access to the machine. This has been proven time and again even for hard drives that support native encryption schemes.
All you can do is make it somewhat difficult for those that have no idea what they are doing.
The fundamental problem is that something has to have access to the decryption key. Whether it's the BIOS of the machine, Firmware of the Harddrive, or even if it's stored in some folder hidden through DPAPI. Which means the only effective way is to force the user to supply the necessary credentials when it's time to encrypt / decrypt the files.
If those credentials are sufficiently short then it's possible to use brute force to get to them. Right now the recommendation is to use minimum key lengths of 128 bits or greater. Of course, if you are limited to use common letters then the number of bits to test goes down dramatically. And if you allow values such as those found in hacking dictionaries then the time to crack goes down further.
Another wrinkle are keyloggers. If one's installed (and they can be hidden from most users) then all an attacker has to do is wait for the user to type their decryption password in and forward that to an interested party.
Heck, for the truly paranoid, there are devices that can detect what you typed based solely on the sound your keyboard makes as you type. For others, RAM maintains state for a certain period of time even after the machine has been shut off...
So, what does all this mean? First, you have to ask them to provide the credentials on each encrypt / decrypt request. Second, they have to be sure that no keyloggers are installed. Third, the credentials can't be something easily remembered. Fourth, the computer cannot be in a physically accessible location. Fifth, even the keyboard has to be secured...
All of which adds up to a situation that says if its on a computer, someone else can get it.
Do you know why websites won't tell you your password when you lost it and they ask for a new one?
Because they don't know it. Yes, they don't know it. They hash it and hash it good so they can only check your input password's hash against the one in the database.
Why all that?
Because they cannot store it safely.
They cannot encrypt it safely.
This is a similar case.
The best way is not to use a master password.
When you encrypt a file, ask for a password and encrypt with the hash of the password.
When decrypting, do ask for a password and attempt to decrypt.
If it fails then it's wrong.
If it's okay then it's the right one.
You can add some (shorter) dummy data before the file's contents that you can use to check the key.
If you try to use that to store the master password, you will enter an infinite loop of security, which is not a good idea.
You'll encrypt the password, and then encrypt the key used and then encrypt the key used to encrypt the first key etc.
Edit: I am sorry about the discouraging nature of this answer but what you need to do is truly impossible.
Consider storing you master password in memory using the SecureString Class.
I'll be frank about this. Leave security to security experts. Security is not easy, and is very very hard to get right even for people who are supposedly experts in the area.
If you really have to store sensitive data that your users are expecting to be secure then asking in SO on how to do it is definitely NOT a good sign and not the way to go. You should seek professional guidance or consider using well tested implementations available in the market or in Windows itself.
Don't persist the user's password, take a hash and be sure to salt it. Use the hash to encrypt and decrypt the files. Beware if the user forgets their password you will not be able to recover it for them however you could still decrypt the files for them. This also means your app would be vulnerable to somebody hacking/patching it to get it to decrypt files without providing the password.
If the encryption method is standard, documented, obvious and/or well-known then to prevent hackers from just reading the hash and using it to decrypt the files themselves you could do this: use the stored hash along with some other info to generate a new hash that you then use to encrypt/decrypt the files and never persist. The other info could be made up of the size of the file, the created date, etc. Hackers could use this info but they would have to hack/reverse engineer your app before they know they need it. Technically it's security through obscurity since those keys are hidden in plain view.

Categories