I am trying to find a technique to encrypt and decrypt a file in a program without hard coding the password into the program and without asking the user for it.
It would be nice if I could also decrypt the file from another program that I also am writing.
So far I haven't had much luck finding a good technique that looks secure enough for my liking.
I'm writing this in c# but the language isn't important I just need someone to point me in the right direction towards an algorithm/technique.
This is a recurring problem with no safe real solution. If you want to be able to encrypt/decrypt something safely, you need a key. Your program needs to know that key. If the key is stored, somebody else can find it and use it to access your encrypted data.
Think of it like this: If your program should be able to access the encrypted data without hard coding the key into the program and without asking the key from the user, then why can't any other program do the same and acquire the encrypted data?
I think you need to define the problem further before you are ready to talk about how to code it.
Specifically, who should be able to decrypt the data? And what technique would you use to prevent others from doing it.
As it stands, the question may was well be "I'd like a lock on my door that doesn't require a key." The statement hasn't really defined the goal with enough clarity.
Put a web resource up with the password on it, and have the code request that web resource. Of course, to do this securely involves SSL and a webhost, but it fits your needs.
If your program features user accounts with their own passwords, you could do something like:
Set up a users table containing a column for storing an encrypted copy of the program-wide password.
Encrypt a copy of the program-wide password in each user's account using the user's password as the key.
When the user logs in, the system password is decrypted using their password and stored as a session-length cookie (SSL only) on their browser.
In this way, each user can get a copy of the system password silently in the background.
HOWEVER, this approach has some serious drawbacks.
First, the system password becomes no more secure than the WEAKEST user password. If Bob from Accounting sets his password to "password123", then that can be used to retrieve a copy of the system password.
Second, an attentive attacker will notice that cookie contains the system password, and then you're screwed.
You could obviate that by actually storing the decrypted password on a third machine accessed via SSL, then retrieve it for each transaction based on the user's session ID; but this would mean if the third server goes down for any reason, your entire system is down. It would also impose performance penalties, and your data server's security would depend on the password server's security.
And after all that convolution, in the end there's no really good solution; you just have to either prompt them for the password or store it on the server itself and lock the server down as tight as you can.
In cryptography the strength of the encryption scheme is the function of secrecy and strength of the key. This means that the key must be secret (i.e. not accessible to the attacker). Now, if there key is not in user's hand and not in the application code, where it is? And how secret it is?
So you need to re-think your task. Maybe good obfuscation of the key will drive away most not-very-skilled attackers. The simplest way to obfuscate the key is to use some text phrase of your program as a key. This makes operations with the key less obvious for an occasional lurker (professionals know different ways to find the encryption keys in the application).
Maybe the best answer could be a password generated by some means (like the size of a file or any other fixed value in the system). So you store in code the way to obtain the password rather than the password itself.
Related
I am making a social media type website, and I store user details such as emails, names and other personal details.
I will be encrypting the personal details using an Encrypt-then-MAC concept. When the user registers, a cryptographically secure string will be made to use as the private encryption key. When the user selects a password, the encryption key will be encrypted using the password.
The password will NOT be stored in the database, but will be the private key to decrypt the encryption key used to encrypt the personal details. The only person who knows the password is the user. My question is: how can I store the encryption key once decrypted?
I have thought of having a table with one column for IP and another column for the encryption key, but some people close the browser window without logging out, therefore there would not a possible way to remove the entry from the database when they have finished their session on the website.
Another way would be to store it in a cookie, but that could be intercepted when sent back to the server. I would like to know if there is a secure, nearly foolproof way to store the encryption key, client side or server side.
Thanks in advance.
EDIT:
In reply to TheGreatContini's answer -
The idea of a "zero-knowledge web application" (in your blog) is a good one, however, for zero-knowledge, even the key cannot be stored in the database, this complicates things a bit, as you would then have to use the user's password as the key. Using the password isn't as secure, as it is a bit harder to verify the password to prevent data which has been "decypted with the wrong key" from passing. There is the concept of Encrypt-then-MAC but that only verifies if the data is legit, and will assume that a hacker has messed with some data and data cannot be trusted, however, as you cannot actually verify the password (the hash would not be stored as it is "zero-knowledge"), so the password may just be wrong.
Not sure I have the answer, but a few considerations:
(1) Sessions need to be timed out. Perhaps you can do this by periodically running batch jobs that scan the database looking for sessions that have lacked activity. This requires storing in the db the date of the last action from the user.
(2) Generally keys are higher value than the content they protect because the keys have a longer lifetime than the individual data elements that the protect (because the data may change or additional data may be added). Rather than storing the key in the db, you can store the decrypted contents in the database for the length of the session. Of course, this is provided that you did (1).
Perhaps I am not adding much beyond what you already know, however may be worth considering a blog I wrote exactly about this topic. The low level details start in the section "A second line of defence for all the sensitive data." Prior to that it mainly motivates the concept. Glad to see somebody actually doing something like this.
In one of my applications, I am to store user credentials and tokens. As the credentials are used directly on third-party services, I cannot hash them and thus need to store them as-is.
As I am not an expert on encryption, I googled and found that AES 256-bit key size-is a good idea to encrypt such data.
I would like to know the opinion of the SO community on the same, before I make a final decision.
Thanks!
Edit: Thanks to all for discussion, I am moving ahead using AES256 as the encryption mechanism for now, which seems like a good choice.
if you ask user for credential every time, then why do you need to store them in db? just keep it in memory and pass to external system. you can even ask user once and keep their password in memory for the whole session. if, for some reason you have to store them in db, them of course encrypt it. as far as i know, current standard is AES256. but still somewhere you have to keep unencrypted key.
to sum up: if you want to authenticate users and then use their password only for the time of session then you don't have to store it in database. keep salted hash for authentication purpose and keep user provided password in session for external systems
btw. is your swap encrypted?
This question has been answered before but the key difference may be that I want to be able to decrypt the password later on and that this is for a deployed application where someone could get a handle on the code assemblies (as opposed to a website behind a firewall)
Basically, I want my application, when deployed, to accept a user password. I want to store that user password somewhere (encrypted) and then decrypt it later for use in an automation routine.
I'll make a few assumptions to simplify things. You can assume that the password in memory is secure (while it is in memory) and that a strong hasing algorithm (feel free to name the best options) is sufficient. Even so, what would prevent someone from reflecting my code and finding the hash key or technique i'm using to decrypt the password (would i even store the hashkey in the code?). I could obfuscate but my understanding is that it is still possible to read. Also, note that one way encryption is not sufficient here. I need to decrypt and use the password later on. Any ideas?
To directly answer the question, you're looking for asymmetric encryption (not hashing which is a one-way process) if you want to encrypt then decrypt your data. The OWASP Top 10 on Insecure Cryptographic Storage is a good jumping off point to learn more about this.
Now to indirectly answer your question, don't do this! Passwords should be stored with a strong cryptographic hash function including a random salt (you'll see this mentioned in the OWASP link as well). If you're trying to return password ciphertext to plain text text then authenticate to other services whilst impersonating someone else, you're missing the root cause of your problem. You've not provided much info on this but it seems the question you should be asking is how you (securely) go about identity impersonation and authentication to a downstream service.
I was wondering, whether there is a known safe way to store username and password safely for desktop application.
For example, the open source KeyPass
Let's say I get access to user local computer, grab all its KeyPass's configuration files, and step through KeyPass source code, is that I can reverse the user username and password after then?
No.
There is the concept of a one-way function. That is, if we have the relationship
y = f(x)
And we know y and f, it might still take a lot of time and effort to find x.
Example one-way functions (as far as we know they are, at least...) are the SHA algorithms.
KeePass keeps all the data symmetrically encrypted in a local store via AES so unless you get hold of the master password, your chances of decryption are pretty minuscule. The master password itself is stored as a SHA-256 hash (I assume salted) which means that so long as it has good entropy to begin with, your chances of getting hold of it are about the same as breaking the encryption.
So yes, this is a very safe way of storing credentials. Not foolproof, but about as good as you practically get.
You can store a password safely by using, say, a well known strong encryption algorithm, like AES.
HOWEVER, you cannot make the procedure that depends on the password 100% secure. Since the actual functionality of a desktop app is right inside the app's code, there will always be a way for the attacker to access that without even needing to know your password. Even using polymorphic self modifying code based on the encrypted key is still crackable (that is actually a protection that CuteFTP was using in the past, but still just xoring user's ftp passwords to store them 'safely').
Bearing that in mind, encryption does make it more difficult and at least, even if people crack the app, they may not be able to recover your original password.
Situation 1 - Connecting the server to the database:
Its always said that passwords should not be stored in plain text, however to connect to the mysql database requires the password, in plain text it seems... I'm guessing the best solution to this is to store it in an encrypted form, decrypt it in my app as needed and then erase it from memory (SecureZeroMemory in windows I guess so the compiler cant optimise it out).
Situation 2 - Users logging into the server from a remote computer:
As for users passwords my plan is to never actually store the original password at all.
Instead I will store a randomly generated "salt", for each user, prefix there password with it then hash it, which seems to be a relatively common way. However I don't have an SSL connection available at this point, so I'm guessing the plain text passwords could be intercepted, what's a good solution to this?
What are good algorithms (links to C/C++ implementations would be handy as well if you have them) for doing this, a look on the net comes up with 100's of them?
EDIT:
If I got SSL, would the following be secure (assuming a strong hash algorithm is used), or should a different method be used?
Client requests salt for a user name
Client prefixes password with salt, then hashes it before sending the hash to the server
Server compares hash recieved to the one on the server for that user name
Connecting the server to the database
Just storing the database password in the server - encrypted or not - is a bad idea. It is obvious storing it in plain text, of course. And if you just store it encrypted, the server still needs the key to decode it. It is usually not very hard to find the key in the server code. The best solution is to let the user starting the server enter the password and store it nowhere. Alternatively - and probably even better - you can store all sensitive information - for example database users, passwords, and so on - encrypted and let the user starting the server enter a master key to decrypt this information.
Connecting a user to the server
This is really a hard problem and easy to mess up. A quote from this great article article on the topic I absolutely recommend reading.
No, really. Use someone else’s password system. Don’t build your own.
A good solution might be using the Secure Remote Password Protocol.
You are correct that if you're not using SSL then the passwords can be intercepted.
It is common practice to never decrypt a user's password, so keep it stored hashed with a salt and when the user types in their password you will add the salt and hash it, comparing it with the stored, hashed password. This will allow you to never have the decrypted version of the password every.
You really should look into securing the connection so that the password is secure when the user types it in.
Update to answer edited question:
If you have the communication secured using SSL you can still use any number of extra measures of security you like including hashing the password. As added security it is a good idea to remember that the password you store should be stored hashed with a salt. That salt should be kept safe and never be accessible anywhere except by your application. This way when the user submits the password you just add the salt and hash and you compare that version with the stored version.
Situation 1 - Connecting the server to the database
There isn't an easy answer here. In order to connect, the server needs the password (or symmetric key, or private key or whatever). It must get it either from the disk or some external means (like an administrator typing it at startup). Adding some indirection, such as encrypting all the sensitive stuff under a master password, can add some convenience but otherwise doesn't change the situation.
Typically, it is fine to put the password or key in a file on a server. If you do this, make sure to set the permissions on the file so that only the users that need it have access to it. This is an excellent reason to have different processes on your system run as different users, and to set up separate roles/accounts and passwords for each.
Situation 2 - Users logging into the server from a remote computer
You are headed in the right direction here, I think. What it sounds like you're asking for is a secure authentication protocol. You want one that provides mutual authentication and prevents a man-in-the-middle attack by failing if such an attack is attempted. There are many to choose from of course.
It is also worth mulling whether your authentication should operate based on "something you know" (passwords) or "something you have" (public/private keys). Assuming based on your question that what we're looking for is passwords, two that I like are SRP and Kerberos.
SRP was mentioned earlier, and that doesn't get nearly the attention it deserves. SRP has the advantage that it doesn't require the server to know the password, or key, or anything that an attacker could use to gain access. If you broke into a correctly configured server using SRP and stole all the data, you'd still need to do something like a dictionary attack on each key individually before you had anything you could use to impersonate a user.
I also like Kerberos because it is supported by tons of software (I know Postgres supports it, I've only found mentions of mysql not supporting any good authentication technology) and has a system of 'tickets' that provides a single sign on capability. Kerberos needs some other technology to help strengthen its initial authentication exchange and SRP would be great for that but I'm not sure they've done that yet. Something about it making the KDC (key server) stateful I think.
Kerberos' weakness is that you have to be more wary of the server storing the keys. While it doesn't store the passwords in plaintext, it does store the keys, which are essentially hashed versions of the passwords. And while the client doesn't exactly send either the password or the key straight over when authenticating (this is a Real auth protocol after all), it does use the hashed password as the key, and so anyone else who knows the algorithm and knows the key could do the same. We say that the server stores a "password equivalent". As a result, all the manuals tell administrators to put the kerberos services on their own separate, locked-down boxes to minimize the chance of compromising their contents.
The nice thing is, once you settle on a strong authentication exchange, other good things typically fall out of it for free. You end up with both parties sharing a mutual 'secret' that can be used once for the duration of the session, never sent over the wire, and can't be known by a third party. Want encryption? There's the key, all ready to go. This is exactly how SRP-secured SSL is defined in RFC 5054.
Not sure if this is what you are asking for.
But a simple PHP example using the built in sha1 function:
// Check the hashed password from the database
if (sha1($salt.$password) == $providedPassword)
{
// User is authenticated
return TRUE;
}
else
{
// User is not authenticated
return FALSE;
}
One thing you could do is also hash the password with javascript before it is sent over the wire. The question is how is the salt string shared between client and server? One possibility is to use a session variable. And then use the session variable to unhash the password afterwards on the server. This would mean that the man in the middle would need to know one other piece of info to make sense of the password. Not as secure as SSL, but perhaps an extra layer of defense against casual network sniffers.
I could also imagine a hashing scheme linked to some sort of captcha system used to salt the password on the local client before sending over the wire. The client would be providing the text for the salt string by completing the captcha. You could look it up on your end.
The main concern is the man in the middle not understanding the plain text password.
SSL should be used, but the above techniques might be useful where SSL is not possible.
Newer MySQL uses hashed password over the wire, so you don't have to worry about man-in-the-middle.
If you worry about the password stored in your configuration file, you can encrypt the configuration file with a password. However, the problem is that you have to enter a password to start your application.
I wrote a similar application over 15 years ago. Back then, PGP was my choice. I am not even sure it's still around.