Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
For the secure communication between Alice and Bob if they have pre-shared password. Why that password shouldn't be used as session key for the communication ?
Because in this communication session you'll probably transmit significant amount of data. This data could be used to discover the password.
If you use session key, it's only valid for the period of one session, so even if it gets compromised, password stays secure. Additionally, discovering this session key will be less likely because it will change periodically, so the amount of data available to the attacker will be limited.
Imagine that an attacker discovers the data sent from the user to the server. If you are using the password as a session key, then the attacker has full access to your account.
If you use a random key, the attacker will only have access to your account during the time that session key is valid (some minutes, hours or so).
It is possible that the password is also used in another websites (your mail for example), so the attacker can gain access to even more accounts.
This example is however not realistic, because session keys are usually associated with user's IP and other relevant information. That means that the attacker would have to fake it's own IP also to use your session key.
This is also why there are some sites that don't let you change your password without entering the old one. That's because if an attacker hijacks your session, he won't be able to hijack your account. Every important change in your account (email, password, etc) should be protected with a "enter your password" field so that session hijacking doesn't become a critical security problem (it is a security problem, but just temporal and not critical).
Passwords are typically too short, they are far from being random so their entropy may be attacked, and they stay the same, so acquired knowledge may be used in a future session. What you end up with is a kind of Vigenère-cipher known to be breakable since 1850. You have to decide yourself, whether this is "good enough".
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am working on a project that has to have authentication (username and password)
It also connects to a database, so I figured I would store the username and password there. However, it seems like not such a good idea to have passwords as just a text field in a table sitting on the database.
I'm using C# and connecting to a 2008 express server. Can anyone suggest (with as many examples as possible) what the best way to store this type of data would be?
P.S I am open to the idea that this info not be stored in the database if a good reason can be provided
You are correct that storing the password in a plain-text field is a horrible idea. However, as far as location goes, for most of the cases you're going to encounter (and I honestly can't think of any counter-examples) storing the representation of a password in the database is the proper thing to do. By representation I mean that you want to hash the password using a salt (which should be different for every user) and a secure 1-way algorithm and store that, throwing away the original password. Then, when you want to verify a password, you hash the value (using the same hashing algorithm and salt) and compare it to the hashed value in the database.
So, while it is a good thing you are thinking about this and it is a good question, this is actually a duplicate of these questions (at least):
How to best store user information and user login and password
Best practices for storing database passwords
Salting Your Password: Best Practices?
Is it ever ok to store password in plain text in a php variable or php constant?
To clarify a bit further on the salting bit, the danger with simply hashing a password and storing that is that if a trespasser gets a hold of your database, they can still use what are known as rainbow tables to be able to "decrypt" the password (at least those that show up in the rainbow table). To get around this, developers add a salt to passwords which, when properly done, makes rainbow attacks simply infeasible to do. Do note that a common misconception is to simply add the same unique and long string to all passwords; while this is not horrible, it is best to add unique salts to every password. Read this for more.
Background
You never ... really ... need to know the user's password. You just want to verify an incoming user knows the password for an account.
Hash It:
Store user passwords hashed (one-way encryption) via a strong hash function.
A search for "c# encrypt passwords" gives a load of examples.
See the online SHA1 hash creator for an idea of what a hash function produces (But don't use SHA1 as a hash function, use something stronger such as SHA256).
Now, a hashed passwords means that you (and database thieves) shouldn't be able to reverse that hash back into the original password.
How to use it:
But, you say, how do I use this mashed up password stored in the database?
When the user logs in, they'll hand you the username and the password (in its original text)
You just use the same hash code to hash that typed-in password to get the stored version.
So, compare the two hashed passwords (database hash for username and the typed-in & hashed password). You can tell if "what they typed in" matched "what the original user entered for their password" by comparing their hashes.
Extra credit:
Question: If I had your database, then couldn't I just take a cracker like John the Ripper and start making hashes until I find matches to your stored, hashed passwords?
(since users pick short, dictionary words anyway ... it should be easy)
Answer: Yes ... yes they can.
So, you should 'salt' your passwords.
See the Wikipedia article on salt
See "How to hash data with salt" C# example (archived)
As a key-hardened salted hash, using a secure algorithm such as sha-512.
The best security practice is not to store the password at all (not even encrypted), but to store the salted hash (with a unique salt per password) of the encrypted password.
That way it is (practically) impossible to retrieve a plaintext password.
I'd thoroughly recommend reading the articles Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes [dead link, copy at the Internet Archive] and How To Safely Store A Password.
Lots of coders, myself included, think they understand security and hashing. Sadly most of us just don't.
I may be slightly off-topic as you did mention the need for a username and password, and my understanding of the issue is admitedly not the best but is OpenID something worth considering?
If you use OpenID then you don't end up storing any credentials at all if I understand the technology correctly and users can use credentials that they already have, avoiding the need to create a new identity that is specific to your application.
It may not be suitable if the application in question is purely for internal use though
RPX provides a nice easy way to intergrate OpenID support into an application.
In your scenario, you can have a look at asp.net membership, it is good practice to store user's password as hashed string in the database. you can authenticate the user by comparing the hashed incoming password with the one stored in the database.
Everything has been built for this purposes, check out asp.net membership
I would MD5/SHA1 the password if you don't need to be able to reverse the hash. When users login, you can just encrypt the password given and compare it to the hash. Hash collisions are nearly impossible in this case, unless someone gains access to the database and sees a hash they already have a collision for.
There are so many articles on stack-overflow and security.stackexchange on storing encryption keys, but I am still confused, so that's why I decided to ask again here.
Basically, I am creating an Email client for education purpose, in that Users can create account where they enter there Email-ID and Password. I am looking for secure way to save the information.
I will be
Encrypting the Email-ID and Password
and storing the encryption key on the user PC because I don't want the user to type in password every time he sends and Email
From reading I have understood that,
I need to store the encryption key in a separate location, so that it will be difficult to find by an hacker, But the problem here is that my application is written in Python and it will be open source application, so hacker can view the source code and get the path of the directory where the key is stored.
Second solution is that I can have a master password which will be used as a key, when the user opens the application for the first time after starting the computer, the application will ask for the master password, then I can store the key in RAM.
Looking at all the articles on internet on this topic this is a repetition, but I am sill learning to make applications and for the last two days I going in a loop with no success.
OS: Linux Ubuntu 14.04
Programming Language/Framework: Python/Gtk+
Your understanding is correct.
It's impossible to prevent a attacker with access to the local key from accessing the password. Obscuring the path where it is stored provides virtually zero additional security - any attacker with the know-how necessary to perform the decryption will easily bypass such a mechanism.
The only secure way to do this is storing the key (or a key to the key) out of the computer - in the user's mind, in the case of the master password mechanism.
If you end up using a master password, don't forget to use a proper key derivation function, ideally with a key-stretching mechanism, such as PBKDF2 or bcrypt. Never use a password as a key directly (or even a simple hash of the password.
I'm asking at a purely abstract level (no code required).
Some data is to be stored on a web-server/database on behalf of a user. The data is encrypted using the user's password as the key, ensuring that if the server or database is compromised, it is relatively useless to the attacker.
The problem is that the standard process of resetting a user's password (sending them a link with a token) won't work, because there is no way to decrypt and re-encrypt the data without knowing the previous password.
Are there any other ways around this?
When you say that you are willing to reset the password using some piece of automated authentication, then what you're really saying is that there are two passwords: the "normal" password and the "authentication" password. The solution to your problem is to encrypt the file using a random key and then encrypt the key using each of the passwords.
As a concrete example:
User provides a password "Aw3som1"
User also provides his high school mascot: "the Chipmunks"
Just to make it really complete, let's assume your authentication scheme is very forgiving like many are. You would accept just "chipmunks" (or "CHIPMUNKS" or maybe even "chipmunk") rather than "the Chipmunks." But whatever it is, your scheme must be deterministic. Every possible answer you will accept must resolve to the same hash. In this case, I'm going to assume that you lowercase the security answer, remove articles, and reduce to singular if it's plural. Then you prepend the class of question. So your secondary password is something like "mascot:chipmunk".
You now make up a random 16-bytes and use that key to encrypt the data. You then use normal password-based encryption techniques (e.g. PBKDF2) to encrypt the key with each of your passwords above. Then you throw away the key and the passwords.
When you need to do a reset, decrypt the real key with the provided password ("mascot:chipmunk") and re-encrypt the key with the new password (and "mascot:chipmunk" again).
The one usability issue is that a password reset invalidates all the other security answers, and the user must reconfigure them all. If that's a problem, you could put all the security answers into a bundle and encrypt that using the same technique as the data. (i.e. the security answers are encrypted against all of the security answers.)
This approach of course creates two (or more) passwords that can unlock the data, and so dramatically drops brute-force search time. You should consider that when scaling things. That said, your safety margins should generally be several orders of magnitude, so even a few passwords should be workable for many situations. Remember also that the security questions live in a tiny key space, particularly things like "mascot" or "make of car" which probably only have a few dozen likely values (unless you went to my high school which had a truly bizarre mascot…) That just means that aggressively tuning PBKDF2 is even more important.
Of course the existence of any kind of password reset system is going to make targeted attacks much easier. But that's true no matter how you implement the encryption.
But what if there isn't even a security question? What if you'll reset the password based on an email address alone? Well, then the email address is the password. That's problematic in the face of a stolen database, and it's hard to fix because there is no real secret (and encryption requires a secret). But all is not completely lost. One thing you can do is to never include the actual email address in the database. Think of the email address as a password (since it is in this case). Store a hash. You can't use a random salt on it, but you could still use some single salt for the whole database.
So my email is test#example.com. You treat that as a password, salt it with "mygreatservice" and run it through PBKDF2. To login, just treat it like a password again.
An attacker, though, has to guess email addresses one at a time. That's not incredibly hard, but he can't just decrypt the entire database in one go, and he'll never get the data from emails he doesn't guess. (And you did choose a really easy reset mechanism.)
Why do you need to un-encrypt the password? If they have forgotten then you will have to verify them based on the fact they had access to the email account where the reset token was sent. Ideally you would include some other form of question/proof of identity on the reset page like a secret question.
Also, you're best not storing the password using reversible encryption but instead using a strong salted hash which is one way.
I'm designing an API that uses application level encryption to protect sensitive information in a database.
A simple example of the problem is a user table with the following fields:
UserID
Name
Address
Telephone Number
ClientIdentifier
In the above table all fields are sensitive and should be encrypted apart from UserID which is just the primary key of the table. While the primary key exists for foreign key constraints the actual identifying value for the record is ClientIdentifier. This is an ID for the user controlled by the consumer of the API.
When a consumer of the API wishes to create a user record they pass all the details (including the ClientIdentifier) to us which we store. When they want to retrieve those details they again pass us the ClientIdentifier. For this use case, they cannot use the UserID.
It's likely that the ClientIdentifier could be public knowledge e.g. an email address or account number and can be traced back to a real person. Therefore we have to secure ClientIdentifier as the existence of a record would imply that the person exists on our system.
I see a couple of options.
Hash the ClientIdentifier. The downside to this is that the ClientIdentifier is likely to follow a fixed format and be vulnerable to brute force attacks.
Encrypt all the data but in the case of ClientIdentifier use a fixed IV. The downside here is that an attacker who had access to both the API and the database could execute plain text attacks on the system.
I'm leaning towards to the second option as the plain text attack can probably be mitigated with monitoring of the encryption service, whereas the hashing option could be broken reasonably quickly if a snapshot of the database was lost.
So my question is, do you think I'm on the right track or are there any better alternatives?
Edit: It's possible that we could have multiple records in the database with the same ClientIdentifier. Given a plaintext ID we should be able to select all those records.
If you're set on encrypting both the user id and the password, you might want to take a look at bcrypt. Its an adaptive hashing algorithm, and you can up the encryption complexity whenever you want. You'll have to use a system-wide salt, which will still make this vulnerable to a dictionary attack. Your best bet is to randomly generate an account # (with numbers and letters) to use for the client id, that should negate any dictionary attack. Be sure to make it long enough to be secure.
In general, the user id isn't encrypted because there is no way to salt the hash of the user id, which makes it vulnerable to attacks. Before you jump through flaming hoops, I'd make sure that you NEED to encrypt both the client id and password.
An organization I work for has a few different websites they use on a daily basis. I've been asked to develop a web application (using ASP.NET) that can access/synthesize information from these and display it in one location. Unfortunately, one of the websites does not support OAuth or anything similar, so I need to store their login credentials in a database.
My first thought was to use their credentials for my site as a key to encrypt their credentials for the remote site. For example: Bob logs in to my website with the password hunter2. Using that password, I decrypt Bob's credentials for www.example.com and log in as Bob there. Since I don't need to access example.com unless Bob is on my site, I can discard the decrypted credentials once he's done.
My assumption that simply using hunter2 (or whatever Bob's password is) isn't enough and that there is a "standard" way that I haven't been able to find on Google or Stack Overflow.
If you can't avoid storing the passwords on the server, then encrypting with the user's "master" password (e.g. "hunter2") is your best bet. No other approach offers protection in the event that the server is compromised. Now... how much protection you get hinges entirely on the complexity of the user's master password. I'll offer my analysis of the security of this scheme at the end, but before that, let me review the pitfalls to avoid.
First—and I assume that you already know this, but—you must not store the user's master password anywhere. Ok, with assumptions out of the way...
Do not use the user's actual password as the key to the encryption function.
Consider what would be possible if you did: what if an attacker managed to download your entire users table, complete with encrypted example.com passwords? We all know that user chosen passwords are easy to guess. What would stop the attacker from repeatedly decrypting the encrypted example.com password, trying 40 million commonly used passwords as the key, discarding any result that doesn't look like a password (that is, the decrypted result does not appear in the wordlist)? AES is designed to be fast. While not an apples to apples comparison, a sense of the speed of AES should be imparted when you consider that an encrypted version of the aforementioned 500mb wordlist could be decrypted in about one second on modern hardware. Worse yet, the attacker would not only get the example.com password, they would also have the key used for encryption, or in other words, the user's master password!
That, in a nutshell, is why you need to use a key derivation function (KDF). A KDF will ideally protect you in three ways:
Require a non-trivial amount of time to compute each key. A user can wait one second for the server to turn their password into a key. An attacker may be less inclined to wait 40,000,000 seconds—see analysis below.
Salt the password. Without salt, an attacker could brute-force the entire users table in one pass, not to mention make a space-time tradeoff.
Prevent recovery of the master password, even if the attacker recovers the encryption key.
One such KDF that provides all three is PBKDF2. Conveniently, there is an implementation built in to .NET:
public static byte[] DeriveKey(int keyBitSize, string password, byte[] salt) {
const int iterations = 1<<12; // Once set, any change will break decryption.
using (var kdf = new Rfc2898DeriveBytes(password, salt, iterations)) {
return kdf.GetBytes(keyBitSize);
}
}
Analysis
40 million seconds is less than 500 days. Since wordlists are usually ordered with the most commonly used passwords first, the attacker has a good chance of finding the password in significantly less than half the time it takes to try the entire wordlist. As a final wrinkle, it is possible to try keys in parallel: a 500-node botnet could try the entire wordlist in a day.
That's the problem with relying on the user's password for encryption security. You can choose to accept this risk or you can decide not to store the user's password on the server. If you decide to store encrypted passwords on the server, you can mitigate the risk by increasing the complexity requirements for the user's master password.
Whatever approach you take will have issues that will leave you doubting yourself. You need to balance the solutions against your environment & see what best fits.
Will each user of your app have an account on the remote system? How are users authenticated by your system? Will your app run in a trusted environment (eg corporate network).
I wrote a similar app to front an internal system that had it's own username & passwords. My app used Windows Integrated auth to figure out who the user was. it then asked for their password to the remote system & encrypted that value using a hard-coded key & stored the value in the DB. It could then retrieve the value, decrypt it & supply it to the remote system when needed.
Now in a non-trusted environment, someone could obtain my binaries & work out what they key was & get all the passwords. That would be bad. But on a corporate network, if they did that, they should come & work for me.
You already have access to the user's clear-text secondary passwords, so regardless of whether or not you throw away the encryption key, you're still responsible for their safety when it is in the clear. Keep that in mind when you handle the passwords.
If you use the user's own password to encrypt, you are reducing the strength of all their secondary passwords to the strength of the primary one. This is probably bad since a) user passwords are notoriously weak already (I know, why do we even bother in the first place?) and b) even with the strongest of passwords, it still won't match the strength of a solidly random 256 bit AES key.
My suggestion is to consider having a single AES key that encrypts their clear-text secondary passwords. Then, guard the AES key well. It may make sense, instead to have a root AES key that encrypts many sub-keys, one for each user. You'll have to do a risk analysis, I suppose.