Generate password based on string in C# - c#

I'd like to generate (secure) local admin passwords based on computer names in our organisation. This way I can build a small UI that takes the computername and gives the password.
With PowerShell we will use the same DLL to generate the password and set it on each workstation.
I've already searched, but all the things I find about cryptography in C# is to hash a password, but I need the hash itself to be the password.
The password should also be of a length between 8 and 12 characters to make it easy enough to type it in.
I'm using .NET Core 2.0 (could use .NET Framework too if needed)

You definitely want to be able to change the passwords on your machines, so include some sort of date or counter in the formula.
You ideally also want to include some form of authentication into the tool, whether that be a master password, a complicated thing with smartcards, or something else. That way when your tool gets into the hands of a baddie they don't necessarily get all your data.
If you go the master password route, you need a plan for how to deal with suspecting that got leaked. (Including someone who knew it leaving the organization, since that's a leak.)
A strawman example which includes:
Using a date
Using a master password
Using HMAC to process the machine name, keyed by a key from the master password
An iteration count to PBKDF2 which matches modern computers.
.
private static string GeneratePassword(
string masterPassword,
string machineName,
DateTimeOffset lastChangeDate)
{
// Use the date (ignoring time) of the last password change as a salt.
byte[] salt = BitConverter.GetBytes(lastChangeDate.ToUniversalTime().Date.Ticks);
HashAlgorithmName prf = HashAlgorithmName.SHA256;
using (var pbkdf2 = new Rfc2898DeriveBytes(masterPassword, salt, 123456, prf))
{
byte[] key = pbkdf2.GetBytes(256 / 8);
using (HMAC hmac = new HMACSHA256(key))
{
byte[] value = hmac.ComputeHash(
Encoding.UTF8.GetBytes(machineName.ToUpperInvariant()));
// Or however long.
return Convert.ToBase64String(value).Substring(0, 16);
}
}
}
The Rfc2898DeriveBytes constructor overload which takes a HashAlgorithmName for the PBKDF2-PRF is new in netcoreapp20. If you are trying to be netstandard20 you can drop the last parameter and use the SHA-1-based version with probably little harm (since HMACSHA-1 isn't currently considered broken).
When going to change a password for a machine you'd enter the date of the last generation to get the existing one. Then enter today's date to get the new value, then write down the new date in whatever text file / spreadsheet / database / sticky note remembers these things.
Another alternative is generating random passwords and saving them in an encrypted structured file. Something like EnvelopedCms as the encryption container gives you smartcard for nearly free, and lets you add/remove readers without changing all the machine passwords (adding is easy, removing might warrant changing them all anyways).
Which is to say: Building a stable generator and deploying the usage is easy. It's maintaining it that gets tricky. Maintaining random might be easier, therefore it's possibly better to pay the cost up front.

I don't know if this is such a good idea - the tool only works as long as the passwords on each and every computer stay unchanged.
Anyway, you could hash the computer name and use the result as a password. Most if not all hashes produce larger hashes than 8-12 "easy enough to type in" characters, but you can solve that by:
Base64 encoding the hash (to get letters, numbers and a couple of other characters)
Take the desired number of characters from the result.
To make this a bit safer, let your UI take a password (a single one) and append it to the computer name before computing the hash. This way, when someone steals your tool, they still won't be able to generate valid passwords.
You won't ever be able to change that password, though. If you share it with a coworker, they will know how to reproduce every password, forever.

Related

How can I check that password is correct if I add random salt?

I'm trying to secure my c# app. I know that we MUST store password hash and salt in DB. So my question: How I can compare that password is correct if I use Random salt? (Random salt gives random values each time).
I also have the code below
public static string HashPassword(string p, string s)
{
var combinedPassword = String.Concat(p, s);
var sha256 = new SHA512Managed();
var bytes = UTF8Encoding.UTF8.GetBytes(combinedPassword);
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public static String GetRandomSalt()
{
var random = new RNGCryptoServiceProvider();
var salt = new Byte[1024];
random.GetBytes(salt);
return Convert.ToBase64String(salt);
}
I am open to other suggestions in general.
I am open to other suggestions in general.
I will preface this post by making a broad point but I believe it is widely enough held to not constitute an "opinion".
If you are doing this "to secure your app", stop now. There are much better solutions like BCrypt, Scrypt and Argon which take care of all this for you and protect against threats that most people haven't even considered. These of course include salt(s) internally, so understanding what they are for and how they work is still a useful endeavour. For approximately the same amount of code, you will be handling the credentials a lot more securely than the posted code indicates. Google them for details.
If you are just doing this as "an exercise to understand how it all works", continue reading.
So what is salt exactly and why is it useful for protecting security?
Salt is additional entropy that is not part of the user's password, but is instead known to or invented by the server at the time the password is hashed and stored. The generated salt must be known to the server when validating your password. There are many ways it can be stored. It may be the first/last/middle/every8th/whatever n characters of the password hash stored in the database. It may have its own separate field. It may even be based on other facts immutable like Primary Keys of the user record itself.
The threat model that this protects against could be described like this. Consider a database that was compromised and now held by a malicious actor. The challenge is, given the malicious actor holds the credentials (in hashed form), can we stop them from guessing people's password (at least without trying some sort of dictionary or brute force guess attack.
If you thought hashing solved that problem, then I will give two possible scenarios:
1. Two users may use the same password
If the password is hashed but not salted, then two users who choose the same password will end up with the same hash. And even if the password isn't "terrible", the other user may reveal your password by whatever they entered as the "Password Hint". If the passwords were salted, then the fact that the password hint gave away the other user's password doesn't leak the fact that the same password would work on your account.
2. Rainbow tables
If you have enough time and compute power, you can generate (or download) a set of rainbow tables. These are basically key-value pairs, where the key is the hash and the value is the original password. These are generated in reverse. That is to say, take a string, hash it, add the hash as the key and the original string as the target. To lookup, you simply lookup the hash key and see what value comes back. Near instantly. With a long enough original string though, it won't have been pre-computed so it won't have a hit in the rainbow table. If I know the salt you are using and the hashing algorithm, I can still do my own dictionary attack or brute force attack, but suddenly I am required to try each guess in turn until I am lucky, so if your password is good, I will not find it in "reasonable time".
The precise answer to your posed question
How I can compare that password is correct if I use Random salt?
Your verification process needs to know or derive exactly what exact salt value was chosen for the hash process. The salt may be randomly generated, but if so it needs to record the exact value used.
First , you have to get salt in database by username , then hash it with posted password , finally compare it to password stored in database

Rehashing a hash (SHA512)

We are following a pretty standard user id / password check. We store the hashed password in the db. When the user enters credentials we hash the entered password then compare to what the db has. If they match then user is authenticated.
Now this login process under load test is slowing down considerably so I was asked to look at it. VS 2013 Profiler pointed out the hashing method as a hot path. Looking at the method in question we are looping over the hashing process??
private const int totalHashCount = 1723;
public string CreateHash(string salt, string password, int securityIndex)
{
string hashedPass = this.GenerateHashString(salt + password, securityIndex);
for (int i = 1; i <= totalHashCount; i++)
{
hashedPass = this.GenerateHashString(hashedPass, securityIndex);
}
return hashedPass;
}
I went to the developer and he stated the client's security team wanted us to rehash the hash and to do it some prime number greater than 1000....and he provided the email as documentation.
Now I am not a cryptology expert and we have a good relationship with the client so before I went to them and connected this rehash loop to their performance woes I wanted to see if rehashing like this does indeed increase security?
To my understanding a single hash is practically impossible to invert so why waste cycles repeating the process?
Thoughts?
Edit
Added GenerateHash:
protected internal string GenerateHashString(string textToHash, int securityIndex = 0)
{
UnicodeEncoding uEncode = new UnicodeEncoding();
SHA512Managed sha = new SHA512Managed();
byte[] bytVal = uEncode.GetBytes(textToHash + hashIntPool[securityIndex].ToString());
byte[] hashVal = sha.ComputeHash(bytVal);
return Convert.ToBase64String(hashVal);
}
Repeating the hash operation is essential to secure password authentication, but you are doing it wrong and therefore indeed wasting CPU to achieve nothing.
You should use an algorithm like PBKDF2 that includes the password in each round of hashing in order to preserve all the unpredictability of the password. bcrypt and especially scrypt are good alternatives too.
Also, one thousand rounds is not nearly enough; to be secure against offline dictionary attacks, you need the hashing operation to be relatively slow, even when performed on the attacker's dedicated password testing hardware. Picking a prime number of rounds is meaningless mumbo jumbo. The number of rounds will depend on the algorithm you select, but for PBKDF2 with SHA-256, somewhere between 10,000 and 100,000 rounds should provide a reasonable level of security.
A slow algorithm is necessary to prevent an attacker who obtains a hash from quickly trying many different passwords to see which produces the same hash. It's true that a secure hash is not feasible to invert, but it won't stop guessing, and attackers are good at prioritizing their guesses to try the most likely passwords first. Repetition of the hash is what provides this necessary slowness.
This has been discussed many times on StackOverflow. I refer you to a previous answer for more background.
In C#, you could use Rfc2898DeriveBytes to perform password hashing securely. You can encode the derived key in Base-64 to be stored as a string, or actually use it as an encryption key to encrypt a known plain text like the bcrypt algorithm does. You'll notice that Rfc2898DeriveBytes uses a "salt", which I discuss elsewhere; you'll need to store this value along with the hash value to perform authentication later.
The technique, called "stretching", of repeated hashing is used to make brute force attacks more difficult. If it takes 0.1 second to hash a password (due to the repetitions) then an attacker can at best try 10 passwords a second to find a match. If you speed up the hashing process so it takes a microsecond, then the attacker can test a million passwords a second.
You need to balance speed against security. A user login only need to be fast enough to satisfy the user, so 0.1 to 0.5 second is probably acceptable.
If your server is overloaded then get a faster processor, or buy a dedicated hashing server. That will be a lot cheaper than the legal consequences of a data breach.

How to save a password properly

I attemt to write a program, with which you can login to a remote website. For some people having multiple accounts, I try to make it easy for them and store account data in IsolatedStorage. At the current state of my code, the password is just entered in a TextBox and as soon as it's stored converted to a MD5 hash.
Now I'd like to refactor this to proper code, but I got stuck.
A PasswordBox exposes its data through PasswordBox.SecureString and PasswordBox.Password.
So when clicking my save button I'd perform something like
public void OnClick(...)
{
var password = passwordBox.Password;
// store it somehow (e.g. custom MD5 encryption)
var savePassword = passwordBox.SecureString;
// store this string somehow, but how?
}
Here my questions
As soon as I put the plain password from my PasswordBox into var password, is there something visible in memory? Would some hacker be able to make this plain value visible through reflection/debugging? Which code makes these strings actually visible? And what do I need to be aware of?
How to handle SecureString of the PasswordBox?
I'm a bit overwhelmed by all this stuff and I can't figure out the essence of how to handle passwords in an application properly, yet.
I'm not pleading for a whole solution and running code. I'd just be glad, if someone can get me started. And also, I don't want an enterprise solution. I'm just searching for one, which is easy to implement and as save as possible for the effort I put in.
Do you really need the password to be reversible?
A safer way to store it is to salt and hash it.
User: JOHN
Password: (starts out as) myUserPassword667!
Then use some sort of database unique code against the user in the DB. Lets say a GUID.
Now you have abcd-1234-12-1212121ab as the uniquifier for JOHN
so you now have a base password(before hashing)
myUserPassword667!abcd-1234-12-1212121ab
You can now Hash this with one of the SHA or other hashing algorithms in the System.Security namespace.
Now you internally have some Salt that you Apply to your hashing algorithm... (Part of your code only)
MySecretSaltWords559BC
then store the Result as either a Base64 or Binary in your DB.
Ab09l\311sas== (simplified)
Next time the user logs on you find their record in the DB, you get your Unique code that was used when you generated the account and attach to the password they entered.
Hash the entered password with the same technique and binary compare the result, then you don't need to ever store their password. If the hashes don't match you don't have the same password.

BCrypt generating different hashes given the same salt, string, and factor

Using one of the C# implementations of BCrypt to hash passwords and store them into a SQL database. However when I return to validate against the hash string BCrypt generates a different hash than the one in the database to compare to. The salts are visibly the same as well as the factors.
Here is what I know
$2a$12$vF/1s3MqIzHwnDshyzH/rOYUelofrj4UWv./vzWqk4o2K0uwhix7W is actually "Qwerty123" and its stored in a column which is initialized to be [nvarchar] (200).
When I use the BCrypt.Verify() or BCrypt.CheckPassword() depending on the implementation, I trace it until just before it makes the comparison and the hash that it is about to compare to the before mentioned one is $2a$12$vF/1s3MqIzHwnDshyzH/rOKVRePZSXFXaIpDv6.IPkbPEoOxZgSEe
If you look close you can see that the salts and the factor parts are the same. Any idea what could be causing this?
The explicit implementation I am working with can be found here http://bcrypt.codeplex.com/
My question could be related to ASP.NET MVC 3 app, BCrypt.CheckPassword failing
Suggestion for testing
private void FindWhatsFailing(string password) //password = Whatever you're passing in to verify BCrypt is working
{
const string expectedpassword = "Qwerty123";
if(expectedpassword != password)
{
Debug.WriteLine("My password isn't what I thought it was");
return;
}
string hashed = BCrypt.HashPassword(expectedpassword , BCrypt.GenerateSalt(12));
if(!BCrypt.Verify(expectedpassword , hashed))
{
Debug.WriteLine("Something is wrong with BCrypt");
return;
}
/// ... Test hashing password, compare to hash of expectedpassword, verify password against hash of itself and expectedpassword
Debug.WriteLine("Everything worked, maybe the database storage is off?");
}
If the Bcrypt.Verify isn't working in this example for you, I have no idea what's wrong, but I'm guessing Bcrypt isn't actually the issue here.
The problem was the input to Bcrypt. I was using a Multiview and MultiViewPanels to collect user data(of which a password), allow user to verify all the data, then on the last MultiViewPanel add the user to the DB and in that process there were postbacks. After some research I found that password fields do not retain their text property after postbacks for security reasons and because I was passing txtPassword.text to Bcrypt this was the problem. This makes a new problem for me to look into.

Password encryption

I am creating a login screen for an application in C#. In my login screen I am reading the username and password from the database and checking whether the entered username and password are correct or not. I need the password to encrypt while I am reading the password form the database. Can anyone explain how encryption and decryption works.
Whether I have to store the encrypted value in the database for reading.
Right now I have two fields
column names: username password
values: admin password
Should I store the encrypted value of the password in another field in the login table?
First: The common approach now is that store the salted hash of the password, instead of the plain-text password itself (SHA-1 and better hashing algorithm are preferred, avoid MD5 because it's not safe any more) . When the user login, you recalculate the hash of the input string, then compare it with string stored in the database.
EDIT: why shouldn't you use encryption for password? Because when the attacker knows the key of encryption, all of you passwords will be exposed (That's very bad). If you using hash, he just can guess one-by-one (and this is not easy). Otherwise, hash algorithms, in general, are faster then encryption, you'll take the performance benefit.
EDIT: why you should store salted hash, instead of a hash? Because hashing algorithms are guaranteed that if you hash identical strings, the result is the same. This may lead to a problem is that, when attacker see the same hash values, he can guess that the texts were the same, and this gives chance for him to get the original password.
Salt means that besides the original text, you put some random text, and therefore, two identical strings will generate different hash values
Take a look at this: http://www.obviex.com/samples/hash.aspx
In case of the user forgets his password, you can use the reset password function, which many sites are using:
The user requests a password reset
An email contains a special link (include a secret token/PIN) will be sent to registered email address, that allows user to reset his password.
A randomly created password will be sent again to user, then he can login and change his password.
UPDATE May 14th 2012: The answer seems to be old, and not completely true. People are moving to more secure hashing-encryption algorithm for storing password. One of notable solution now is bcrypt, and another (new and promising) is scrypt.
The advantage of these encryption? They're slow! Much slower than hashing algorithm. With the power of GPU (for example, CUDA from nVidia), cracking the hash value is not impossible now, and the slowness can make it much harder to crack these encryption.
You can find more about bcrypt at: http://codahale.com/how-to-safely-store-a-password/
Second: You should separate the users table (contains user profiles, such as full name, DoB, address,...) and logins table (Which contains user name and password, and some special attributes). This will lead to better management and reduce the risk of exposing sensitive information
Along with given advices, there are other methods to protect passwords:
One-Time Password: In spite of
implementing salted hash, passwords
are still stored on hard disk and
are prone to be cracked. So a better
approach is required here. In
contrast with static passwords,
one-time passwords are changed each
time a user logs on to the system
and usually users should carry a
small hardware used for
synchronizing with server. Mainly
there are two types of OTP: (Visit Safer Authentication with a One-Time Password)
Time-Synchronized
Counter-Synchronized
Using BCrypt which uses a variant of the Blowfish encryption algorithm's keying schedule and contains a work factor, which lets you determine how expensive the hash function will be. In order to get familiar with bCrypt, visit: http://codahale.com/how-to-safely-store-a-password/
In C#, you can use BCrypt.Net library which is a port of iBCrypt library: read the following article to understand how to get this library up and running in Visual Studio.Net:
Using BCrypt in a .NET Application – Why it’s better than SHA or MD5.
Of course, there are a lot of discussions about this algorithm in SO, search and study more about this.
Are you implementing your own authentication mechanism? You can use already existing System.Web.Security microsoft authentication. By using Membership class you can validate user password without retrieving it from the database. This way you will be able to store the salted (encrypted) password in your database. Just use Membership.CreateUser and Membership.ValidateUser.
If you don't need (performance wise or proprietary implementation) use existing implementations and save time.
The password should be stored in database with encrypted value itself. And when user tries to login, encrypt the password with the same algorithm and then compare it to the value in db.
Md5 is usually used for password encryption as it cannot be decrypted. Incase the user forgets the password, he cannot retrive it back, but it can only be reset.
Hope this helps !
You can encrypt the passwords in many ways.
One of the way is using the MD5 encryption. Let me show you one of the encryption method that I am using.
#region Encrypt
public string Encrypt(string simpletext, string keys)
{
try
{
XCryptEngine xe = new XCryptEngine();
xe.Algorithm = XCrypt.XCryptEngine.AlgorithmType.DES; //DES = Data Encryption Standard
string cipher = xe.Encrypt(simpletext, keys);
if (cipher != null)
return (cipher);
else
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region Decrypt
public string Decrypt(string simpletext, string keys)
{
try
{
XCryptEngine xe = new XCryptEngine();
xe.Algorithm = XCrypt.XCryptEngine.AlgorithmType.DES;
//Console.WriteLine(xe.Decrypt(simpletext, keys));
simpletext = simpletext.Replace(" ", "+");
string cipertext = xe.Decrypt(simpletext, keys);
if (cipertext != null)
return (cipertext);
else
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
you need to use reference for XCrypt to use this.
using XCrypt;

Categories