Optimum tempory password length for SHA hash - c#

When creating a "forgotten password" mechanism, we might want to create a tempory password for the user which is stored using SHA1 (feel free to suggest other C# Cryptography mechanism).
How long should we make the tempory password? Too short, it could be brute forced. Too long and the unnecessary length is redundant since the string is hashed anyway? (Since a 20 character and 50 character string results in a hash of the same length anyway)
Update
Sorry if this was misleading. Sure we can pick a number out of the air, but I was wondering if there was a good mathematical reason to pick 13 rather than 12.

I think this is good advice regarding temp passwords:
The definitive guide to form-based website authentication
It talks about avoiding generating them in favour of getting to the real action the user wants.

I generally go with 10 characters. No particular reason for that, just something that I'd guess is above average length for a password chosen by a user.
Just by the fact that it's randomly generated, it'll probably be more secure and more difficult to brute force than anything chosen by your users. People pick stupid passwords such as myspace1, stackoverflow1, 12341234 etc.

If the password is in alphanumeric characters you only have about 6 bits of usable data per character and therefore you're wrong that there's no sense making a password longer than 20 characters.

It seems like you are worried about making the temporary password stronger than the user's password... when in reality, something like a 10-character base-64 (or similar - punctuation etc) is going to be very hard to crack and much stronger than the password the user will generate....

Make it a variable size as well (say 8-12 character) that will make it harder to brute force... if the attacker know you return an X character password all they have to do is try all passwords with N... assuming N is large it'll be impractical, but varying the size of N will at least make it that much harder for them.

Steve Gibson has created a "Ultra High Security Password Generator".
On that page he generates 3 different passwords on every page display:
64 random hexadecimal characters (0-9 and A-F)
63 random printable ASCII characters
63 random alpha-numeric characters (a-z, A-Z, 0-9)
He also explains the reasons behind this. It's a nice read. Hope this helps.

Go for whatever length your site specifies as recommended for the users. When generating a random string of base64 chars, I would sleep safely at night with 8-char password. But of course I'd limit login attempts to once every X second, and temporarily disable account after Y failed tries.
And remember to add a per-user unique salt before hashing, to thwart database-based attacks.

Related

Generate password based on string in 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.

algorithm-shorten +10 digits string

I'm using C# language for a project. I need to provide user with large (9+ digit) number, which they will have to reenter into another system (for later data correlation). Having a user enter a number that large (by hand) with no errors will be almost impossible.
I have been trying to come up with a solution to shorten that number using base64, but all the code I have found will create a string combination of character and digits. Is there a simple math algorithm I can use to make a large number smaller? The result should be numeric not alpha numeric.
You address the problem in a wrong way, instead of changing the number size just build a convenient way for the user to copy past the number , a simple key event wich will copy the number to the buffer, then the user will not have to write the number down.
Reducing a number using only numbers will never work.
What you really need is some form of error checking.
One that works very good is the Verhoeff Algorithm that will detect almost every typo. There are many examples to find online.
like:
https://www.codeproject.com/articles/15939/verhoeff-check-digit-in-c
You can use a Hash algorithm to hash your large number, but you need to deal with hash collision.
One of those very easy to implement is checksum sum16:
https://en.wikipedia.org/wiki/List_of_hash_functions
See sum16 you can only have 0-65536. Think about sum18 ?

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.

Creating a short unique string for each unique long string

I'm trying to create a url shortener system in c# and asp.net mvc. I know about hashtable and I know how to create a redirect system etc. The problem is indexing long urls in database. Some urls may have up to 4000 character length, and it seems it is a bad idea to index this kind of strings. The question is: How can I create a unique short string for each url? for example MD5 can help me? Is MD5 really unique for each string?
NOTE: I see that Gravatar uses MD5 for emails, so if each email address is unique, then its MD5 hashed value is unique. Is it right? Can I use same solution for urls?
You can use MD5 or SHA1 for such purposes as your described.
Hashes aren't completely unique. As example if you have 4000 bytes array, that's mean that you potentially have 256^4000 combinaton. And MD5 has will have 256^16 combination. So, there is a possibility of collisions. However, for all practical purposes (except cryptography), you don't never to worry about collisions.
If you are interested to real about collission vulnerability of MD5 (related to cryptographical use), you can do it here
A perfect hash function is one that guarantees no collisions. Since your application cannot accomodate hash chains, a perfect hash is the way to go.
The hashing approaches already mentioned will work fine for creating unique short strings that will probably uniquely identify your URL's. However, I'd like to propose an alternate approach.
Create a database table with two columns, ID (an integer) and URL (a string). Create a row in the table for each URL you wish to track. Then, refer to each URL by its ID. Make the ID auto-incrementing, this will ensure uniqueness.
This addresses the problem of how to translate from the shortened version to the longer version: simply join on the table in the database. With hashing, this would become a problem because hashing is one-way. The resulting page identifiers will also be shorter than MD5 hashes, and will only contain digits so they will be easy to include in URL query strings, etc.
I think you could try to make from the url string a byte(each char can be a byte) array and then use encoding (Base64 for example, or you can create one yourself if you want to go that far), Then if you want to decode you just use base 64 decoding and make from the bytes (in the array) again chars. However I am not sure or this will be a long string or not, but I am pretty sure it will be unique.
(PS you should ofc apply some logic first like always remove http:// and add it again later when decoding)

Generate serial number using letters and digits

I'm developing an application for taking orders in C# and DevExpress, and I need a function that generates a unique order number. The order number must contain letters and digits and has a length of 20 ..
I've seen things like Guid.NewGuid() but I don't want it to be totally random, nor to be just an auto increment number ..
Can anyone help? even if it's a script in a different language, I need ideas desperately :)
You can create type of your own .
lets say yyyyMMddWWW-YYY-XXXXXXX where WWW is the store number, YYY the cashier id XXXXXXX is a hexadecimal number ( -> maybe an actual autoincrement number that you turn it into hex ) . This is just an idea . Im afraid you have to decide by the elements of your system how it will be .
edited : also if you can apply a check digit algorithm on it will also help in avoiding mistakes
Two different methods:
Create MD5 or SHA1 hash of current time
Hash of increment number
One thought comes to mind.
Take the DateTime.Now.Ticks convert it to hexadecimal string.
Voila, String.Format("{0:X}", value);
If not long enough , you said you need 20 digits, you can always pad with zeros.
Get the mother board ID
Get the hdd ID
Merge it by any way
Add your secret code
Apply MD5
Apply Base54
Result: the serial code which is linked to the currect client PC :)
My two cents.
If you need ideas then take a look at the Luhn and Luhn mod N algorithms.
While these algorithms are not unique code generators, they may give you some ideas on how to generate codes that can be validated (such that you could validate the code for correctness before sending it off to the database).
Like Oded suggested, Guid is not random (well, not if you have a network card). It's based on time and location coordinates. See Raymond Chens blog post for a detailed explanation.
You are best off using an auto incremented int for order ids. I don't understand why you wouldn't want to use it or failing that a Guid?
I can't think of any way other then an auto id to maintain uniqueness and represent the order of your different orders in your system.

Categories