Secure Password Storage and Transfer - c#

I'm developing a new user store for my organisation and am now tackling password storage. The concepts of salting, HMAC etc are all fine with me - and want to store the users' passwords either salted and hashed, HMAC hashed, or HMAC salted and hashed - not sure what the best way will be - but in theory it won't matter as it will be able to change over time if required.
I want to have an XML & JSON service that can act as a Security Token Service for client-side apps.
I've already developed one for another system, which requires that the client double-encrypts a clear-text password using SHA1 first and then HMACSHA1 using a 128 unique key (or nonce) supplied by the server for that session only.
I'd like to repeat this technique for the new system - upgrading the algo to SHA256 (chosen since implementations are readily available for all aforementioned platforms - and it's much stronger than SHA1) - but there is a problem.
If I'm storing the password as a salted hash in the user-store, the client will need to be sent that salt in order to construct the correct hash before being HMACd with the unique session key. This would completely go against the point of using a salt in the first place. Equally, if I don't use salt for password storage, but instead use HMAC, it's still the same problem.
At the moment, the only solution I can see is to use naked SHA256 hashing for the password in the user store, so that I can then use this as a starting point on both the server and the client for a more secure salted/hmacd password transfer for the web service.
This still leaves the user store vulnerable to a dictionary attack were it ever to be accessed; and however unlikely that might be - assuming it will never happen simply doesn't sit well with me.
Greatly appreciate any input.

HTTPS is the best solution for this problem.
You are throwing a lot of crypto primitives at this problem in hopes that it will go away. In general the protocol that you are proposing seems to wasteful of resources, I recommend doing research into other authentication protocols and think of ways of simplifying your protocol. Practical Cryptography is an excellent book.
The biggest problem is see is in transfer of secrets between the client and server. In order to implement this correctly you need to use a Diffie-Hellman key exchange. Luckily one has already been written in javascript:
http://enanocms.org/News:Article/2008/02/20/Diffie_Hellman_key_exchange_implemented
Another problem is that i don't see how the client can determine that its talking to the correct server. SSL uses asymmetric cryptography, backed by a PKI, which you will not be able to implement in JavaScript.
A message digest is not an encryption algorithm. It is never okay to spill a password hash, where as cipher text is meant to protect against an eavesdropping.
Spilling a password salt to an attacker will make your passwords less secure. If the attacker has a salt then they can use a dictionary to attack the password, without the salt they will have to guess randomly, making the password storage system far more robust.

A salt does not need to be secret - it must be unique. a salt is designed to mitigate the threat of two users having the same password and hence the same resulting hash. so you can use the user's name as the salt if you wish. a salt makes a dictionary attack much much harder because the attacker has to compute each result for every dictionary word and every possible salt.
in my opinion, i would use a password-based key derivation function (PBKDF) with a high iteration count and a salt.
http://www.bing.com/search?q=pbkdf2
Here's sample code in C#, but it's avail in most any popular framework today
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

Related

Storing credentials in an encrypted file

I'm working on a couple of projects that need to store user credentials for third-party applications, such as Paypal, Facebook developer creds etc. I've read a few books about different kinds of coding, including ASP.NET, WPF, jQuery, and all have nice examples on how to access the preceding services with own secrets, and also all of them use the exact phrase "in a real project you would store these in an encrypted file". None, however, give an example how to do so.
I have little (read: none) experience in encryption, but based on my understanding, I would need to encrypt a username and a password using some sort of key (salt?) and save them in a file. I would also want to be able to use these credentials on my apps so I would need to store the key (salt?) in my code.
Now my question is: How is it safer to store the decryption key, which is still plain text, in the program code, than the actual credentials?
Wouldn't the malicious user be able to decrypt my password-file as soon as he gets the key?
--EDIT--
I really mean my own credentials I need to store to log in to third party applications, not credentials of my users. For example I need to identify my self and/or my app to Google, so that users can log in to my app using their own Google account.
--EDIT 2--
To clarify, this is what I'm talking about. This screenshot is from asp.net PayPal tutorial:
Any quick pointers on good practises here?
You misunderstood the part about storing encrypted password* + salt: this is done when your system needs to validate someone else's credentials. In this situation storing password hash and the salt is more secure than storing the credentials, encrypted or not, because an attacker would have no way of getting the password back, even if he manages to get his hands on both the hash and the salt.
Storing decryption key in plain text is never a good option, because an attacker would get your users' passwords as soon as he gets access to the key.
There is no good solution to persisting your own credentials, encrypted or not. Your component that talks to 3-rd party services should use developer APIs from these providers. For example, PayPal provides two sets of APIs which you can use to access your account without having to store your password.
If you need to store a small amount of secret information in an encrypted form, use registry APIs to store the data in a key known to your application, and accessible from the user running your server-side component. This secret would be safe, as long as hackers do not hack the password for the account under which your service is running.
* Technically, password is not encrypted, it's hashed, i.e. there is no reliable way to turn the result of conversion back to the original value.
Your suspicions are correct. If the user has access to the key they can just go and decrypt the username and passwords themselves.
The two options you have are
Make it difficult enough to get the password that the reword of getting the password is not worth the effort to find it. This approach is done via things like Code Obfuscateors, I would not recommend this to someone starting out. Its not easy to get it right and it only takes one person who things it is "worth the effort" for it to break.
Don't give the user the information ever. Instead of storing the usernames and passwords in the program have your program call out to a server you own, then that server is what makes the request using the credentials. This approach is the more reliable one and is "unbreakable" (as long as your server is secure) but costs more because you now need to keep a server up and running that can handle the load of your entire userbase.

What would be the best way of storing a password in SQL that needs to eventually be in plain text?

For user passwords, we should always hash and salt them and then store the hash and salt in the DB. But what's the best practice for storing passwords that need to be eventually be in plain text? I don't feel comfortable storing a plain text password in SQL, but I have to send the password to a library so it can access something.
My thinking was that I could store an encrypted password on the database server and then decrypt on the web server. If both are compromised, I'm screwed. But if just one if compromised, the encryption gives me enough time to change the password.
What do you all think?
To be on a safer side, just hash the password and save, then you can compare user password input with the hash code in your database when you need to authenticate.
If you really need to get plain-text form of password ( which is really not good idea ) you can use symmetric encryption for security user passwords. But you must figure out how to keep private key in secure. I mean you need a private key in your code in order to decrypt data. Also all of your developers can access private key which means they can access plain-text too.
Also I suggest you to read this article. It's comparing hashing and encrypting user password. http://www.darkreading.com/safely-storing-user-passwords-hashing-vs-encrypting/a/d-id/1269374
Microsoft provide an API for this use case as part of the Crypto API. It's not particularly easy to work with, but provides much better security than storing keys in text files, or in the database.
It's fair to assume that if an attacker can get onto your database server, they have access to every system in your environment; and even if you think you have "time to change the password", how would you know your system has been compromised? Most attacks aren't noticed until much, much later...

Which Encryption algorithm does ProtectedData use?

For password encryption I want to use ProtectedData.
As far as I found out, this is a wrapper for CryptProtectData.
The MSDN only states something vague about encryption based on user credentials
and that decryption usually must be done on the same machine, if user has
no roaming profile.
Which encryption algorithm does it use?
Is there any analysis that states whether this encryption is suiting for password storage?
How else to implement a local password storage?
This MSDN article has more information about CryptProtectData and DPAPI, and should contain the information you need. In particular:
DPAPI initially generates a strong key called a MasterKey, which is
protected by the user's password. DPAPI uses a standard cryptographic
process called Password-Based Key Derivation, described in PKCS #5, to
generate a key from the password. This password-derived key is then
used with Triple-DES to encrypt the MasterKey, which is finally stored
in the user's profile directory.
The article applies to an older version of Windows, so depending on your Windows version, these algorithms might change, but they are probably not going to be less secure than the ones mentioned here.
Whether or not this is suitable for "password storage", depends a bit on what exactly you mean by this and what passwords you're storing I would say.

Password hashing over multiple platforms (Andorid, iPhone, W8M)

We are currently developing a web application in .Net which will also have Android, iPhone and Windows Mobile 8 apps to occupancy it. All of these applications need to have a unified login system. Our site and web services will be using SSL but obviously we want to do all we can to make sure user passwords stay safe. As such we are looking for a common password hashing function that can be used throughout the platforms outlined above.
Currently the only common one we have found is SAH256 however I would like to use something a little stronger. C# has the Rfc2898DeriveBytes class which I would like to use (and can be used in the website and Win8 Mobile) but are there any implementations of this for Android/Java and iOS/Objective C? If this can’t be used what would be our next best option?
The password hashing function should be used on your back-end when storing the user's password and comparing during a login attempt.
Login scenerio:
User sends password over SSL via one of the versions of your app.
The back-end server hashes the password that was sent from the user, retreives the stored hash from the data store, compares the hash of the password sent with the stored hash.
Hashes match, user is allowed access, otherwise access is denied.
The SSL encryption prevents exposure of the password during transmission from the client, storing passwords as hashes prevents exposure of user passwords if your database is breached.
Using this scenerio, since the hashing is all done at the back-end server, only one implementation of the hash algorithm is required.
PBKDF2 is not something that fits well in your situation. It is mainly intended to prevent attacks when the attacker already has your data (ie. an encrypted file). It does this by eating up CPU to force a delay during brute-forcing. Because you're performing auth server-side, you can easily save some CPU and just wait a second or two to send an response to the client if they get the password wrong. Just use a salted hash (like HMAC), and you'll be fine.
If you're using SSL, then your passwords are secure. The only way you can do any better is to implement full public-key crypto, which can prevent MITM attacks. SSL even has this built in.
Sending password hashes over a network is not really more secure than sending passwords. Yes, the password text is hidden from attackers, but they've still got the hash and if they have that, they don't need the password. In the case of SSL, your plain text is also protected.
While I've never used it personally, bcrypt appears to have all the implementations you are looking for.
http://en.wikipedia.org/wiki/Bcrypt#See_also
Hope that helps.

How to encrypt stored information, using C#?

I am creating an application which stores multiple passwords of a user. First user has to provide his/her user-name plus password, and after successful login he'll be given all his saved passwords.
I am using md5 encryption method. I've successfully integrated md5 in my log-in module. But the problem is, how can I encrypt the stored passwords (in a file), as there is no legal way to decrypt md5 hash. Please suggest an algo.
Any help would be greatly appreciated!
You would want to use a symmetric encryption algorithm like AES, or 3DES. MD5 is not encryption, it's hashing, and the original password is not actually preserved.
You could use AES Algorithm
Following article may help you to get started:
Keep Your Data Secure with the New Advanced Encryption Standard
The Advanced Encryption Standard (AES) is a National Institute of
Standards and Technology specification for the encryption of
electronic data. It is expected to become the accepted means of
encrypting digital information, including financial,
telecommunications, and government data. This article presents an
overview of AES and explains the algorithms it uses. Included is a
complete C# implementation and examples of encrypting .NET data. After
reading this article you will be able to encrypt data using AES, test
AES-based software, and use AES encryption in your systems.
MD5 is not an encryption algorithm. It's a one-way hash. A one-way hash algorithm is suitable for authenticating users because you only ever hash their entered password (and compare it with the saved hash). You cannot decrypt a hash and display their passwords.
You need an encryption algorithm.
I am creating an application which stores multiple passwords of a
user. First user has to provide his/her user-name plus password, and
after successful login he'll be given all his saved passwords.
Since you are using C#, I'm assuming you are working on Windows and not a Mono project. First, the user proved his/her identity when they logged on, so there's no need to ask them to do so again.
Second, use Data Protection API (DPAPI). Its the standard way of storing user secrets on a Windows system. (cf Writing Secure Code, Chapter 9, p. 305). On earlier version of .Net, you will need to interop. On later versions of .Net (3.5, IIRC), it is available via the CLR.
Finally, MD5 is broken so it should not be used for cryptographic purposes. NIST recommends a security level of 112 bits (cf, Special Publication 800-57). Ditto for ECRYPT.
If you must discard DPAPI, use SHA-224 or higher as the hash for a password based key derivation function. Encrypt the file with 3-key TDEA, AES, Camellia, etc. Use an authenticated encryption mode (EAX, CCM, GCM) to detect tampering. If you don't have an authenticated encryption mode, you will need to add authenticity assurances yourself with a CMAC or HAMC (DPAPI does it for you).
Jeff

Categories