Where should we store our hashed username\password? - c#

I'm developing a desktop application in C#. In my application user should login before using my application. Now I want to save my username and password securely.
I know about hashing my username\password and adding salt to my password and saving hashed data in a file; but in this case user can replace this file with previous one. And I know we can't prevent this completely but I want make it hard.
One solution is storing hash of file in registry to prevent changing this file; but I think there should be a better solution.
Edit: I don't use database and I'm using windows 7.

You can follow this tutorial: http://msdn.microsoft.com/en-us/library/aa302402.aspx
It uses CryptProtectDataAPI, that provides the following:
The CryptProtectData function performs encryption on the data in a DATA_BLOB structure. Typically, only a user with the same logon credential as the user who encrypted the data can decrypt the data. In addition, the encryption and decryption usually must be done on the same computer.
Check more info here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261(v=vs.85).aspx

Related

ProtectedData.Unprotect after User changes password

I have a C# application that stores password information in a database using ProtectedData class. I use a scope of local machine and as I understand It DPAPI will use master key to encrypt it and it won't be changed unless I uninstall OS.
Let's say I want to use scope DataProtectionScope.CurrentUser. As I understand it then uses different master key that is protected by users password. So when User changes the password the master key with which it protected data stays the same and just password that protects it changed.
My question is: is my data (in database) retrievable (and how) after User changes password?
See this site, which has links to papers (and more importantly, code) reverse engineering the system. Their first presentation was this one at Blackhat Europe 2010.
Essentially, the SHA-1 hash of your current password protects the DPAPI masterkeys, which protect in turn each DPAPI-blob (there is a per blob salt as well). Each masterkey has a GUID that identifies the password that is used to protect it. Each blob also has a GUID that identifies which masterkey was used to encrypt it. These masterkeys expire after three months and a new one is created, but the old ones are kept around.
If you change the password all masterkeys are re-encrypted with the new SHA-1 hash, but as insurance (the process might get interrupted, e.g.) the old SHA-1 hash is also stored, encrypted with the new SHA-1 hash (and the old and new password GUID) (in a file named CREDHIST close to the master keys), to ensure all blobs are always decryptable with the current password, directly or indirectly. You can find password hashes of all your old passwords this way, if you know the current one, by chaining back. All of these password protections in masterkeys and CREDHIST also use the S-ID of the user (so if this would change, e.g. after a reinstallation of Windows, you could no longer decrypt old blobs.).
Note that if you manually change a local user's password, you will get the following warning, and any data that was encrypted using ProtectedData with DataProtectionScope.CurrentUser of that user, will be lost/unaccessable, just like the warning says:

C# Most secure way to load a password into Process method with a service

I have a C# service that needs to run a process as another user (interactive mode). That user is an admin level user and I know I should NOT store the password as a string in the code.
I could use some help pointing me in the right direction as all the research I have done seems point to a ton of methods that all do not seem to fit with what I want to do.
Am I required to store a hashed PW in a config file? Can I store a hashed PW right in the code and someone pass that to a secure string? I feel a bit lost here and could use some guidance.
If I understood the problem correctly, you need the plaintext password, so you can start the external process as another user. This would rule out password hashes, since you need the plaintext password.
1) Probably the safest thing you can do, is to ask for the password whenever the service starts. The service can then hold the password in memory as long as the service is up.
This way you don't have to store the password at all on the harddisk.
The disadvantage is of course that the password must be entered when the service starts.
2) If you need to persist the password, there is no absolute safe way, but Windows offers an Api for exactly this problem, the Data Protection API (DPAPI). It solves the problem, that one cannot encrypt a password, without storing the key somewhere (which raises the question of where to store the key...).
using System.Security.Cryptography;
byte[] passwordBytes = Encoding.UTF8.GetBytes(plaintextPassword);
byte[] encryptedPassword = ProtectedData.Protect(passwordBytes, optionalEntropy, DataProtectionScope.LocalMachine);
With this code, Windows will encrypt the password using information of the running computer. Only your process running on this computer should be able to decrypt the password then.

Best Practice for Storing and Updating External API Passwords

I have a ASP.Net C# application that needs to connect to an external API using WebServices every 5 minutes.
The requirements of the External Webservice are as follows:
Username and Password are required
I must transmit the username and password with each webservice request
Passwords expire every 90 days and must be changed prior to the expiration date
Passwords cannot be changed manually (by human), my application must connect to a separate Password Change Webservice to change the password.
My application must generate each new password based on a set of rules.
Passwords can never be reused.
SSL, Certificates and Firewall IP restrictions are required
I have built all of the previous, but I currently have one issue. What is the best practice for storing the current and historical passwords?
Obviously storing the plaintext password is a bad solution. I need to be able to have my webservice read the password and transmit it with each request. I also need to be able to access all of the historical passwords to make sure that my newly generated password is not a duplicate.
Ideally, I would like to store each (encrypted) password in my database and decrypt it whenever I need to call the webservice. Is there a best practice I should be following? Should I encrypt each password using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Cryptographer.EncryptSymmetric(..)?
Note: Unfortunately, I have no access to change the way the external API functions. I must follow the rules provided.
With regard to the password history I would go down one of two routes:
As per your current plan, store passwords in file/db/config - suggest you use a hashing algorithm (as opposed to encryption) to compare the new password with stored password hashes for "equality".
Don't bother storing password history at all - let the first attempt to the password change web service just fail if it chooses too, then resend with an alternative password. This way, you are not duplicating the business rules of the password change web service (for example, lets say they change it to allow you to re-use a password after 6 months time).
With regard to storing the current password: assuming you must send the password as plaintext, then yes, you should store it in encrypted form. There are many articles out there on how to do this. Or you could even encrypt a specific section of your config file such as seen here.
The easiest way... use the ProtectedData class:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(password);
byte[] cypher = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
//... reverse
byte[] bytes = ProtectedData.Unprotect(cypher, null, DataProtectionScope.CurrentUser);
string password = System.Text.Encoding.UTF8.GetString(bytes);
The ASP.NET IIS Registration Tool (Aspnet_regiis.exe) can encrypt and decrypt sections of web.config. There is no special code required in an application, as ASP.NET 2.0 will magically decrypt sections at runtime.
http://msdn2.microsoft.com/en-us/library/zhhddkxy.aspx

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.

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