I am reviewing the implementation of a cryptographic challenge-response protocol. The password is used as the key to encrypt a cryptographic nonce (the challenge), and the result is compared with the response.
Currently, the nonce is not really secure as it is obtained with srand() and rand(). All of the ingredients of the random number seed (the current time in seconds (!) and the pid) are quite easy to guess for a man in the middle. This is obviously not good but my question is, how bad is this at preventing replay attacks? Should the challenge be obtained from a CSPRNG (such as /dev/urandom)? Does anybody have any pointers to best practices?
If you worry about the challenge not being random enough and/or being predictable, there is always adding all those you can think up into a (long string) and calculating a one-way hash of that.
So a pseudo random number, time(), the IP address of the connection, the source port number, the username, a long string your challenge generator keeps secret, the pid, ... the more the merrier.
If any of those change, the resulting hash changes dramatically, and given the long string in there ... one would to need guess it or reverse the hash before the challenge becomes predictable.
It also makes for rather unique challenges (you'd need to find a collision in the hash for the challenge to not be unique).
That said, if the odds of the challenge recurring is mitigated (a pseudo random number generator does that IMHO), I think the purpose of the challenge is already met.
What I would worry about a lot in a challenge based authentication scheme is the storage of the secret password on the server. It can be done with salted storage and slow hashes, but many implementations just store the shared secret and that's IMHO a real bad idea.
Reference of an salted challenge response scheme: https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism
If your hash and password are both good, it should not really matter if the challenge is predictable or not. The challenge is public knowledge once it has been submitted. The most important thing is never to repeat the challenge as a response could have been intercepted.
As I see it, a simple incrementing nonce could work here if you could keep it monotonically increasing.
Or perhaps there is some vulnerability here that I don't see?
Related
What is the best one way permutation function I could use to digest an e-mail so I can use it as a primary key without storing personal data?
I'm getting my first F2P game ready: a simple yet (hopefully) addictive 2D casual puzzler based on aiming mechanics. It's made with Unity and will be released on Android very soon.
In order for the player to keep the same data across different devices, I have an SQL table with the device e-mail as the primary key, then another string as the savegame data.
But I don't want to store the user e-mail for privacy reasons.
So I thought of digesting it with some function that would use the original e-mail to generate a new string that:
is unique (will never collide with another string generated from a different e-mail address)
is not decypherable (there should be no way to obtain the original e-mail from the digested string - or at least it should be hard enough)
This way I could still use the Android device e-mail to retrieve the savegame data, without storing personal data from the player.
As far as I've researched, the solution seems to be called a one way permutation function. The problem is that I can't seem to find an appropriate function on the internet; instead, all answers seem to be plagued with solutions for password hashing, which is very interesting (salting, MD5, SHAXXX...) but don't meet my first requirement of no collision.
Thank you in advance for any answer on this topic.
What you need is a cryptographic hash function such as SHA-256. Such functions are designed to be collision resistant, Git uses an older version SHA-1. Most languages/systems have support of this, just Google "Android SHA-256" along with your language of choice.
One option is to append a creation timestamp.
Update: Since SHA-256 does not provide sufficient collision resistance consider s GUID, from RFC 4122: "A UUID is 128 bits long, and can guarantee uniqueness across space and time.". Of course you need to find a good implementation.
I need to decrypt this hashed password: e59dc19f2a3a569417fa183696f91604 and have the salt: 4067. Is it possible to recover the password with this information?
You mentioned the word decrypt in your question, so I wanted to just mention firstly that hashes are not a means encryption. Encryption is a two way process of encryption and decryption. It's a way of securing data in transit or stasis.
Hashes are a one way algorithm and cannot be decrypted. However, there are means of finding out what was hashed. If you do some research into Rainbow tables, you'll see that you simply need to build a list of texts (with a salt, in your case) and their corresponding hash.
Hashes and Encryption are like bread and icecream. You can heat up bread and get toast, but you can't cool down toast to get bread. You can head up icecream to get cream, and you can cool it down again to get your icecream back.
No, hash algorithms are one way.
You can hash the original password again and see if the hash result match the previous one.
There is a way to decrypt this, but it is a long and laborious process. It's referred to as "brute-force", which means you would try a large (and by large, I mean significantly large dependent on the length of the password) number of inputs. Since the hash function is a one-way function that produces a non-random result, you will always map an input to the same output. So by using "brute-force", you're literally trying every possible combination and seeing if the hash produced is equal to the hash stored on the system (since you already know the salt). There are tools that do this such as John the Ripper (available on Kali Linux) but again, dependent on your computational power, it can take awhile.
It is impossible to decrypt it. However, you may be able to crack it using the brute force method to find matching passwords in a dictionary.
Best tool to use would be hashcat.
I tried to decrypt a hash with salt, and it works but only with the same encrypt application or method (I mean with the same exact thing, if u encrypt it on a website, or an app you have to decrypt that on the very same place).
I hope that helps
I was talking to a friend of mine and he stated that to store user passwords in the database, he, and I quote:
Takes a users password
Hashes it with a random salt
Then, he prefixes the result of #2 with the hash type and the salt, joining them with a pipe delimited string. (e.g. SHA1|RANDOMSALT|afde4343....)
Stores result of #3 in the db
He claims that's it readable, as he "can instantly know" what type of hash digest is used.
I don't think I've ever seen this before, but, I'm looking for reasons on why it would be bad aside from the fact than an unauthorized user can instantly know what type of hash is used to encrypt the passwords and the extra space required for storing the field.
My gut reaction is that this approach to working with passwords is silly, as any indication to help an attacker break passwords is a weakness. Any other reasons I should use to convince him that this is a bad idea?
Thanks!
It is a good idea. Everybody does that, including in the /etc/password (/etc/shadow...) file on Unix systems.
Any decent security model will assume that the attacker knows what kind of hash function is used, if only because the hashing system is a piece of software, store on a hard disk. Conversely, believing in the virtue of not announcing which hash function is used is akin to security through obscurity and that's bad.
So do not try to convince your friend that what he is doing is bad. Instead, let him convince you that what he is doing is good.
PS: this is not password encryption, this is password hashing. Hashing is not a kind of encryption.
It's also good practice to store the hash "cost" (number of times the hash has been stretched), even crypt() does that. Possibly, the worst issue is that you first have to query the database (to know the salt, cost, algorithm) and then check against your generated hash, this requires an extra trip to the DB.
Why is this a good practice? Well, if you have user-specific salts, they have to be stored somewhere... Also, you may (in the future) want to escalate the cost (number of times a hash is "re-hashed") of your hashes to keep up with Moore's Law, if you don't know the original cost you wont be able to do anything.
I strongly recommend that you read this blog post about (secure) password hashing.
I'm working on a multi-tenant application that will be implementing service APIs. I don't want to expose the default auto increment key for security reasons and data migration/replication concerns so I'm looking at alternative keys. GUID/UUID is an obvious choice but they make the URL a bit long and while reading an article about them I saw that Google uses "truncated SHA1" for their URL IDs.
How does this work? It's my understanding that you hash part/all of the object contents to come up with the key. My objects can change over time so hashing the whole object wouldn't work since the key will need to remain the same over time. Could I implement UUIDs and hash those? What limitations/issues are there in using SHA1 for keys (e.g. max records, collision, etc.)?
I've been searching Google but haven't come up with the right search query.
/* edit: more information about environment */
Currently we are a Java shop using Spring/Hibernate with MySQL in back. We are in process to switch core development to Grails which is where this idea will be implemented.
I thought about a similar problem some time ago and ended up implementing Blowfish in the URL. It's not super safe but gives much shorter URLs than for instance SHA256 and also it's completely collision free.
That's actually a pretty solid idea, though it might make key lookups a little tough (unless you hashed the key and kept it inline in the table, I suppose). You'd just have to hash every key you use, though if you're auto-incrementing, that's no problem. You wouldn't even need a GUID - you could even just hash the key, since it's a one-way operation and can't be easily reversed. You could even "salt" your key before you hash it, which would make it virtually unbreakable by making the key unpredictable.
There is a concern about collision, but with SHA1, your hash is 160 bits, or has 1.46 × 10^48 unique values, which should be enough to support some fraction of that many unique keys without worrying about a collision. If you've got enough keys that you're still worried about a collision, you can upgrade to something like SHA256 or even SHA512, which should be plenty long as to avoid any reasonable concern about a collision.
If you need some hashing code, post the language you're using and I can find some, though there's plenty available online if you know what you're looking for.
What is your preferred method/datatype for storing passwords in a database (preferably SQL Server 2005). The way I have been doing it in several of our applications is to first use the .NET encryption libraries and then store them in the database as binary(16). Is this the preferred method or should I be using a different datatype or allocating more space than 16?
I store the salted hash equivalent of the password in the database and never the password itself, then always compare the hash to the generated one of what the user passed in.
It's too dangerous to ever store the literal password data anywhere. This makes recovery impossible, but when someone forgets or loses a password you can run through some checks and create a new password.
THE preferred method: never store passwords in your DB. Only hashes thereof. Add salt to taste.
I do the same thing you've described, except it is stored as a String. I Base64 encode the encrypted binary value. The amount of space to allocate depends on the encryption algorithm/cipher strength.
I think you are doing it right (given that you use a Salt).
store the hash of the salted-password, such as bcrypt(nounce+pwd). You may prefer bcrypt over SHA1 or MD5 because it can be tuned to be CPU-intensive, therefore making a brute force attack way longer.
add a captcha to the login form after a few login errors (to avoid brute-force attacks)
if your application has a "forgot my password" link, make sure it does not send the new password by email, but instead it should send a link to a (secured) page allowing the user to define a new password (possibly only after confirmation of some personal information, such as the user's birth date, for example). Also, if your application allows the user to define a new password, make sure you require the user to confirm the current password.
and obviously, secure the login form (typically with HTTPS) and the servers themselves
With these measures, your user's passwords will be fairly well protected against:
=> offline dictionary attacks
=> live dictionary attacks
=> denial of service attacks
=> all sorts of attacks!
Since the result of a hash function is a series of byte in the range 0 to 255 (or -128 to 127, depending the signed-ness of your 8-bit data type), storing it as a raw binary field makes the most sense, as it is the most compact representation and requires no additional encoding and decoding steps.
Some databases or drivers don't have great support for binary data types, or sometimes developers just aren't familiar enough with them to feel comfortable. In that case, using a binary-to-text encoding like Base-64 or Base-85, and storing the resulting text in a character field is acceptable.
The size of the field necessary is determined by the hash function that you use. MD5 always outputs 16 bytes, SHA-1 always outputs 20 bytes. Once you select a hash function, you are usually stuck with it, as changing requires a reset of all existing passwords. So, using a variable-size field doesn't buy you anything.
Regarding the "best" way to perform the hashing, I've tried to provide many answers to other SO questions on that topic:
Encrypting passwords
Encrypting passwords
Encrypting passwords in .NET
Salt
Salt: Secret or public?
Hash iterations
I use the sha hash of the username, a guid in the web config, and the password, stored as a varchar(40). If they want to brute force / dictionary they'll need to hack the web server for the guid as well. The username breaks creating a rainbow table across the whole database if they do find the password. If a user wants to change their username, I just reset the password at the same time.
System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
username.ToLower().Trim(),
ConfigurationManager.AppSettings("salt"),
password
);
A simple hash of the password, or even (salt + password) is not generally adequate.
see:
http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/
and
http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords
Both recommend the bcrypt algorithms. Free implementations can be found online for most popular languages.
You can use multiple hashes in your database, it just requires a little bit of extra effort. It's well worth it though if you think there's the remotest chance you'll need to support additional formats in the future. I'll often use password entries like
{hashId}${salt}${hashed password}
where "hashId" is just some number I use internally to recognize that, e.g., I'm using SHA1 with a specific hash pattern; "salt" is a base64-encoded random salt; and "hashed password" is a base64-encoded hash. If you need to migrate hashes you can intercept people with an old password format and make them change their password the next time they log in.
As others have mentioned you want to be careful with your hashes since it's easy to do something that's not really secure, e.g., H(salt,password) is far weaker than H(password,salt), but at the same time you want to balance the effort put into this with the value of the site content. I'll often use H(H(password,salt),password).
Finally, the cost of using base64-encoded passwords is modest when compared to the benefits of being able to use various tools that expect text data. Yeah, they should be more flexible, but are you ready to tell your boss that he can't use his favorite third party tool because you want to save a few bytes per record? :-)
Edited to add one other comment: if I suggested deliberately using an algorithm that burned even a 1/10th of a second hashing each password I would be lucky to just be laughed out of my boss's office. (Not so lucky? He would jot something down to discuss at my next annual review.) Burning that time isn't a problem when you have dozens, or even hundreds, of users. If you're pushing 100k users you'll usually have multiple people logging in at the same time. You need something fast and strong, not slow and strong. The "but what about the credit card information?" is disingenuous at best since stored credit card information shouldn't be anywhere near your regular database, and would be encrypted by the application anyway, not individual users.
If you are working with ASP.Net you can use the built in membership API.
It supports many types of storage options, inlcuding; one way hash, two way encryption, md5 + salt. http://www.asp.net/learn/security for more info.
If you dont need anything too fancy, this is great for websites.
If you are not using ASP.Net here is a good link to a few articles from 4guys and codeproject
https://web.archive.org/web/20210519000117/http://aspnet.4guysfromrolla.com/articles/081705-1.aspx
https://web.archive.org/web/20210510025422/http://aspnet.4guysfromrolla.com/articles/103002-1.aspx
http://www.codeproject.com/KB/security/SimpleEncryption.aspx
Since your question is about storage method & size I will address that.
Storage type can be either binary or text representation (base64 is the most common). Binary is smaller but I find working with text easier. If you are doing per user salting (different salt per password) then it is easier to store salt+hash as a single combined string.
The size is hash algorithm dependent. The output of MD5 is always 16 bytes, SHA1 is always 20 bytes. SHA-256 & SHA-512 are 32 & 64 bytes respectively. If you are using text encoding you will need slightly more storage depending on the encoding method. I tend to use Base64 because storage is relatively cheap. Base64 is going to require roughly 33% larger field.
If you have per user salting you will need space for the hash also. Putting it all together 64bit salt + SHA1 hash (160 bit) base64 encoded takes 40 characters so I store it as char(40).
Lastly if you want to do it right you shouldn't be using a single hash but a key derivation function like RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single threaded application can hash about 30K to 50K passwords per second thats up to 200K passwords per second on quad core machine. GPUs can hash 100x to 1000x as many passwords per second.With speeds like that brute force attacking becomes an acceptable intrusion method. RBKDF2 allows you to specify the number of iterations to fine tune how "slow" your hashing is. The point isn' to bring the system to its knees but to pick a number of iterations so that you cap upper limit on hash throughput (say 500 hashes per second). A future proof method would be to include the number of iterations in the password field (iterations + salt + hash). This would allow increasing iterations in the future to keep pace with more powerful processors. To be even more flexible use varchar to allow potentially larger/alternative hashes in the future.
The .Net implementation is RFC2892DeriveBytes
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx