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.
Related
A friend of mine and me are having a discussion about whether we should pre-hash the passwords of the users of our webapp before sending it to our servers.
I know that there are multiple questions that already handle this topic but they're all about transferring it securely to the server. Our idea is not about the transfer security (we use SSL) we want to hash clientside to prevent that the "real" passwords reach our server.
The idea came as Twitter announced their bug that caused passwords to be printed to a logfile in cleartext.
We are currently discussing about whether this concept makes sense or not and how it affects the security of a password (in terms of Bruteforce) if we would hash it with SHA512.
TL;DR:
We want to hash passwords clientside to prevent our servers from getting them in cleartext (we use SSL for transfer).
Does this make any sense?
What algorithm would be best to use for hashing?
The hashed passwords would then serverside be hashed again with bCrypt.
It 100% makes sense: in fact, the concept has been proposed by a number of people, but the difficulty is in implementing correctly. There are a number of pitfalls if you do it wrong, the most direct one is being vulnerable to "pass-the-hash" as #swa66 describes. To prevent that, you need to hash on both sides. The client-side hash should be slow (bcrypt, scrypt, argon2, or pbkdf2) whereas the server side hash should be fast (sha256).
EDIT: A number of people have down-voted this without understanding how this works, so I now include the basic details here (previously I only linked to how this works). The idea is to apply a slow hash such as bcrypt on the client side, and then a fast hash such as SHA256 on the server side. The fast hash is required to prevent pass-the-hash attacks. In the event of the database leak, an attacker either hash to invert the fast hash (impossible -- violates the one-way property of a cryptographic hash function), or brute force the preimage to the fast hash (impossible -- the size is the length of the output from the slow hash, for example 184-bits for bcrypt), or brute force the combination of the slow hash and the fast hash -- which puts the attacker back at the same position as if the entire computation had happened server side. So we have not reduced the security of password attacks in the event of a database leak by shifting the heavy computation to the client side.
I've surveyed a number of proposals like this in Method to protect passwords in databases for web applications. Additionally, I analyse the pros and cons and identify weaknesses that have not been identified before (account enumeration), and propose a unique way of doing this securely. The research is built off a number of sources, including:
Secure authentication: partial client-side key stretching… please review/criticize my idea
How to securely hash passwords? -- see section on Client Side Hashing
Client side password hashing
Discussion from various authors on Hacker News -- see comments from oleganza, mschuster91, crusso, etc...
You cite the Twitter example, and GitHub did similarly. When I wrote the paper above, the most prominent example for preventing a server from seeing the clear text passwords was Heartbleed, which I comment on in the paper (bottom of Section 1.3).
There has been subsequent follow up research by others identifying similar ideas -- Example: Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server. No one person deserves all the credit, but the main takeaway is yes it is a good idea if you do it securely, but you really need to understand the risks (it is easy to do insecurely if you have not read the research).
While #swa66 outlined how to manage passwords securely, let me note that there is a valid scenario where you can consider client-side password hashing, so don't just blindly follow "best practice", try and understand it first.
Let's say I have a standard web application that stores data from users. In my threat model, I don't even want my own users to have to trust me, or in other words, I want my users' data to be secure even in case of a full compromise of my servers. Therefore, I let them choose a password, and encrypt their data on the client, before sending it to the application. They can retrieve their encrypted data with their user id. Well, that doesn't sound very secure, I can just download anybody's encrypted data and run offline attacks against it. So let's have them access their encrypted data with their password (I don't want them to have to remember two different passwords). But that's not good, because I have their password then to decrypt their data. So one simple solution is to encrypt their data with their password, and send it to the server along with their hashed password, which as it's correctly noted in the answer is the new password as far as the server is concerned (so the server should store it hashed once again and so on). However, the server has no way to decrypt client data, because it never has the original password, yet only the valid person can download even their encrypted stuff, and they only have to remember one password. (Note that this is a very much simplified model, in reality, much more is needed, like for example a proper key derivation function, not just plain hashes, but that's another, much longer story.)
Don't get me wrong, I'm not saying you should normally be hashing passwords on the client - no, the other answer is the correct one in that regard. I just wanted to show that there is at least one use-case where client-side password hashing is a valid option. See well-known password managers, some work similarly.
NO!
Rule one in cryptography: do not invent it yourself, you'll make horrible mistakes.
It's not against you personally, by far not: even top notch experts make mistakes when designing with great care new systems. That's why they peer-review each-other's work multiple times before anything become a standard. Many proposals for such standards by such experts get redrawn due to problems detected during such a peer-review. So why can't the rest of us mere mortals design: there's nobody good enough to do the peer-review as the experts will not touch it.
Hashing the password client side
Hashing client side is really bad as the hash becomes the password, and now you store it on the server in the clear.
How to do passwords
Only store hashed passwords (implied: send the password to the server, just do not store it)
use a salt and store it with the password (unencrypted). The salt is essentially a random string that you concatenate to the pasword before you hash it (to store it , and to verify it)
Use a SLOW hash. Using a fast hash is a common and fatal mistake, even when using salts. Most hash functions people know like SHA-256, SHA-3 etc. are fast hashes and completely unsuitable for hashing short, predictable items like passwords as they can be reversed in a surprising short time.
How slow: as slow as you can afford. Examples of slow hashes:
bcrypt, PBKDF-2 (which is essentially a high number of rounds of a
fast hash to make it slow)
There are -depending on your programming environment- pre-made routines, use them!
Ref:
https://crypto.stackexchange.com/questions/24/what-makes-a-hash-function-good-for-password-hashing
https://crypto.stackexchange.com/questions/59797/authorities-on-password-hashing-best-practice
I have just pressed 'forgot password' on hosting24.com, only to have my password emailed to me in plain text (see image below). I contacted their technical support to question this and they have told me:
We are using Salt encryption on our website, passwords are not stored
in plain text. Please let us know if you have any concerns regarding
the security of your data.
The way I understand it, is that once a password is 'salted' it cannot be reversed back to plain text. I am also very concerned, considering their partner company 000webhosting was victim of a massive hacking incident recently, which exposed that their security was sub-par.
Thanks.
EDIT:
After a few heated emails I finally got this response:
Our passwords are encrypted with a secure encryption method in the
database. Although we do have a decryption method in place (that is
used to prevent fraud), all this is going to change as we are
re-designing the project and updating the code to adhere to new age
standards. We are sorry to have let you down on this one.
Please contact us with any additional questions. Happy holidays!
'New age'. Amazing.
EDIT:
I sent the website this link to prove a point, so I anticipate a load of down votes from their tech support.
Salted hashed passwords are not directly reversible—that's the point of hashing. However one can always try to recover them through brute force, trying all possible/likely passwords to see if the hash matches.
How expensive that is to do depends on the strength of the hash used, but you would never build a system that stores and decrypts passwords that way. If they said they were storing only salted hashes, and still were able to send you the password you originally set yourself, they're clearly lying.
They don't mention hashing though:
We are using Salt encryption on our website, passwords are not stored in plain text.
“Salt encryption” isn't a thing, but let's be as generous here as we can.
It is possible they mean they're using reversible encryption with some randomised element (variable IV, or extra data in the encrypted message) which would ensure two passwords don't get matching encrypted versions (ie the same purpose as the ‘salt’ in a hashing operation).
It's also conceivable that there could be some valid reason why they need reversible passwords, for example if they need to use the passwords to authenticate to another separate system. It's possible to build reasonable systems with reversible passwords, but compared to Good Old Bcrypt it's a whole lot more effort to manage this way (eg keys on the application server; wide-ranging internal policies to manage that; HSMs; and watertight code auditing).
Let's say we accept that this is what they've done and they've implemented it solidly (which is highly doubtful—much more likely they've got plaintext passwords or a hacked-up and vulnerable AES). Even then, they've then blown it by sending you the reversed password in a mail over the unencrypted public SMTP infrastructure.
There are things you can do to mitigate the untrustworthiness of the mail channel, such as sending a single-use token or temporary password that requires a new password to be set afterwards. But there is never a good reason to send an existing password, that will continue to work on the target site and which you might have used to secure other services. User-set passwords should never touch SMTP.
No, they can't without astronomical computing power. I'd bet large sums of money that they have a second database of plaintext passwords.
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?
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.
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.