I am looking for a way to securely encrypt any credentials used in my source code, e.g. Credentials used to connect to a third party API
I have a question regarding encrypting a string or a file...
Take the following GitHub project: https://github.com/2Toad/Rijndael256/blob/master/README.md
I understand the encryption / decryption method but the part that confuses me is using a password that is hard coded to encrypt, surely if anyone gained access to your source code they could decrypt it anyway.
How would you go about making sure the password used to encrypt is also secure?
Of course a password is generally retrieved from a user. A computer doesn't have any use for a password; instead it can simply remember a key directly; humans are however pretty bad at remembering 128 bits (32 hex characters) or more .
There are many ways for a computer to retrieve a key; there is key agreement, there are key stores, key wrapping, key derivation, storage in hardware etc. etc. The entire handling of keys is the subject of books and is called key management.
Sometimes it does make sense to have keys in code / runtime memory. If the runtime is less accessible than the process itself to the user then it can give a small amount of protection. The same goes for configuration files, although both are generally readable by the user.
Related
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.
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/
I have an application that requires a secure way to store its configuration. There are users that can change the configuration. I need some sort of signature scheme where I can verify that the config file has not changed with out a valid user. I had thought about using RSA, where the private key is encrypted with the users password, and the public key is used to sign the config. However there is nothing to prevent someone from changing the user file and adding their own public key, thus circumventing my security. Any ideas?
You could just keep the file encrypted, and only allow editing from within your application. This would prevent users from editing the configuration from any tool other than yours, which could do the authentication to verify that the user is a "valid user".
Of all the methods listed, key management is the true weakness on a client machine. The key is required to decrypt. Using another key to encrypt that key is no stronger. Obfuscation is a start.
What I use is a separate assembly that contains our encryption code. The key is then stored via a technique called Steganography. I encode the key in the logo of application. This key is then encrypted using a known value of the software. In one case, it may be the checksum of a specific assembly. Thus anyone that makes any change to that file will break the system. This is by no means any more secure, but its all about hiding details. and raising the level of difficulty from casual to determined. From there, I then run the assembly through an obfuscator and string encryptor. This breaks Reflector with a crash when attempting to view the assembly and thus makes its more difficult to learn what is going on.
The issue with these strategies, is that if you attach an debugger then you get the data in the clear since you may store the values in a string after the encryption/decryption process. To combat this, but not eliminate, I use the System.Security.SecureString class and do not keep data in the clear.
The goal is to break reflector, stop simple attacks of just using the .NET Framework to decrypt the data, stop dictionary attacks by employing a random salt, allow easy string handling by URLEncoding the encrypted buffer, proper use of an Initialization Vector.
There is no way to fully secure a stand-alone Client application. The only way would be to do a checksum on the file and validate it to a/the server. The method of signing the file is less important than how you verify what is in fact signed.
A start to securing the client application is with Obfuscation. Thereafter your encryption is next in line.
For the actual signature, even a SHA series of hashes should do the job for you. An example using SHA512 is as follows:
FileStream fs = new FileStream(#"<Path>", FileMode.Open);
using (SHA512Managed sha512 = new SHA512Managed ())
{
byte[] hash = sha512.ComputeHash(fs);
string formatted = string.Empty;
foreach (byte b in hash)
{
formatted += b.ToString("X2");
}
}
These contradicts:
"I can verify that the config file has not changed with out a valid user"
"there is nothing to prevent someone from changing the user file"
You should just find a way to protect your "user file" first. By encrypting it with a key nobody can edits (except determined crackers) or otherwise. And then your RSA scheme will work.
Do note that, however, there is NO way to protect an application that runs entirely on the client from a determined cracker.
For most applications, though, you DON'T need perfect security. Maybe you should think about how much security is actually "enough" for your application first.
If you, however, needed perfect security, then you might need to add a server-side component OR add human-intervention into the process such as having an administrator controls the user file.
Encrypt the "user file" with the admin's passwords. And then whenever someone wants to change the user file, the administrator's consent is then needed.
I think what I will do is keep a private key(A) in the office. I will ship the app with an public private pair(B), signed with the private(A) that only I know. I will use the public private pair(B) I ship to sign everything on the config files. Thus there will be a verifiable set of RSA keys(B), that can't be change, because the private key(A) used to verify them is in the office, and the public key(A) is hard coded.
-new- I found another use. Theres some data submitted to me via HTTPS POST data and i'd like to store it in my db (Such as mother maiden name that customer support may need to read later instead of spelling incorrectly checking if the hash matches). I only need that section encrypted and not the entire DB and using a separate DB may not be worth it. Question: How might i use a premade public key to encrypt a symmetrical key + text using .NET? (the rest is for context, i just want an answer plz)
-edit- I have done symmetrical encryption before. How do i encrypt the symmetrical key with the public key? a nice bonus is if you can tell me how to generate the public/private key in a separate app so i can create them and store only the public key in my a app.
I am considering having cheaper less stressed site grab backups automatically from a more busy site. Transferring the data is not a problem since i can use https but i dont completely trust that my cheaper site is as secure or wont have people looking around at my files. I mostly want to protect email address and PM if i have them on the site.
So i am wondering how i can have a public or private key in my app which encrypts the data so only i (or whoever i give the key(s) too) can decrypt the backup. How do i do this in .NET. logging in and transferring i can write in a few minutes but how do i encrypt the stream as i write it?
-edit- it just hit me. The user/pass wouldnt be a secret. So i would have to encrypt my backups before the transfer. How do i encrypt a symmetric key with a public key using .NET. Then decrypt it on my side. Encryption the file with a symmetric key i know how to do.
First off: defense in depth. If you have concerns about the security of the backup site secure the backup site. Mitigating attacks through encryption is a good idea, but it should not be the only idea.
Second, why are you thinking about using public/private key crypto? Normally you'd only use public/private key crypto when attempting to communicate a message from a sender to a recipient. What value does public key crypto add to your scenario?
To encrypt the stream in C#, this page might help:
http://support.microsoft.com/kb/307010
UPDATE:
Absolutely, YES, you have to encrypt the files before they get to the site which you are assuming is compromised.
You believe that the site might be insecure. The assumption you should be making is that the site is your enemy and is trying to hurt you. Start thinking like your attacker thinks. What would your enemy do? If I were your enemy and you handed me a bunch of files to store on your behalf, I might:
delete your files
corrupt your files
read your files
log every byte that comes in or goes out for analysis later
replace your files with hostile files -- in particular, all executable code, scripts, and so on, that you store on this site, you should assume are full of viruses targetted specifically at attacking you
do stuff to get you in trouble -- forge messages that look like they come from you, and so on
Assume that the insecure backup site operators are trying to do all of those things to you. Crypto is a mitigation for some of those attacks, but not all of them.
No offense, but it is very clear that you do not know enough about crypto to solve this problem with any reasonable chance of getting it secure against real attackers. That's nothing to be ashamed of; I don't have this knowledge either. Rather, I have sufficient knowledge to know that this problem is beyond me. There's nothing wrong with trying to learn more about crypto; I strongly encourage that. But if you have a real threat here, and you're trying to mitigate it with professional-strength crypto tools, do not roll your own solution. Go hire an expert consultant in this field who can advise you on what the right thing to do is given the realistic threats that you face.
You encrypt with a symmetric key, then encrypt the symmetric key with a public key, then drop the symmetric key. Only the owner of the corresponding private key (you) can later decrypt the symmetric key, and hence the document. There is no secret stored in the app. The good news is that ther just about a tonne of out of the box products (pgp) and protocols (s-mime) to solve this.
You can use an symmetric key algorithm (AES, DES, Triple-DES) to perform an encryption on your code, and store it a hex in your database (in a nvarchar field). Since, you done need to transfer that in encrypted form to someone else, you wont need to use any assymetric algorithm (like RSA, ElGamal etc.) If you something like RSA, you would also have to consider signing with data using something like PGP.
But, irrespective of which algorithm you use, you would need to make sure your keys are as secure as possible, i.e. your symmetric key for AES, and your private key for RSA etc.
This article, provides an tutorial on how to perform Symmetric encryption with/without Salt.
http://www.obviex.com/samples/Encryption.aspx
I'm trying to determine the best course of action to implement a simple "licensing" system with a partner of mine. The concept is:
Generate an encrypted value based upon several internal hardware components. Have the customer send this value to us which we will implement into our key generator. Once we have that, we add any other restrictions on the license (user, expires, etc.). From there we generate a file which we send to the customer they can add to their installation and voila, happy people about.
I have the first part all done. My next part is trying to figure out which encryption methodology I would need to use. I already know Symmetric Encryption is pretty much the only route I can take. Most of the information I have found involves .NET already creating a key from its own internal methods.
That's a bit of background, my question is: "Which encryption method could I use which would allow me to encrypt the restrictions based upon the "id" I was given from the customer's computer?" I'm writing this in C# by the way.
You say you know you need symmetric encryption but you would be wrong. With symmetric encryption the code checking the license has to have access to the secret, which means if your code is reverse engineered someone can not only figure out where to remove the checks, they can generate and sell license keys that are indistinguishable from the ones you make.
Use asymmetric encryption, or a secure hash. And don't try to use the customer-specific hardware information as the key, instead prepend or append it to the other data. You're essentially creating an access control/rights/privileges list file coupled with a message authentication code to verify its source (you).
I recently did something very similar to this. I used AES to generate a value based on a private key using an internal customer id or order number as the IV used to encrypt the value.
Instead of an order number you can use some form of checksum from your first step so it's not something that's stored as the IV. That way if the file is hosed or if they transfer the software to a new computer - either way will invalidate the file.
Something you might be careful of though is how closely you tie the installation/license to the hardware. You don't want to punish a legitimate user simply because they upgraded their motherboard.