I am currently writing a c# mvc web application in which password are being taken from a user and stored in a database - sql server. I need a way of hashing the passwords.
It has been recommended to be to use the Data Protection API (DPAPI). I am not familliar with it and from research on the internet, very little information exists on it.
Can anyone point in the direction for further information on it? OR give me an overview of how to set it up and work with it etc.
The Data Protection API is primarily used for protecting cryptographic keys and secrets under a users credentials. If you want to store hashed passwords in a database, the DAPI isn't really what you want.
The ASP.NET Membership Provider is used for managing users, including hashing passwords with a salt. Unfortunately there doesn't seem to be a method to just return a hashed password, so if you don't need the extra functionality, it might be worth extracting the relevant code from something like CodeFirst Membership Provider (See Crypto.cs in the Source Code). The advantage here is this Membership Provider uses PBKDF2 to derive the hash, which is more resistant to brute force attacks given the number of rounds. It's also the method StackOverflow itself uses.
.Net has a wrapper class for the DPAPI called ProtectedData. It it very easy to use, and contains just two static methods: Protect and Unprotect. A How-to article can be found here. The DPAPI does not require a key because it uses either the logged-in users's credentials or the machine's credentials to do the encryption, depending on what scope you choose when calling Protect. Note that if you intend to store the encrypted data in a database, you must be sure to always use the same windows user account or machine (again, depending on the encryption scope), or else you will not be able to decrypt the data. Thus, depending on your application, this API may not be optimal. It is primarily intended for doing local encryption on a single machine rather than for distributed applications.
Related
I know that the "how do I securely store a password?" questions have been asked many times here; and I know the answer is always "Never do this! Store hashes, never store passwords! Use bcrypt!"
But what about times when you cannot use a hash for authentication? For example: automated processes. Say I wrote an automation application that needs to log into an SFTP site or some sort of external service that requires a username/password. I can't use a hash to authenticate with an external service, so what am I supposed to do?
I tagged this question with C# and ASP.NET as these are the two areas that this question applies to specifically for my situation.
Edit: Due to discussion raised in the comments, let me clarify the threat I'm trying to address: I want to prevent an attacker from being able to read the plain-text password used to access the external service. Meaning that if they somehow gained non-admin access to our network or database, even with the database dump they would not be able to read the passwords in plain text.
There are different options, both using encryption for password using a key, and protecting the key storage using HSM module.
option (1): Using Database with HSM module
You can store passwords encrypted in database and benefit from a feature in SQL 2016 "Always Encrypted (Database Engine)".
Always Encrypted allows clients to encrypt sensitive data inside client applications and never reveal the encryption keys to the Database Engine (SQL Database or SQL Server).
You can use Hardware Security Modules (HSM) with Always Encrypted.
The hardware security module (HSM) is a physical device that safeguards digital keys and performs cryptographic operations. These modules traditionally come in the form of a plug-in card or an external device that attaches directly to a computer or to the network.
When you get an HSM, you also get a software libraries implementing common APIs, such as Microsoft Crypto API and Cryptography API. These API are called Cryptographic Service Provider (CSP) and Cryptography API: Next Generation CNG providers.
Your applications can communicate with an HSM using those APIs.
For more securing the HSM module, you can:
- Tie the HSM to your Database Server.
- Tie the HSM to your admin login to Operating System Server.
for more details:
Always Encrypted (Database Engine)
Using Hardware Security Modules with Always Encrypted
Also, Oracle database and other engine can provide encryption with HSM
Securing Stored Data Using Transparent Data Encryption
Option (2): Store password in files in Protected storage using HSM module:
Encrypting files that contain passwords. This may be done by the operating system, an application, or a specialized utility such as password management software that is specifically designed to protect the confidentiality of passwords.
Using OS access control features to restrict access to files that contain passwords. For example, a host could be configured to permit only administrators and certain processes running with administrator-level privileges to access a password file, thus preventing users and user-level processes from accessing passwords.
As you are not using hashing, I exclude this option, but it's a mechanism for storing one-way cryptographic hashes for passwords instead of storing the passwords themselves.
AES encryption and store the key in an external encryption key storage module, if you happen to have access to one of those.
Otherwise, you could try scattering parts of the encryption key on different servers or something but it shouldn't be the first choice.
In my opinion, this shouldn't be solved with a HSM, as that also needs a password that you would need to save. Better is to always type in the password only when restarting the system (a server seldom restarts, so that's ok). The RAM is more or less safe (see here). See for discussion of small projects that have a maybe physical server that have a crontab here.
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.
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.
I would like to use TDE, but I cannot use it, so I have chosen to use the EncryptByCert and DecryptByCert functions. However, I was also considering encrypting/decrypting data in c# as shown here.
My question is are EncryptByCert and DecryptByCert unsecure because the certificate is also stored in the database? How do people get around this problem?
Is using the c# built-in encryption a better idea?
Thanks in advance for any help. :)
There is an Encryption Hierarchy one has to deploy:
(source: microsoft.com)
The root key used can be the service master key (actually the root is the service password, but this is transparent to the service start), in which case the applications can access the data just by simply connecting to the database and decrypting it. This protects the data if the database file is lost accidentally, but does not protect the data against compromised access to the server: since the decryption key is held by the server itself (the service master key) then anyone that has access to the data can see the data, because anyone can decrypt it. The data is protected through normal access rights and permissions, but the cryptography does not add any protection against authorized users.
The other option is to rely on a password at the root o encryption hierarchy, in which case the application must ask the user for the password to access data. For instance, if is a web site , the user would have to fill in a data decryption password in order to access a specific page. This truly protects the data cryptographically against users that gain access to the data through ordinary data access permissions and don't know the password(s).
SQL Server 2008 also offers the possibility to leverage a hardware TPM to store the decryption key (ie. an employee badge) but this is Enterprise Edition functionality only.
Ultimately, asking if the SQL Cryptographic API is secure or insecure is a non-question. The API itself of course is secure. Encrypting with the data with a symmetric key and then encrypting the symmetric key with a certificate and storing the private key of the certificate along with the data in the database is secure, as long as the private key is properly protected. The security or insecurity of a cryptographic deployment it always ultimately driven by the key management (bare some faulty implementation, but lets assume the implementation is perfect) and key management is 1% application design and 99% human process.
Ultimately, you need to do a serious threat modeling (sorry, but "The threat is that the data is private information and should not be seen plain text." is not threat modeling). Follow a methodology like STRIDE, or other similar methodologies. This is a very hard domain, and is deceptively simple to read about cryptographic APIs and believe that you know how to protect data:
The world is full of bad security
systems designed by people who read
Applied Cryptography
I need to store my users' name/password somewhere (preferably the Registry) so my .Net application can use them to log in to some remote service on behalf of the user. I know it's possible to store values in the registry as "secrets", which means their encrypted using the Windows domain user token or something. In other words, I don't want to have to deal with the encryption myself.
To clarify: I can't store hashes of the password or salt them or anything. These credentials are for a 3rd party system and the only way for me to be able to login to this system on behalf of my users is to somehow keep their credentials and be able to restore them.
So anyway, I remember vaguely there's such a place in the registry, but the details are murky. And I need to do it in C# (though if it's simple registry access it shouldn't matter).
Edit: One more thing, it should persist between Windows user sessions (IOW it doesn't help me if the password in unreadable after the user logs off and on).
You're probably thinking of the Data Protection API. Search MSDN or read some blogs and see if that'll work for you.
You can try using System.Security.Cryptography.ProtectedData, which can encrypt them using a per user key. http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx.
It's not completely secure, since code running as the user could decrypt the data.
Keep in mind that you're not really securely storing anything if you can automatically (without user input) retrieve the password. Using RSA, symmetric, or other encryption doesn't make a difference so long as you store the decoding key within your application. Once anyone gets the key, the secret's out.
However, the Data Protection API mentioned above should protect passwords from other users on the same machine. (It sounds like DPAPI uses your login credentials for encryption.)
For a few more options, check out the msdn page for Threat Mitigation.
You should never store credentials as plaintext. Use a symmetric key cipher. Take the password out at runtime. See the MSDN reference on Cryptography functions.