C# and SQL Server: Passwords. Where to do what? - c#

Ok, I have an application written in C#. We have data in an SQL Server. Among that data we have user accounts, which will give access to the application.
I've read around, and I know that you should salt and hash and possibly hash a bunch of times, etc. But, where do I do what? What do I send to and from the SQL Server? Exactly what do I store in the database? Do I hash it in SQL? (possibly a hash function there, like in mysql?) Do I hash and do the fancy stuff in my code? Do I send the hash to the server and compare, or do I get the hash from the server and compare in my application? What about the salt? Where do I make it? Where do I store it? How do I get it?
In other words, could someone give me a nice and clear walkthrough of a login scenario (and possibly a user add/reset password scenario). What goes where, what should be used where, etc.
Hope someone can clear these things up for me =)

For C# + SQL Server, you can just use the MembershipProvider model, which will take care of all this for you.
And IMO, the most important part of getting all this stuff right is not doing it yourself. Rather, rely on the mechanism provided by your platform. It's just so easy to get it wrong in a subtle way that appears to work. Then you deploy, and you don't even know anything is wrong until after you are hacked.

I agree with Joel Coehoorn completely, the best choice is to trust someone else's tried and true implementation. If, however, you're determined to roll your own security implementation, then my advice is the following:
Store the hash and salt in the database.
Generate the hash and the salt in your own code. That way you're not tying yourself to a specific database.
Never send the password over the wire as plaintext. I would recommend fetching the hash and the salt from the database and comparing it to the ones you calculated from the username and password supplied by the party that wishes to be authenticated.

If you are using ASP.NET, using the built in membership stuff is a cakewalk to implement I would recommend going that way.
However, as a general question, I would implement the hashing in your local code, then only send the hash values out to the database. For salts there is a number of ways to do it, you can create a random salt, or you can salt the value using the records id, or something else. Again, I would do it in the C# code. There is a helpful method in the framework for doing it.

I did this myself a number of years ago before the Membership Provider model was available.
We used the functions built-into ASP.NET to handle the hashing of the password; it's the static method HashPasswordForStoringInConfigFile in the FormsAuthentication namespace. You give it a password and an encryption choice and it returns the hashed password.
Our flow was:
- Get the hashed password from the database for hte entered user name.
- Hash the entered password.
- Do they match? If so, continue, else logon failed.
When changing the password, we sent the hash to the database for storing; we did not send the unencrypted password.
And, I believe, it is what the MembershipProvider is doing under the covers today.
To reiterate too, the most important piece when doing forms authentication regardless of how you are doing it, is to work over a secure (HTTPS) connection.

Related

Get back computed hash value when using SHA512Managed

this may sound non sense, actually in may application I use to store password string in DB by computing to hash using SHA512Managed, I am writing a utility using which an admin can send mails to users using that EmailAddress and Password, but I can't pass that coputed value as a password to SMTP. is there any way to solve this?
Or a better cryptogarphy way?
Or any way to send mail in this condition?
Thanx
You cant, SHA512 I believe is not possible to be decrypted, which is why it is used.
All you can do is keep some form of data on your users aka, secret questions, and they must match them and then it will send them a new password.
Any properly encrypted password is not abled to be decrypted
You should NOT be using OR sending your users password, or even a simple hash of that, for that matter.
If you want to enable password reset, you should hand the users a TOKEN (which is NOT the hash of anyone's password). This token should be separately stored in a table and should have a set expiry.
You can use any kind of cryptographic hash (SHA512 is just fine) to 'encode' special information.
--- I fully missed what you meant by 'I cannot...as a password to SMTP'
If you need the original password of your users to even send mail, than - well that is twisted. Perhaps you could elaborate/explain this part
SHA-512 is a one-way hash, meaning you can't take the hash value and determine what string/value was used to generate that hash. Technically, there can be an infinite number of strings/values that would generate the same hash.
If you want to be able to get the value back, you should use encryption, not hashing.

SQL query to create a encrypted password

I am trying to create a secure password login screen in c#.Right now i have just created the login screen and I am able to read the username and password from the database.But which i have designed does not have an encrypted password. Can any one help me out how to write a query to generate encrypted password and store the encrypted password value in a separate field.Thanks in advance.
Consider hashing the password that you currently store. SQL can hash a password as follows:
DECLARE #HashThisPassword nvarchar(4000);
SELECT #HashThisPassword = CONVERT(nvarchar(4000),'dslfdkjLK85kldhnv$n000#knf');
SELECT HashBytes('SHA1', #HashThisPassword);
... But SQL shouldn't even need to do this. You should hash the password as soon as your C# application receives it, and then only ever pass the hashed password into SQL to be saved. When checking if the user has provided the correct password for login, compare the hashes.
Your best bet is one way encryption.
What happens in this scenario is the user selects/is given a password. When that password is stored in the database it passes thorugh this one way encryption before it is stored. (You'll be doing this in your c# code)
Then when the user logs in, the entered password passes through this same one way encryption before it is compared with the password in the database.
This ensures that if a hacker gets into the database, it will be difficult to learn the password because they would have to determine the encryption type, and then devise a way to un-encrypt it which to my understanding is difficult at best, impossible at worst.
Here is a link to some code that may help. One Way Encryption
You don't want to do the encryption in sql itself, because if a hacker DOES access your database, they will be able to simply look at the procedure/function that you are using to do the encryption and they will have a much easier time.
And you don't want to store the password in the database unencrypted as well...
Your best bet is to write some code to read the password, encrypt it, and update the record, then all you have to do is continue to use the same encryption type and salt.
The c# cryptography library is very easy to use.

How to Manage Key in a Symmetric Algorithm

I am doing an AES encryption in my C# code, using a key which is generated using PasswordDerivedKey function by passing a password and a salt of 12 byte. I have implemented the logic in my application code and the "password" is the username of the logged in user and the salt is a static byte aray.
What is the best way of storing the password and the salt, as someone can easliy determine the salt (by reflecting my code) and the username of a person.
What are the alternatives I can adopt to store the password and the salt in a secure way. I dont think storing them in my application code is the best way of doing it.
Edit: By password, i meant the passkey used in the PBKDF function (to derive an encryption key) and its not the password provided by the user. I am using Windows Authentication
Why would you need to store password if it is merely an encrypted version of the windows username?
Anytime you need to encrypt/decrypt you know name of user thus can generate key dynamically.
Salt should never be considered a secure asset. No need to hide it. You should always assume attacker knows the salt. Salt is simply a mechanism to defeat rainbow tables and other fast lookups.
Is there something I am not seeing?
On Edit
The issue is misstated in the question. The issue isn't what/how should be stored. That answer is simple. Never store any of the cryptographic data (except salt).
The current implementation creates an encryption key from the username of logged in user. The problem is that is insecure as determining username is rather easy. To get around this one would need to either:
a) accept the implementation is insecure to someone willing to decompile app.
b) ... not a good idea ... hash can change based on groups/roles
c) use a unique secret password for each user.
c is the only secure implementation however it requires prompting the user for a passphrase when encrypting or decrypting.
Against whom must be the data be secure? If the currently logged in user is allowed access to the data, but other Windows Authentication users are not allowed access, what you really want is for the data to be encrypted for the particular logged in user. If you have access rights to configure the PC, you might be able to create an Encrypted folder with permissions only for the desired user. This is not 100% secure (you can still intercept the data at various places if you have root access), but your only other reasonable alternative is to add another password.
Alternately, you can simply accept that the protection is weak and provide minimal obfuscation. It depends on the value of the data and the capabilities of your possible attackers. If your attackers have sufficient privileges to Reflect over your assembly on the actual machine, then it's highly likely that they're also Administrator, which means you're pretty much screwed no matter what you do. There are tools that can connect to a running process and monitor its memory, which means they could simply wait until you've decrypted the data and read it from memory.
Best way to keep the salt is to generate it on runtime and keep it per session along with other user stuff such as username and password:
use signs in and provide username/password
hash with stored salt and check against password hash
create new salt and store it along with the hash
Symmetric encryption (or even asymmetric) is not at all recommended for passwords. You not to hash it which is just one-way.
I added this as an second answer because it is a different solution. I just thought of it tonight because I am working with this class (trying to reverse engineer kindle encryption).
You may want to look into the Protected Data Class
http://msdn.microsoft.com/en-us/library/2c64xe0y(v=VS.90).aspx
This is a class that allows you to store data in the windows cryptographic store.
By using the Protect and Unprotect function you can pass data into and pull data from the cryptographic store.
If you didn't want to force the user to create (and remember) an encryption key you could.
1) Check to see if current user has encryption key in the store.
1a) If not then create a random encryption key
2) Use key to encrypt file and store
3) To decrypt retrieve key from store.
4) Another user may be able to access the file but will be unable to get a copy of the key from the store.
A couple caveats. Only the windows user who stored the key can retreive the key. However this can be bypassed depending on environment. If the user has no windows password (or weak windows password) anyone w/ access to machine can run as the user and windows will gladly hand over the key. In a domain environment anyone (admin) who can impersonate the user and modify password can access they key. If user's windows profile is trashed so is the only copy of your encryption key.

Best way to store password into sql

in my current C# windows application password has been stored in plain text which is obviously not good. so i just want to know what is the best way to encrypt the password and stored into SQL Server. I have read that using hash+salt is better. but i feel "EncryptByPassPhrase","DecryptByPassPhrase" new feature in sql 2005 is better to use because you are handling everything from SQL Server itself and i suppose it uses triple DES. can somebody suggest is it good to use it ?
Do you need to have access to the original password, or are you just going to try and compare an entered password against one in the database?
If you need access to the original password, then you are going to have to use an encryption algorithm instead of a hash algorithm.
If all you're doing is storing a password in the database so that you can check it later against a known input value, then a hash with a salt will work.
Remember that when the client is sending the credentials across to be validated, that you don't want to be sending the password in clear text!
A hash & salt is the way to go, because its impossible to retrieve the original password from it. If you encrypt then decrypt the password, the plaintext password is retrievable so its not the best.
I agree it makes sense to have the encryption all in 1 place. However if you separate the key from the data (key in the c# code, data in the db), that will increase security. Also, Sql Server uses a master key when encrypting, which means if you need to restore the data to a new server, you will have trouble restoring the data.
This all comes down to key management and how you want to do this.
As with most questions the best answer depends on the context of your situation. There is no good solution.
Some options:
Leave the password in plain text or reversably encrypt. Use SQLServer facilities to encrypt important fields at the RDBMS level or use similiar encryption functions and hope that MS has implemented reasonable key management and the keys are reasonably secure for your purposes. In practice all encryption does is collapse storage of a whole lot of little secrets into storage of one big secret.. It might make the problem more managable but the problem itself never goes away.
Irreversably "Encrypt" the password using a hashing algorithm or some form of crypt(). Depending on the attack vectors available this method may not provide much in the way of actual improvment of security over plaintext storage.
. Use of hashed passwords limits your options in terms of selection of a secure authentication algorithm. With this approach you will likely end up sending plain texts or other material that is no better over a transport (regardless of if unbound encryption is used or not) this can be a substantial risk from a trust POV.
. Succeptable to offline dictionary attack if hashes are stolen recovery of some portion of passwords should be outright assumed if they have any value to an attacker.
. In some cases knowledge of the password hash can be just as bad as knowing the password in terms of system access.
If you are certain that you will never use a hashed scheme to authenticate (like HTTP Digest Auth), hashed password is more secure. To avoid rainbow table attack, please use a nonce (or salt). I would use HMAC-SHA1 and use the nonce as the key. They key must be stored with the password.
Otherwise, you will have to store encrypted password because hashed password can't work with authentication involving hashes. For encryption, I have following suggestions,
Don't store the key in DB, don't hardcode it either. Store it some other secure place, like using DPAPI on Windows.
Make sure you have a key version so you can rotate the key to comply with certain standards.
I am not familiar with the encryption in SQLServer. Make sure it has a random Initial Vector. You can check this by encrypting same password twice, it should yield different ciphertext. If no random IV, don't use it, just encrypt it in your application.

Class with userdata (password & username) - make it secure

I have a class that stores a users user data (user ID & password) from the login window in my application. Currently I'm using SecureString to store the password, but in certain places I need the original password to verify things. (it has to be plain text at that moment)
Does anyone know a secure way to store it in memory where it can easily be re converted to plain text if it is needed?
It looks like SecureString itself isn't secure and there are tools to get the secure string. You can write your own code, to encrypt the string, break into parts and store it, but again no security is complete, if you need to use the password like say for Database login, etc. hacker can find out and break your code.
Security is not one point, so lot of things like code obfuscation, etc. goes hand into hand.
Tools like SmartAssembly can protect strings by auto encrypting, it.
The other idea would be to store the hash, instead of the password itself, and the hash is basically created using some random parameter, so that it can't be recreated, one time passwords.
Consider CryptProtectData():
http://www.pinvoke.net/default.aspx/crypt32.cryptprotectdata
It can use either the current user key or the local machine key. In a Web setting (i. e. ASP.NET), you want to use local machine. As long as you have a single Web server where encryption/decryption takes place.
you can encrypt password by MD5 and for compare you can encrypt inputed data and copmare two string

Categories

Resources