C#: Best practice for obfuscating password in text file? - c#

Firefox has to store passwords. That is totally unsafe, but it has to do it, that's all.
My C# app has the same requirement (it is a kind of browser).
Rather than storing passwords in plaintext, Firefox obfuscates them a bit.
What is the best practice for this kind of obfuscation?
For instance, here is Firefox's strategy, if I understand well:
Create a salt for the app's user
For each password, use the salt in a symmetric transformation when storing/retrieving
Store the passwords file in a directory named after the salt.
Is my understanding correct?
Is there any better strategy, or even a C# library for this?
Similar questions for other programming languages have unsatisfying answers, they don't not go as far as Firefox, just suggesting rot13 or base64, which makes it easy for automated malware to identify obfuscated passwords in unknown software. (just searching for the base64 value of common passwords)
Once again: it will not resist to any attacker, I know. But if Firefox cares I should too.

You should use the ProtectedData class to encrypt the passwords.
You can specify DataProtectionScope.CurrentUser to encrypt data using the current user's Windows login password, so that no other user can decrypt it (this also works if the user has no password)

It would probably be easiest to use an encryption rather than obfuscating. Obfuscating code generally makes it harder for someone to identify what is what in code if they viewed the source. If you don't encrypt the information however, people can still figure it out.
My advice would be is to use AES-256 or Tripple DES-128 Encryption.
Easily, you could have the passwords stored in a text file and then encrypted. Only then through your browsers can the file be decrypted.

Related

Best approach to hide secret key(password) in C# code when application will be used on multiple machines?

To access a API, I have to have a secret key. How would you approach storing that secret key, if this is going to be used on multiple machines?
I read this answer, and if I understand it correctly, besides some obfuscation, there's no point doing anything more?
It's not easy because IL code is readable. And the IL code easily gain from a binary like DLL or EXE using IL Disassembler: ildasm.exe.
The solution that #miniHessel said, downloading the code from a server using SSL is also not a safety solution, because a client on his/her own machine can track the SSL communication doing a "MITM attack" with a proxy like Fiddler or any other app. We have a lot.
We can only make things more difficult:
One solution is to encrypt the secret and keep the encrypted secret in the code. (before you use it you can decrypt it)
Better if you cut the encrypted secret to multiple parts and keep it different place in the code. And merge them before you decrypt it.
Give the variables and functions innocent name, so noone can figure out what the content is.
A good encryption/decryption solution is here: Encrypting & Decrypting a String in C#

C# - Storing user password for comparison

I am storing user logon encrypted passwords in a database (SQL Server). Because of an API restriction, the passwords need to be encrypted on the C# end of things, so I can't use the database's built-in encryption. what is the fastest/easiest way to encrypt these passwords so I can compare them to what the user would have typed in to a third-party service later?
I am new to C# and I understand that passwords should never be in plain text so that's why I want to make sure I have the highest security. I have tried using the RSA.EncryptValue() function but I'm pretty lost as to how to use it correctly.
Any help is appreciated - thanks in advance.
-Jimmy
You don't want to encrypt and store passwords. You want to generate a hash and store that. Then, when a user is logging in, you regenerate the hash and compare it to the one stored in the database.
The answers to this question provide examples of how one might hash a password in c# (one answer includes information on doing a "salted" hash).
Firstly dont encrypt; hash.
Secondly dont encrypt; hash.
A password should never be recoverable.
I'd advise reading...
http://www.troyhunt.com/2010/05/owasp-top-10-for-net-developers-part-1.html
front to back.
You should salt your passwords and hash using a decent hashing algorithm; take SHA512 for the low end, or if your serious about protecting that data look at something more along the lines of BCrypt http://code.google.com/p/bcryptnet/
The point in hashing rather than encrypting isn't to secure your site against brute force attacks, but more importantly, is to secure your users against data loss.
i.e.
http://www.bbc.co.uk/news/technology-11998648 - Gawker
https://www.google.co.uk/search?sourceid=chrome&ie=UTF-8&q=sony+hacked
People put allot of trust in the hands of web developers taking care of their, often pathetic, passwords. Taking good care of them can make a hell of a lot of difference.
With BCrypt you set a workfactor to the salting; I would also add a database salt (see the troy hunt membership provider article on how MSFT does it) to increase the original password value.
Example from the BCrypt site (BCrypt.net is also a NUGET package)
// Pass a logRounds parameter to GenerateSalt to explicitly specify the
// amount of resources required to check the password. The work factor
// increases exponentially, so each increment is twice as much work. If
// omitted, a default of 10 is used.
string hashed = BCrypt.HashPassword(password);
// Check the password.
bool matches = BCrypt.CheckPassword(candidate, hashed);
Hope thats been of use.
You can of course use the built in forms authentication encryption system to encrypt/decrypt your data. Though it's somewhere between daft and dangerous to encrypt passwords.
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.encrypt.aspx
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.decrypt.aspx
You'd also need to add a machineKey tag to your web config, microsoft provides a generator for this; http://aspnetresources.com/tools/machineKey The tool creates a 256-bit decryption key and a 512-bit validation key, with Rijndael as the data validation algorithm.
And if you DO NEED (as in you'll be shot if you don't) to start throwing plaintext passwords around, for all that is holy, check the service is restricting by IP (IPSec) and please, dear god, use SSL.
Like Steve Wellens mentioned generate a hash.
Hope this gives some insight on the different ones available

Could I hide the encryption key of a c# exe securely (in a way that can't be decompiled in any known way), as in C/C++?

I love c# for programming applications (I consider myself intermediate with c#, and a bit less with C/C++, but am only learning, nothing real yet in the arena), and I used to like it until i discovered "anyone" who understand MSIL (not an easy task to learn neither) could decompile my code. I don’t really care about someone decompiling my code, but my utter concern is the security for my eventual program users. I know obfuscators exist, and I even know of one or two that are really good, I hear (even if they only delay a decompiling).
For example, if I want to decrypt something using c#, some where in the code the key should be, making it a danger for anyone who use my program (someone who know someone who encrypted the file using my program could decrypt it by researching on my MSIL code, finding my key). Then, the developing of massive applications that encrypt/decrypt stuff (or OpenSSL) is insane with c#, I think, for this reason.
I mean, most users won’t know what language was used to make that exe, but a bunch of people are able to program n c#, and an elite of this people can read MSIL, and a minority of this elite would like to hack what ever is possible to hack. Of those people who like to hack, some of them can do it with perverse intentions (in a value-less world where we live that shouldn’t surprise anyone).
So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key. I know avoiding hacking is probably impossible, but it looks like c# is a very unsecure way.
Does it happen with Java? (Java has the same “interpreting” and “decompile” structure as C#); I mean, the fact that the key is visible in Java (with some educated eye) some where in the building file? Or does Java use some C/C++ based API that makes it harder (way harder) to decompile the file where the key is and so making it hard to get the key?
Is my only option to write my program with c/c++? Because if so, my only option is C++Builder, since its a hell to even try to watch (and less to learn) MFC/OWL code; I mean: I cant hardly think of someone who could like MFC/OWL programming. In fact, I suppose Assembly could be of more interest in the today programming world.
So, here I am, wanting to find someone who could explain me better a way to store securely crypto keys for encrypting/decrypting or to use OpenSSL with c#. Or even with Java. I would like to confirm that C/C++ is the only way of really using these features with some security for decompiling reasons (as other compiled programming languages, i.e. Delphi).
If anyone knows a site where I can find precise information about the subtle reasoning I suppose I have done (specially one that shows am wrong in my analysis), please tell me. If any one can confirm my analysis, please confirm. If anyone find any hole in my analysis, again, please tell me, and where to find more information that rule me to get a better understanding of all this.
Am sorry for making this philosophical computer programming question that long.
Thank you,
McNaddy
Could I hide the encryption key of a c# exe securely (in a way that can't be decompiled in any known way), as in C/C++?
No. You can't do that in any language.
The .NET security system is designed to protect benign users from hostile code. You are trying to protect benign code from hostile users. You simply cannot do that, so don't even try. If you have a secret, do not share it with anyone.
The purpose of crypto is to leverage the secrecy of some private key into the secrecy of a text. If that is not the security problem you face, crypto is the wrong tool. Explain the security problem you actually have and someone here can help you solve it.
So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key.
You don't need to store a secret key in the program just to download a file safely.
If you want to ensure that the file you downloaded is authentic and hasn't been modified in transit, you use a digital signature. The private key used to make the signature doesn't have to be (and shouldn't be) distributed with the program; all the program needs is the corresponding public key, which you don't have to hide.
If you want to prevent eavesdroppers from reading the file as it's downloaded, then you need to encrypt it, but that can be done with a temporary session key generated randomly for each download; it doesn't have to be stored anywhere. If you use HTTPS for your download, it'll do this for you.
The choice you've mentioned (embed key into executable) is bad irrespective of language you choose - it is not too hard to extract data from C/C++ and slightly easier for C#/Java.
As Jordão said - you need to figure out your story of distributing key outside the binaries. You also need to figure out what you actually trying to protect and understand possible exploits. Just using encryption of some sort in an application does not make it more secure.
You should not store cryptographic keys inside assemblies; they should normally be provided from outside, e.g. from a key-store, or derived from a secret known to a user.
You can also generate a key from a password(this means the key is no more stronger than the password though). So each time the user runs the program, they are prompted for a password, and that password is then used to generate a key. Depending on your requirements you could employ this in a variety of ways.
When the user needs to access the encrypted data, the password can be provided again and this generates the key for use during that session. Once the program is closed the key is discarded(there are techniques/APIs in C# to help ensure that sensitive data is only present in memory as short a time as possible).
For example, this is essentially what many password storing programs like Keepass or Roboform do. The user can upload and download the encrypted data to and from servers. No keys are ever stores, and instead generated on demand as the user supplies their password for that session.
With a service like Dropbox, when you register with their site, they generate the private key on their server and keep a copy there. So the user's machine and client software never store the key, but the server has a copy stored. Dropbox does this so that they can decrypt user data for many purposes, such as compression, de-duplication, compliance with law enforcement, etc.

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.

Encryption/Decryption in .NET

I'm looking for a secure way to encrypt and decrypt a string in a Visual Studio Project (in C#). I found that there is native DES classes, but it's not secure enough. Do you have any suggestions?
UPDATE :
OK then, the question is : What's the most secure way to encrypt/decrypt a string without too much hassle (aka having to install external tools, etc. An external library is fine though). And where to put the secret "key" (is compiling the value inside the code secure enough?).
Update #2
If I'm using something like this code to save encrypted string in a config file :
using System.Security.Cryptography;
using System.Security;
byte[] encrypted = ProtectedData.Protect(StrToByteArray("my secret text"), null, DataProtectionScope.LocalMachine);
byte[] derypted = ProtectedData.Unprotect(encrypted , null, DataProtectionScope.LocalMachine);
Is this secure enough? I guess that with the "LocalMachine" parameter instead of "User" parameter, somebody could just write an application in .net, put it on the machine and execute it to decrypt the encrypted string. So if I want it more secure, I'll have to have a config file different for each user? Am I understanding that correctly?
To answer your second question, no, storing the encryption key in the executable, even obfuscated, is not secure at all. It'll keep casual prying eyes out, but not those with an hour to devote to walking through your decompiled source.
Think hard about where to store your encryption key - it looks like that'll be your weak point. And yes, this is a hard problem to solve. The most secure way to store encryption keys is not to - require the user to type a password, or require external hardware, like a key fob.
If you're encrypting contents intended to be read only on a single machine or by a single domain user, consider the Data Protection API (DPAPI). It takes the encryption key out of your hands - it uses the user's Windows credentials as the key.
I've got a little more detail in another answer here: Persistent storage of encrypted data using .Net
Regarding your second edit (is DataProtectionScope.LocalMachine good enough?); this MSDN blog entry summarizes it well:
Setting a scope of
DataProtectionScope.CurrentUser
encrypts the data so that only the
currently logged on user can decrypt
it. Switching to
DataProtectionScope.LocalMachine
allows any process running on the
current machine to decrypt the data.
This could be useful in a server
scenario, where there are no untrusted
logins to the machine, but for a
general purpose workstation using
LocalMachine encryption is almost
equivalent to using no encryption at
all (since anybody logged in can get
at the data).
It also has AES.
If I read your update correctly, you basically want to conceal some string constant from a sysadmin snooping around your assembly.
There is no way to make it impossible that someone with too much time extracts your string constant eventually. But you can annoy them, hoping that they give up trying before they unmask your secret.
One way to achieve that are Obfuscation Tools. These obfuscate your compiled assembly as much as possible, making it much harder to follow program flow when decompiling it with Reflector. Try it. If your string constant is still not hidden enough, you can additionally invent your own scheme to make it harder to find.
If you need more security, the almost only option is to not give the relevant parts of the code to the user. Create a web service that contains the secret parts of your application and secure the connection with SSL/TLS.
Try using AesManaged.
That depends on your definition of secure enough. You may use triple DES. .Net also has native Rijandel class. Is it secure enough? http://www.obviex.com/samples/Encryption.aspx
Using a well tested and accepted library is a good idea too...
http://www.bouncycastle.org/csharp/

Categories