I'm developing a mobile application and in my lay research of the argon2 password hashing algorithm, it seems that (ignoring the key and salt) there are three main parameters:
iterations
memory
parallelism
While it obviously wouldn't make sense to broadcast these, as far as I see it these will unavoidably need to be compiled within the mobile application and a bad actor could figure out these parameters by decompiling the mobile application.
How protective do I need to be of these parameters?
If these parameters need to be protected, how can I obfuscate these parameters or mitigate the threat to a compiled application? Or, alternatively, can these parameters somehow be distributed by a means other than compiled within the mobile app?
You should not be at all protective of your default Argon2 parameters.
Instead, you should be proud of them.
You should choose parameters that maximize resistance to offline brute-force attack if the hashes are leaked. You should be confident enough in the math behind selecting them to post them publicly, as per Kerckhoffs' Principle.
There is no need to protect those parameters, the security does not depend on them to be secret.
Even more you need them to verify a user entered password, so it is necessary to store them along with the stored password hash (usually they become part of the password-hash). Storing the parameters together with each hashed password allows to adapt the parameters in future (for faster hardware), and still be able to verify older passwords, which where hashed with lower parameters.
Related
The first & accepted answer on this question about passwords management suggests to encrypt the user identifiers in DB.
The good point is that if anyone gets a password, he has to know how to decrypt the user login to get the full login/password pair.
Some disadvantages I see, for example:
you have to decrypt user logins every time you want to display them
if you want to do a 'begins with' search on user login to find users, you cannot simply use LIKE '...%'
ORDER BY on login field may be quite difficult too...
What would you recommend (encrypt user identifiers or not)?
As usual, the answer is "it depends".
In general, I'd say that if an attacker has access to your database, your security situation is so badly compromised that encrypting the passwords will likely do you no favours. This is different to using a one-way hash - it's likely that an attacker who has access to your database also has access to your decryption key, whereas one-way hashes, by definition, are one way.
As you already say, it's likely that you will need regular access to the userIDs (esp. if you use email addresses as user IDs); in that case, again, an attacker who can read your database likely can intercept the unencrypted data.
So, if you work for a bank, the government, or any other place where data security has to be at the very top of the list, this additional protection may just be worth it, especially if you have a strong key management system.
For other uses, I'd consider the additional security too small to merit the additional pain.
Encryption is considered to be a lesser form of secret storage than message digest functions. In fact, storing an encrypted password is a clear violation of CWE-257.
But why not hash the username? When the login the application will have the plain text. Depending on your application, you might not need to display a list of users. this would be an added layer of security, as both hashes have to be broken before the attacker can login.
That being said, if you have a plain text list of every username it will be trivial to perform a dictionary attack against any recovered hash. Further more user names are not created to be difficult to guess, often times users choose goofy names of birds or silly games like chess so that they are easy to remember.
I am an integration consultant and tend to use C and Lua in my spare time, unfortunately it is not my day job ;-(
Anyway, I tend to believe that a mixture of C and Lua is perfect for many "product" developments. I currently have an "adapter engine" built in pure C, but would like to actually move the adapter code to Lua....
For example, coding an EMAIL adapter in Lua is far easier than in C...yet I like the "engine speed of C"....
But now there is the big question of security risk in that the user can potentially add whatever he or she wants to the LUa scripts in production.....obviously there we could CHMOD the files...but is that really secure?
Ideally I want the C / Lua combination here....but now do I literally imbed the Lua code in the C application with a CHAR*....or do I issue a lua_dofile??
Thanks for the help
Lynton
First, one of the drawbacks to using C/Lua in production is it tends to be harder to find resources who can develop for these languages. C++ and JavaScript programmers are typically easier to find.
In terms of security, the key here is to use leading practices. Security is about risk reduction, there is no expectation one can achieve perfect security so you need to mitigate risk.
Here are my suggestions:
As with all middleware you need to use a hardened server. This is the first step, if the server is compromised using any platform you are in trouble. Middleware should NOT be in the DMZ.
You want to store the Lua code external to the compiled code (otherwise you lose the advantage of using Lua.) Make that storage as secure as you can. CHMOD is good, a secure DB server is better. The more secure the script store the more secure the system.
You can encrypt the Lua source - this is a trade off since it makes it a little harder to gain the advantage of easy updates and modification. You will probably need to implement decrypted script caching for performance.
Your security is as strong as your weakest link. If you provide a way to modify the Lua source via external access this will be an attack vector. Avoid this design if you can.
You should consider putting in change management checks. For example a separate place in the system where a checksum for each Lua file is stored. Then if an un-authorized change is made to a script you can abort functioning till the security breach is mitigated.
Other than the drawback I mentioned above, I don't think there is anything fundamentally flawed in your plan. If it can aid in making a good middleware system I would say go for it. Just mitigate the risk of your adapter scripts getting compromised as much as possible.
To expand on Donal's comment - given the popularity of node I would say that JavaScript is the the leading practice in scripted middleware right now. If you can handle learning a new scripting language I would say it would be a good idea given the support, popularity, and tools available.
Your primary requirement in terms of security is to ensure that the server cannot evaluate anything send by clients by any mechanism (not just direct evaluation, but also through supplying filenames). A lesser requirement is that they should also not have any mechanism to produce a message that allows other clients to evaluate unexpected things (i.e., avoid XSS trouble). If you can satisfy these requirements, you've got a safe server and the language(s) that it written in won't matter; using multiple languages is in fact a good idea as it lets you leverage the best of each.
It's also a good idea to use a carefully configured firewall, plenty of privilege restriction, some kind of DMZ proxy system to at least verify basic syntactic legality of messages, etc. These things are all just good practice. (Aim to configure things so the server can only just manage to do the service you want to provide.)
With sending email, there are a few other things to beware of. In particular, you do not want to be a conduit for spam, so you need to take care to ensure that arbitrary email headers cannot be constructed from client input and that the data formats you send out are non-executable (or that the data is constructed in a way that is non-evil). Rate limiting is also a good idea; unless your site is insanely popular, you shouldn't need to send more than a few messages a second across all clients. If you're ever sending only to a small set of addresses (e.g., to a fixed contact address) then you can relax these restrictions a bit (but still be careful of header injection). In all cases, route all email by a specialist email handling server instead of doing routing yourself as this avoids a whole lot of configuration difficulties.
I am currently working on a service which requires users to pick a 4-digit password/pin, because it is a mobile service. I am encrypting those passwords with either 256 or 2048bit encryption and it will be hashed. The account is blocked after 4 wrong entries, and can only be entered by mobile phone. Would it be hard to crack those PINs? I am asking this because sensitive information is being stored. The database is connected to a web application, the application is loaded to the phone using twilio. The thing I am most scared for is that the database is being hacked via the web. What would be a good way to keep sensitive data secure?
If someone gets hold of the database, you would be pretty much screwed:
If you just encrypt the 4-digit passwords, an attacker can just build a table of the 10000 possible encrypted strings and can trivially decrypt the PINs.
If you use salt strings (and encrypt not PIN, but PIN+salt and store crypted(PIN+salt) alongside with salt), people have to make a per-password effort, but there are still only 10000 possibilities for each password (which is not very much).
Which means, yes, by all means you should keep the database off the web. (If the web application is only ever accessed through twilio, you can reject connections from any other IP range).
Since you're using twilio, just make sure that twilo only talks to your web service using a secure protocol and reject any requests that you aren't sure are coming from a trusted source (that is, twilo). No real need for a pin at all.
This is a huge webpage on how to setup ssl between your web server and twilo. It even has a php example.
http://www.twilio.com/docs/security
If you use PKCS#1 1.5 or 2.0 RSA encryption (view the standards) you will also encrypt a random padding. This means that in transit, the PIN's cannot be compared, as long as the padding is kept secret and is truly random (this is not a salt which should be made public).
As for the database, it would be a good idea to move it out of the normal operations as much as possible. Create a simple service that just checks the PIN after decryption, make sure you don't have buffer overruns etc. on that, and if possible, use a different machine and access rights than the production server. Really test this part well, as the interface is small, it should not be difficult.
If you and the phones are up to it, you might want to try ECC, but that's not for the meek. RSA encrypt normally uses a small public exponent (0x010001 is highly recommended) so it is faster than ECC for the phone. On the server (and during key creation) ECC is much faster. I would not recommend symmetric cryptography (AES/3DES) for this.
Oh, and include the public encryption key in the application (for implicit trust), don't send it over from the server. Keep the private key secret and inaccessible for anything other than the already mentioned service.
The interface you describe sounds secure to me. It's secure enough for ATMs!
Are the encrypted PINs easy to crack? Yes, there's only 10000 possible combinations and a rainbow table can be generated of all the possible encrypted values unless you salt. However that would require access to the encrypted PINs which means the attacker already has a copy of your database.
So really you need to ensure your database server is secure. There's a lot of variables that could make it insecure so it's a big question. Instead you could rely on third-party solutions like Amazon S3 or others and concentrate on coding instead of security. Let them do the hard work!
You should use good quality password salting technique to prevent against hacking passwords. Check the wikipedia article to know more about salting. Salt Article
I'm looking for a stornger scheme than just password salting-and-hashing.
I want passwords file/DB that will not compromise:
Number of users
User names
User passwords
My basic idea is to hash and salt both the usernames and the passwords, and also to add 1000's of 'trap' entries into the database (for example, random user names ending with _xxxx with random passwords ending with _yyyy which won't be valid for real users).
Of course, when someone tries to log in, I'll have to check it against all lines in the database.
Is this scheme secure?
Notes:
The users are added manually. If a user has to be removed - the login names are stored in a safe.
I'm not sure if I can protect this scheme againt brute-force methods, but I think guessing both name and password is harder
Edit:
I'm protecting against a leak of the user/password file (as well as the application that read this file). As said, I need to protect the actual number of users, as well as their identities (or anything that may disclose their identities).
Number of users seems to be the hardest datapoint to protect. You can mask this by creating large numbers of fake users with nonsense names encrypted as you describe. These can serve double duty as the traps you describe, but then you need to be able to distinguish a trap from a real user which means it is possible for an attacker to do the same if they can compromise the trap-checker.
Who are you trying to secure it against?
Do you want to secure it against someone who compromises the DB, e.g by SQL injection, or a rogue sysadmin?
Do you want to secure it against someone who compromises the OS and gains access to the files that back the database tables?
The former can be mitigated by restricting access to the table to well-reviewed stored procedures, and tough DB access controls.
The latter can be mitigated by putting DB files on an encrypted partition, though this can slow down access and/or complicate startup.
Ironically, the larger the number of users, the more likely a brute force attacer is to stumble on a valid combination - and if they know that you have a lot of users with _xxxx or _yyyy in their usernames/passwords, that may give them a cryptographical advantage.
So, I would absolutely recommend that you give your bogus users no actual privileges, so that even a succesful guess yields no rights to the system.
Secondly, you might want to think about who you're protecting against, and how - it's widely accepted that a good hash/salt combination protects against most credible attacks; adding the username to that scheme just means you're protecting against attacks that don't currently exist.
On the other hand, you're doing nothing to protect against the far more common attack vector of "username on post-it note", "password = sex", etc.
The most common way to improve on "username/password" is to require users to have something physical.
I'm currently working on basic user authentication for an app I'm putting together, and I don't have much experience with security.
This said, I understand the practice (and necessity) of salting/storing a (salted) password hash in a database as a blob, as opposed to the password (encrypted or no). I've already implemented this.
Is there anything to be gained by salting/hashing a user name and storing the hash in the database, as opposed to the username in plain-text (or encrypted)? It strikes me this would make it quite a bit harder to determine which users may access the system using the database for authentication.
Since it's vital to make it difficult for someone to crack the password for a user account, wouldn't it also make sense to increase the difficulty for determining which users are viable?
Edit: it's possible some of the language I'm using isn't 100% correct: feel free to correct :-)
Edit2: I changed one of my first points to indicate salting hashes -- thanks everyone for pointing out that I missed this :-)
Edit3: Removed wording indicating I am encrypting/decrypting a password. I'm using salted hashes and am storing that in the DB -- thanks Scotty for pointing this out.
It depends on the context
It's important to assess the sensitivity of the material you're serving. To dig deeper, I'll provide a few use cases.
Scenario 1: A social networking application
All of your user's interactions happen in the public. Their email address will be used as their username. There username is not considered private because their name appears in all their posts. The username may be searched by other users and/or email invites are enabled.
Verdict - Hashing = Bad
Scenario 2: An E-Commerce site
The user may or may not participate in public interactions (ex. commenting, reviews). Using an email address as the username is probably a bad idea because, through the use of password recovery, a compromised email account means a compromised user account on your site.
There is a lot of gray area here that is typically exploited for 'convenience.' If your site uses email as the user name, stores shipping history, and credit card numbers; a compromised email could mean a lot of identity theft troubles for your user.
In this case, using a policy where the username is not the user's email address is probably a good idea. Hashing the email adds no value.
Note: I'm looking at you Amazon.com.
Verdict: Common Practice != good practice
Scenario 3: A porn site
Make the username a pseudonym and the login name the user's email address. They may feel inclined to talk about the content and don't necessarily want their name to show up on Google's results for a smut site.
Assume the worst here. If somehow your database is hacked, the exposing of your user's identities could cause irreparable harm. Don't think this could happen to you? Take a look at this article.
Not only are their user's accounts hacked and passwords exposed but, there's a good chance a lot of those users used the same password on their email accounts. Now their info is posted anonymously on PasteBin for the whole world to see. Even worse, most of them probably don't even know this has happened yet.
By simply hashing both the username and password, they would have saved themselves and their users a whole lot of trouble.
Verdict: Definitely hash the email address whether or not it's used as the username.
Scenario 4: A bank
It should go without saying that no expense should be spared when it comes to banking/financial sites.
Security can be increased by:
Using a username other than the email address
Forcing a unique username by requiring numbers and letters
Hashing passwords
Requiring 2-point authentication (in case the user's email password is compromised)
Hashing email addresses
etc...
No expense should be spared to protect your users because, to not do so, means you're gambling with their livelihood.
Conclusion:
There is no hard and fast rule for security that applies to all sites. In some cases, the username is made public so hashing it adds no value. In others, not hashing it could cause irreparable harm. If you do end up developing a site where a username/email hash could be made useful here's a good approach.
Hash the username
Generate a unique salt for the user
Hash the password using the salt
Store the password with the salt in the database
By not hashing the username with a salt you avoid the chicken/egg problem. Unless you use a static salt for all of the usernames.
Keep in mind that a static salt for all the user accounts may be found out by reading the code. Once a static salt is found out, it'll essentially be useless when a rainbow table attack is employed. If you salt the passwords, generate a dynamic salt and store it along with the rest of the user's credentials in the database.
If you want hard/fast rules for simplicity here are a few good assumptions to remember:
Assume your database may be compromised at some point
Assume your source code will be compromised at some point
Assume your user's email will be compromised at some point
Assume your user's are dumb and use the same password for your site as they use for their email
Assume that hackers are smart/resourceful and financially driven.
If you choose to store sensitive/private data, then going the extra step may save you a PR/legal nightmare in the future.
Update:An interesting article about seed hashing just showed up on Coding Horror.
Short answer: most likely no.
Long answer: Your situation seems to lack the key "my usernames are sensitive because of ..." which raises the question: "Why? What is the specific, demonstrable problem that protecting usernames would solve?"
Without that problem, what you are describing is a common pitfall in security-related development (and really development as a whole): coming up with some idea to secure or obfuscate some part of the system, and then searching for a reason to use it. As with anything in software development, you should avoid doing anything other than exactly what is needed until a clear problem presents itself that can only be solved by using a specific tool.
Extra hint (for free!): salt your password hashes. Plain-old hashes are far less secure.
If you salted & hashed the username, you'd leave yourself with a bit of a chicken & egg problem.
If you salted & hashed the username, how would you find it in the database? You'd need to look up the user's record to find the salt you used to hash the username...
Probably not. Think of it this way - the username is the application's way of figuring out which account a user is trying to login as. The password is the application's way of figuring out whether the user is actually allowed to login as that account. In practice, this means you're going to look up a row in your accounts table using the username as an index. By encrypting the username, you're simply making it harder to find the right row.
However, if you're using the same encryption scheme to encrypt the username and password, they are pretty much equally secure - if you can break one, you can break the other. Thus, encrypting both makes it harder to lookup the user, but doesn't add any additional security.
Note: In your question you talk about decrypting your password field. You probably want to make this impossible (literally). Most people encrypt their passwords using a one-way hash function of some sort (MD5 and SHA256 are popular), along with a salt. The "one-way" part simply means that once you run something through the function, you can't use what you get out to get what you started with. However, if you start with the same input, you'll always get the same output. The salt is a secret that only your application knows (sort of like an encryption key), which is added to whatever you are encrypting, before it is run through the one-way hash. This makes it impossible to do things like match two encrypted passwords from two different sites (assuming they're using different salts).
It's not very fair to your users to store their password in plain text since everybody that has access to your database can see their passwords. You should use a salted hash.
Salt_(cryptography)
You can never properly evaluate the security of a system by looking at a single part of it in isolation. Whereabouts are you storing the key to decrypt the passwords?
Do the people that have access to the database also have access to the location you are storing the encyption key? If so you've only gained a minor improvement in security by encrypting the passwords and probably nothing much more to gain by encrypting the usernames.
If the decryption key and program using it are more secure than the database - which is pretty unusual, normally the database is in the most secure spot possible - then there would possibly be additional benefit to also encrypting the username as you'd be depriving attackers of useful information in brute force attacks.