0

I'm currently employing the following hashing algorithm for storing encrypted text in my database:

public static string HashString(string inputString, string hashName)
{
    HashAlgorithm algorithm = HashAlgorithm.Create(hashName);
    byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
    return Convert.ToBase64String(hash);
}

Basically, whenever the user inputs anything that needs to be encrypted, I call this function first, and then store the result in the database.

This has worked fine for me so far, because I've only been storing passwords, and I never need to actually output the content. Whenever a user wants to log in, I take the password they enter, encrypt it using the above function, and then compare the encrypted password with the value stored in the database.

The problem I'm now encountering is that, in certain cases, I do need to get the unhashed content. Basically, I want the clients to be able to store the username and password for their SMTP sending account, and I need to be able to then create the credential, using the following:

System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(login, pass)

Since the content stored in my database is encrypted using the HashString method, how can I send the password to the NetworkCredential, for use in my SmtpClient? Ideally I want to maintain the part about me not being able to obtain those passwords myself.

Kiran Ramaswamy
  • 605
  • 1
  • 8
  • 19
  • 5
    Note that hashing is not the same as encrypting. You can unencrypt something, but you can't unhash something. Hashing is irreversible. In addition, if you need the actual login and password to pass to that function, you will have to have it. You can't use it if you don't have the actual unencrypted password. – GolezTrol Nov 02 '17 at 20:48
  • So there is no way for me to store the username and password in my database, in a manner that allows me to use those usernames and passwords to create the NetworkCredentials for sending emails, but at the same time make it impossible to make use of for anyone who somehow gets access to my database? – Kiran Ramaswamy Nov 02 '17 at 20:52
  • 1
    You can actually *encrypt* the passwords in the database. The password needed for decryption can be stored somewhere else. It's an extra safety measure, because someone who would break into the database can't use those encrypted passwords without the 'master' password. But there is a bit more to storing passwords than this comment can contain, so make sure you get a proper book or article that at least mentions something about 'salt' and 'cycling'. – GolezTrol Nov 03 '17 at 10:51
  • In addition, check for OAuth and other means by which you can authenticate to third party systems (if they support it). Those systems work with *tokens*. Your system only has to save the token (still protected, of course), but if someone breaks in into your system, they only can do what your system could do. They don't have the actual credentials. When in doubt, you (or the user) can easily deactivate the token, without the need to change their actual credentials. – GolezTrol Nov 03 '17 at 10:55

1 Answers1

0

After reading a bit more in to this, I've realised that my question is not really well formulated. I'm going to mark this as answered, and upvote @GolezTrol's comment

Note that hashing is not the same as encrypting. You can unencrypt something, but you can't unhash something. Hashing is irreversible. In addition, if you need the actual login and password to pass to that function, you will have to have it. You can't use it if you don't have the actual unencrypted password.

since it helped steer me in the correct direction. I found Fundamental difference between Hashing and Encryption algorithms to be a useful reference for helping to guide me closer towards what I should be doing.

Kiran Ramaswamy
  • 605
  • 1
  • 8
  • 19
  • 1
    Since comments are considered ephemeral, it'd be a good idea to briefly restate @GolezTrol's comment in your answer. – Blorgbeard Nov 02 '17 at 21:26
  • More info: Do not encrypt passwords, when the attacker gets the encrypted passwords he will also get the encryption key. Just using a hash function is not sufficient and just adding a salt does little to improve the security. Iterate over an HMAC with a random salt for about a 100ms duration and save the salt with the hash. Use a function such as `ehash`, `PBKDF2`, `Rfc2898DeriveBytes`, `Bcrypt`, `passlib.hash` or similar functions. The point is to make the attacker spend a substantial of time finding passwords by brute force. – zaph Nov 02 '17 at 22:47
  • @zaph the problem here is that OP needs access to the plaintext password in order to authenticate on their behalf to a 3rd party system. – Blorgbeard Nov 02 '17 at 23:01
  • 1
    Got it. The passwords that are not used for SMTP should be password-hashed. The encrypted SMTP passwords are a more difficult problem. They need to in an HSM or on a server that is not directly connected to the internet. Access to such a server must be very restricted, rate limited with alarming and with 2-factor authentication. – zaph Nov 03 '17 at 00:24